1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2019 The Qt Company Ltd. 4 ** Contact: http://www.qt.io/licensing/ 5 ** 6 ** This file is part of the Qt Gui module 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL3$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see http://www.qt.io/terms-conditions. For further 15 ** information use the contact form at http://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 3 as published by the Free Software 20 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the 21 ** packaging of this file. Please review the following information to 22 ** ensure the GNU Lesser General Public License version 3 requirements 23 ** will be met: https://www.gnu.org/licenses/lgpl.html. 24 ** 25 ** GNU General Public License Usage 26 ** Alternatively, this file may be used under the terms of the GNU 27 ** General Public License version 2.0 or later as published by the Free 28 ** Software Foundation and appearing in the file LICENSE.GPL included in 29 ** the packaging of this file. Please review the following information to 30 ** ensure the GNU General Public License version 2.0 requirements will be 31 ** met: http://www.gnu.org/licenses/gpl-2.0.html. 32 ** 33 ** $QT_END_LICENSE$ 34 ** 35 ****************************************************************************/ 36 37 #ifndef QRHIMETAL_P_H 38 #define QRHIMETAL_P_H 39 40 // 41 // W A R N I N G 42 // ------------- 43 // 44 // This file is not part of the Qt API. It exists purely as an 45 // implementation detail. This header file may change from version to 46 // version without notice, or even be removed. 47 // 48 // We mean it. 49 // 50 51 #include "qrhimetal_p.h" 52 #include "qrhi_p_p.h" 53 #include <QWindow> 54 55 QT_BEGIN_NAMESPACE 56 57 static const int QMTL_FRAMES_IN_FLIGHT = 2; 58 59 // have to hide the ObjC stuff, this header cannot contain MTL* at all 60 struct QMetalBufferData; 61 62 struct QMetalBuffer : public QRhiBuffer 63 { 64 QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size); 65 ~QMetalBuffer(); 66 void release() override; 67 bool build() override; 68 QRhiBuffer::NativeBuffer nativeBuffer() override; 69 70 QMetalBufferData *d; 71 uint generation = 0; 72 int lastActiveFrameSlot = -1; 73 friend class QRhiMetal; 74 friend struct QMetalShaderResourceBindings; 75 }; 76 77 struct QMetalRenderBufferData; 78 79 struct QMetalRenderBuffer : public QRhiRenderBuffer 80 { 81 QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, 82 int sampleCount, QRhiRenderBuffer::Flags flags); 83 ~QMetalRenderBuffer(); 84 void release() override; 85 bool build() override; 86 QRhiTexture::Format backingFormat() const override; 87 88 QMetalRenderBufferData *d; 89 int samples = 1; 90 uint generation = 0; 91 int lastActiveFrameSlot = -1; 92 friend class QRhiMetal; 93 }; 94 95 struct QMetalTextureData; 96 97 struct QMetalTexture : public QRhiTexture 98 { 99 QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, 100 int sampleCount, Flags flags); 101 ~QMetalTexture(); 102 void release() override; 103 bool build() override; 104 bool buildFrom(NativeTexture src) override; 105 NativeTexture nativeTexture() override; 106 107 bool prepareBuild(QSize *adjustedSize = nullptr); 108 109 QMetalTextureData *d; 110 int mipLevelCount = 0; 111 int samples = 1; 112 uint generation = 0; 113 int lastActiveFrameSlot = -1; 114 friend class QRhiMetal; 115 friend struct QMetalShaderResourceBindings; 116 friend struct QMetalTextureData; 117 }; 118 119 struct QMetalSamplerData; 120 121 struct QMetalSampler : public QRhiSampler 122 { 123 QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, 124 AddressMode u, AddressMode v, AddressMode w); 125 ~QMetalSampler(); 126 void release() override; 127 bool build() override; 128 129 QMetalSamplerData *d; 130 uint generation = 0; 131 int lastActiveFrameSlot = -1; 132 friend class QRhiMetal; 133 friend struct QMetalShaderResourceBindings; 134 }; 135 136 struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor 137 { 138 QMetalRenderPassDescriptor(QRhiImplementation *rhi); 139 ~QMetalRenderPassDescriptor(); 140 void release() override; 141 bool isCompatible(const QRhiRenderPassDescriptor *other) const override; 142 143 // there is no MTLRenderPassDescriptor here as one will be created for each pass in beginPass() 144 145 // but the things needed for the render pipeline descriptor have to be provided 146 static const int MAX_COLOR_ATTACHMENTS = 8; 147 int colorAttachmentCount = 0; 148 bool hasDepthStencil = false; 149 int colorFormat[MAX_COLOR_ATTACHMENTS]; 150 int dsFormat; 151 }; 152 153 struct QMetalRenderTargetData; 154 155 struct QMetalReferenceRenderTarget : public QRhiRenderTarget 156 { 157 QMetalReferenceRenderTarget(QRhiImplementation *rhi); 158 ~QMetalReferenceRenderTarget(); 159 void release() override; 160 161 QSize pixelSize() const override; 162 float devicePixelRatio() const override; 163 int sampleCount() const override; 164 165 QMetalRenderTargetData *d; 166 }; 167 168 struct QMetalTextureRenderTarget : public QRhiTextureRenderTarget 169 { 170 QMetalTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags); 171 ~QMetalTextureRenderTarget(); 172 void release() override; 173 174 QSize pixelSize() const override; 175 float devicePixelRatio() const override; 176 int sampleCount() const override; 177 178 QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; 179 bool build() override; 180 181 QMetalRenderTargetData *d; 182 friend class QRhiMetal; 183 }; 184 185 struct QMetalShaderResourceBindings : public QRhiShaderResourceBindings 186 { 187 QMetalShaderResourceBindings(QRhiImplementation *rhi); 188 ~QMetalShaderResourceBindings(); 189 void release() override; 190 bool build() override; 191 192 QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings; 193 int maxBinding = -1; 194 195 struct BoundUniformBufferData { 196 quint64 id; 197 uint generation; 198 }; 199 struct BoundSampledTextureData { 200 int count; 201 struct { 202 quint64 texId; 203 uint texGeneration; 204 quint64 samplerId; 205 uint samplerGeneration; 206 } d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE]; 207 }; 208 struct BoundStorageImageData { 209 quint64 id; 210 uint generation; 211 }; 212 struct BoundStorageBufferData { 213 quint64 id; 214 uint generation; 215 }; 216 struct BoundResourceData { 217 union { 218 BoundUniformBufferData ubuf; 219 BoundSampledTextureData stex; 220 BoundStorageImageData simage; 221 BoundStorageBufferData sbuf; 222 }; 223 }; 224 QVarLengthArray<BoundResourceData, 8> boundResourceData; 225 226 uint generation = 0; 227 friend class QRhiMetal; 228 }; 229 230 struct QMetalGraphicsPipelineData; 231 232 struct QMetalGraphicsPipeline : public QRhiGraphicsPipeline 233 { 234 QMetalGraphicsPipeline(QRhiImplementation *rhi); 235 ~QMetalGraphicsPipeline(); 236 void release() override; 237 bool build() override; 238 239 QMetalGraphicsPipelineData *d; 240 uint generation = 0; 241 int lastActiveFrameSlot = -1; 242 friend class QRhiMetal; 243 }; 244 245 struct QMetalComputePipelineData; 246 247 struct QMetalComputePipeline : public QRhiComputePipeline 248 { 249 QMetalComputePipeline(QRhiImplementation *rhi); 250 ~QMetalComputePipeline(); 251 void release() override; 252 bool build() override; 253 254 QMetalComputePipelineData *d; 255 uint generation = 0; 256 int lastActiveFrameSlot = -1; 257 friend class QRhiMetal; 258 }; 259 260 struct QMetalCommandBufferData; 261 struct QMetalSwapChain; 262 263 struct QMetalCommandBuffer : public QRhiCommandBuffer 264 { 265 QMetalCommandBuffer(QRhiImplementation *rhi); 266 ~QMetalCommandBuffer(); 267 void release() override; 268 269 QMetalCommandBufferData *d = nullptr; 270 QRhiMetalCommandBufferNativeHandles nativeHandlesStruct; 271 272 enum PassType { 273 NoPass, 274 RenderPass, 275 ComputePass 276 }; 277 278 // per-pass (render or compute command encoder) persistent state 279 PassType recordingPass; 280 QRhiRenderTarget *currentTarget; 281 282 // per-pass (render or compute command encoder) volatile (cached) state 283 QRhiGraphicsPipeline *currentGraphicsPipeline; 284 QRhiComputePipeline *currentComputePipeline; 285 uint currentPipelineGeneration; 286 QRhiShaderResourceBindings *currentGraphicsSrb; 287 QRhiShaderResourceBindings *currentComputeSrb; 288 uint currentSrbGeneration; 289 int currentResSlot; 290 QRhiBuffer *currentIndexBuffer; 291 quint32 currentIndexOffset; 292 QRhiCommandBuffer::IndexFormat currentIndexFormat; 293 int currentCullMode; 294 int currentFrontFaceWinding; 295 QPair<float, float> currentDepthBiasValues; 296 297 const QRhiNativeHandles *nativeHandles(); 298 void resetState(); 299 void resetPerPassState(); 300 void resetPerPassCachedState(); 301 }; 302 303 struct QMetalSwapChainData; 304 305 struct QMetalSwapChain : public QRhiSwapChain 306 { 307 QMetalSwapChain(QRhiImplementation *rhi); 308 ~QMetalSwapChain(); 309 void release() override; 310 311 QRhiCommandBuffer *currentFrameCommandBuffer() override; 312 QRhiRenderTarget *currentFrameRenderTarget() override; 313 QSize surfacePixelSize() override; 314 315 QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; 316 317 bool buildOrResize() override; 318 319 void chooseFormats(); 320 321 QWindow *window = nullptr; 322 QSize pixelSize; 323 int currentFrameSlot = 0; // 0..QMTL_FRAMES_IN_FLIGHT-1 324 int frameCount = 0; 325 int samples = 1; 326 QMetalReferenceRenderTarget rtWrapper; 327 QMetalCommandBuffer cbWrapper; 328 QMetalRenderBuffer *ds = nullptr; 329 QMetalSwapChainData *d = nullptr; 330 }; 331 332 struct QRhiMetalData; 333 334 class QRhiMetal : public QRhiImplementation 335 { 336 public: 337 QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *importDevice = nullptr); 338 ~QRhiMetal(); 339 340 bool create(QRhi::Flags flags) override; 341 void destroy() override; 342 343 QRhiGraphicsPipeline *createGraphicsPipeline() override; 344 QRhiComputePipeline *createComputePipeline() override; 345 QRhiShaderResourceBindings *createShaderResourceBindings() override; 346 QRhiBuffer *createBuffer(QRhiBuffer::Type type, 347 QRhiBuffer::UsageFlags usage, 348 int size) override; 349 QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type, 350 const QSize &pixelSize, 351 int sampleCount, 352 QRhiRenderBuffer::Flags flags) override; 353 QRhiTexture *createTexture(QRhiTexture::Format format, 354 const QSize &pixelSize, 355 int sampleCount, 356 QRhiTexture::Flags flags) override; 357 QRhiSampler *createSampler(QRhiSampler::Filter magFilter, 358 QRhiSampler::Filter minFilter, 359 QRhiSampler::Filter mipmapMode, 360 QRhiSampler:: AddressMode u, 361 QRhiSampler::AddressMode v, 362 QRhiSampler::AddressMode w) override; 363 364 QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, 365 QRhiTextureRenderTarget::Flags flags) override; 366 367 QRhiSwapChain *createSwapChain() override; 368 QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override; 369 QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override; 370 QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override; 371 QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override; 372 QRhi::FrameOpResult finish() override; 373 374 void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; 375 376 void beginPass(QRhiCommandBuffer *cb, 377 QRhiRenderTarget *rt, 378 const QColor &colorClearValue, 379 const QRhiDepthStencilClearValue &depthStencilClearValue, 380 QRhiResourceUpdateBatch *resourceUpdates) override; 381 void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; 382 383 void setGraphicsPipeline(QRhiCommandBuffer *cb, 384 QRhiGraphicsPipeline *ps) override; 385 386 void setShaderResources(QRhiCommandBuffer *cb, 387 QRhiShaderResourceBindings *srb, 388 int dynamicOffsetCount, 389 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override; 390 391 void setVertexInput(QRhiCommandBuffer *cb, 392 int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, 393 QRhiBuffer *indexBuf, quint32 indexOffset, 394 QRhiCommandBuffer::IndexFormat indexFormat) override; 395 396 void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override; 397 void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override; 398 void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override; 399 void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override; 400 401 void draw(QRhiCommandBuffer *cb, quint32 vertexCount, 402 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override; 403 404 void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, 405 quint32 instanceCount, quint32 firstIndex, 406 qint32 vertexOffset, quint32 firstInstance) override; 407 408 void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override; 409 void debugMarkEnd(QRhiCommandBuffer *cb) override; 410 void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override; 411 412 void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; 413 void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; 414 void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override; 415 void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override; 416 417 const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override; 418 void beginExternal(QRhiCommandBuffer *cb) override; 419 void endExternal(QRhiCommandBuffer *cb) override; 420 421 QVector<int> supportedSampleCounts() const override; 422 int ubufAlignment() const override; 423 bool isYUpInFramebuffer() const override; 424 bool isYUpInNDC() const override; 425 bool isClipDepthZeroToOne() const override; 426 QMatrix4x4 clipSpaceCorrMatrix() const override; 427 bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override; 428 bool isFeatureSupported(QRhi::Feature feature) const override; 429 int resourceLimit(QRhi::ResourceLimit limit) const override; 430 const QRhiNativeHandles *nativeHandles() override; 431 void sendVMemStatsToProfiler() override; 432 bool makeThreadLocalNativeContextCurrent() override; 433 void releaseCachedResources() override; 434 bool isDeviceLost() const override; 435 436 void executeDeferredReleases(bool forced = false); 437 void finishActiveReadbacks(bool forced = false); 438 qsizetype subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const; 439 void enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEncPtr, 440 int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc, 441 qsizetype *curOfs); 442 void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates); 443 void executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot); 444 void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD); 445 static const int SUPPORTED_STAGES = 3; 446 void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD, 447 QMetalCommandBuffer *cbD, 448 int dynamicOffsetCount, 449 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets, 450 bool offsetOnlyChange, 451 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[SUPPORTED_STAGES]); 452 int effectiveSampleCount(int sampleCount) const; 453 454 bool importedDevice = false; 455 bool importedCmdQueue = false; 456 QMetalSwapChain *currentSwapChain = nullptr; 457 QSet<QMetalSwapChain *> swapchains; 458 QRhiMetalNativeHandles nativeHandlesStruct; 459 460 struct { 461 int maxTextureSize = 4096; 462 } caps; 463 464 QRhiMetalData *d = nullptr; 465 }; 466 467 QT_END_NAMESPACE 468 469 #endif 470