| /**************************************************************************** |
| ** |
| ** Copyright (C) 2019 The Qt Company Ltd. |
| ** Contact: http://www.qt.io/licensing/ |
| ** |
| ** This file is part of the Qt Gui module |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL3$ |
| ** 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 http://www.qt.io/terms-conditions. For further |
| ** information use the contact form at http://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPLv3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or later as published by the Free |
| ** Software Foundation and appearing in the file LICENSE.GPL included in |
| ** the packaging of this file. Please review the following information to |
| ** ensure the GNU General Public License version 2.0 requirements will be |
| ** met: http://www.gnu.org/licenses/gpl-2.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_p.h" |
| #include "qrhi_p_p.h" |
| #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; |
| QRhiBuffer::NativeBuffer nativeBuffer() override; |
| |
| QMetalBufferData *d; |
| uint generation = 0; |
| int lastActiveFrameSlot = -1; |
| friend class QRhiMetal; |
| friend struct QMetalShaderResourceBindings; |
| }; |
| |
| struct QMetalRenderBufferData; |
| |
| struct QMetalRenderBuffer : public QRhiRenderBuffer |
| { |
| QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, |
| int sampleCount, QRhiRenderBuffer::Flags flags); |
| ~QMetalRenderBuffer(); |
| void release() override; |
| bool build() override; |
| QRhiTexture::Format backingFormat() const override; |
| |
| QMetalRenderBufferData *d; |
| int samples = 1; |
| uint generation = 0; |
| int lastActiveFrameSlot = -1; |
| friend class QRhiMetal; |
| }; |
| |
| struct QMetalTextureData; |
| |
| struct QMetalTexture : public QRhiTexture |
| { |
| QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, |
| int sampleCount, Flags flags); |
| ~QMetalTexture(); |
| void release() override; |
| bool build() override; |
| bool buildFrom(NativeTexture src) override; |
| NativeTexture nativeTexture() override; |
| |
| bool prepareBuild(QSize *adjustedSize = nullptr); |
| |
| QMetalTextureData *d; |
| int mipLevelCount = 0; |
| int samples = 1; |
| uint generation = 0; |
| int lastActiveFrameSlot = -1; |
| friend class QRhiMetal; |
| friend struct QMetalShaderResourceBindings; |
| friend struct QMetalTextureData; |
| }; |
| |
| struct QMetalSamplerData; |
| |
| struct QMetalSampler : public QRhiSampler |
| { |
| QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, |
| AddressMode u, AddressMode v, AddressMode w); |
| ~QMetalSampler(); |
| void release() override; |
| bool build() override; |
| |
| QMetalSamplerData *d; |
| uint generation = 0; |
| int lastActiveFrameSlot = -1; |
| friend class QRhiMetal; |
| friend struct QMetalShaderResourceBindings; |
| }; |
| |
| struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor |
| { |
| QMetalRenderPassDescriptor(QRhiImplementation *rhi); |
| ~QMetalRenderPassDescriptor(); |
| void release() override; |
| bool isCompatible(const QRhiRenderPassDescriptor *other) const override; |
| |
| // there is no MTLRenderPassDescriptor here as one will be created for each pass in beginPass() |
| |
| // but the things needed for the render pipeline descriptor have to be provided |
| static const int MAX_COLOR_ATTACHMENTS = 8; |
| int colorAttachmentCount = 0; |
| bool hasDepthStencil = false; |
| int colorFormat[MAX_COLOR_ATTACHMENTS]; |
| int dsFormat; |
| }; |
| |
| struct QMetalRenderTargetData; |
| |
| struct QMetalReferenceRenderTarget : public QRhiRenderTarget |
| { |
| QMetalReferenceRenderTarget(QRhiImplementation *rhi); |
| ~QMetalReferenceRenderTarget(); |
| void release() override; |
| |
| QSize pixelSize() const override; |
| float devicePixelRatio() const override; |
| int sampleCount() const override; |
| |
| QMetalRenderTargetData *d; |
| }; |
| |
| struct QMetalTextureRenderTarget : public QRhiTextureRenderTarget |
| { |
| QMetalTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags); |
| ~QMetalTextureRenderTarget(); |
| void release() override; |
| |
| QSize pixelSize() const override; |
| float devicePixelRatio() const override; |
| int sampleCount() const override; |
| |
| QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; |
| bool build() override; |
| |
| QMetalRenderTargetData *d; |
| friend class QRhiMetal; |
| }; |
| |
| struct QMetalShaderResourceBindings : public QRhiShaderResourceBindings |
| { |
| QMetalShaderResourceBindings(QRhiImplementation *rhi); |
| ~QMetalShaderResourceBindings(); |
| void release() override; |
| bool build() override; |
| |
| QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings; |
| int maxBinding = -1; |
| |
| struct BoundUniformBufferData { |
| quint64 id; |
| uint generation; |
| }; |
| struct BoundSampledTextureData { |
| int count; |
| struct { |
| quint64 texId; |
| uint texGeneration; |
| quint64 samplerId; |
| uint samplerGeneration; |
| } d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE]; |
| }; |
| struct BoundStorageImageData { |
| quint64 id; |
| uint generation; |
| }; |
| struct BoundStorageBufferData { |
| quint64 id; |
| uint generation; |
| }; |
| struct BoundResourceData { |
| union { |
| BoundUniformBufferData ubuf; |
| BoundSampledTextureData stex; |
| BoundStorageImageData simage; |
| BoundStorageBufferData sbuf; |
| }; |
| }; |
| QVarLengthArray<BoundResourceData, 8> boundResourceData; |
| |
| uint generation = 0; |
| friend class QRhiMetal; |
| }; |
| |
| struct QMetalGraphicsPipelineData; |
| |
| struct QMetalGraphicsPipeline : public QRhiGraphicsPipeline |
| { |
| QMetalGraphicsPipeline(QRhiImplementation *rhi); |
| ~QMetalGraphicsPipeline(); |
| void release() override; |
| bool build() override; |
| |
| QMetalGraphicsPipelineData *d; |
| uint generation = 0; |
| int lastActiveFrameSlot = -1; |
| friend class QRhiMetal; |
| }; |
| |
| struct QMetalComputePipelineData; |
| |
| struct QMetalComputePipeline : public QRhiComputePipeline |
| { |
| QMetalComputePipeline(QRhiImplementation *rhi); |
| ~QMetalComputePipeline(); |
| void release() override; |
| bool build() override; |
| |
| QMetalComputePipelineData *d; |
| uint generation = 0; |
| int lastActiveFrameSlot = -1; |
| friend class QRhiMetal; |
| }; |
| |
| struct QMetalCommandBufferData; |
| struct QMetalSwapChain; |
| |
| struct QMetalCommandBuffer : public QRhiCommandBuffer |
| { |
| QMetalCommandBuffer(QRhiImplementation *rhi); |
| ~QMetalCommandBuffer(); |
| void release() override; |
| |
| QMetalCommandBufferData *d = nullptr; |
| QRhiMetalCommandBufferNativeHandles nativeHandlesStruct; |
| |
| enum PassType { |
| NoPass, |
| RenderPass, |
| ComputePass |
| }; |
| |
| // per-pass (render or compute command encoder) persistent state |
| PassType recordingPass; |
| QRhiRenderTarget *currentTarget; |
| |
| // per-pass (render or compute command encoder) volatile (cached) state |
| QRhiGraphicsPipeline *currentGraphicsPipeline; |
| QRhiComputePipeline *currentComputePipeline; |
| uint currentPipelineGeneration; |
| QRhiShaderResourceBindings *currentGraphicsSrb; |
| QRhiShaderResourceBindings *currentComputeSrb; |
| uint currentSrbGeneration; |
| int currentResSlot; |
| QRhiBuffer *currentIndexBuffer; |
| quint32 currentIndexOffset; |
| QRhiCommandBuffer::IndexFormat currentIndexFormat; |
| int currentCullMode; |
| int currentFrontFaceWinding; |
| QPair<float, float> currentDepthBiasValues; |
| |
| const QRhiNativeHandles *nativeHandles(); |
| void resetState(); |
| void resetPerPassState(); |
| void resetPerPassCachedState(); |
| }; |
| |
| struct QMetalSwapChainData; |
| |
| struct QMetalSwapChain : public QRhiSwapChain |
| { |
| QMetalSwapChain(QRhiImplementation *rhi); |
| ~QMetalSwapChain(); |
| void release() override; |
| |
| QRhiCommandBuffer *currentFrameCommandBuffer() override; |
| QRhiRenderTarget *currentFrameRenderTarget() override; |
| QSize surfacePixelSize() override; |
| |
| QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; |
| |
| bool buildOrResize() override; |
| |
| void chooseFormats(); |
| |
| QWindow *window = nullptr; |
| QSize pixelSize; |
| int currentFrameSlot = 0; // 0..QMTL_FRAMES_IN_FLIGHT-1 |
| int frameCount = 0; |
| int samples = 1; |
| QMetalReferenceRenderTarget rtWrapper; |
| QMetalCommandBuffer cbWrapper; |
| QMetalRenderBuffer *ds = nullptr; |
| QMetalSwapChainData *d = nullptr; |
| }; |
| |
| struct QRhiMetalData; |
| |
| class QRhiMetal : public QRhiImplementation |
| { |
| public: |
| QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *importDevice = nullptr); |
| ~QRhiMetal(); |
| |
| bool create(QRhi::Flags flags) override; |
| void destroy() override; |
| |
| QRhiGraphicsPipeline *createGraphicsPipeline() override; |
| QRhiComputePipeline *createComputePipeline() 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::Flags flags) override; |
| QRhiTexture *createTexture(QRhiTexture::Format format, |
| const QSize &pixelSize, |
| int sampleCount, |
| 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, QRhi::BeginFrameFlags flags) override; |
| QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override; |
| QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override; |
| QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override; |
| QRhi::FrameOpResult finish() override; |
| |
| void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; |
| |
| void beginPass(QRhiCommandBuffer *cb, |
| QRhiRenderTarget *rt, |
| const QColor &colorClearValue, |
| const QRhiDepthStencilClearValue &depthStencilClearValue, |
| QRhiResourceUpdateBatch *resourceUpdates) override; |
| void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; |
| |
| void setGraphicsPipeline(QRhiCommandBuffer *cb, |
| QRhiGraphicsPipeline *ps) override; |
| |
| void setShaderResources(QRhiCommandBuffer *cb, |
| QRhiShaderResourceBindings *srb, |
| int dynamicOffsetCount, |
| const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override; |
| |
| void setVertexInput(QRhiCommandBuffer *cb, |
| int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, |
| QRhiBuffer *indexBuf, quint32 indexOffset, |
| QRhiCommandBuffer::IndexFormat indexFormat) override; |
| |
| void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override; |
| void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override; |
| void setBlendConstants(QRhiCommandBuffer *cb, const QColor &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; |
| |
| void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override; |
| void debugMarkEnd(QRhiCommandBuffer *cb) override; |
| void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override; |
| |
| void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; |
| void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; |
| void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override; |
| void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override; |
| |
| const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override; |
| void beginExternal(QRhiCommandBuffer *cb) override; |
| void endExternal(QRhiCommandBuffer *cb) override; |
| |
| QVector<int> supportedSampleCounts() const override; |
| int ubufAlignment() const override; |
| bool isYUpInFramebuffer() const override; |
| bool isYUpInNDC() const override; |
| bool isClipDepthZeroToOne() const override; |
| QMatrix4x4 clipSpaceCorrMatrix() const override; |
| bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override; |
| bool isFeatureSupported(QRhi::Feature feature) const override; |
| int resourceLimit(QRhi::ResourceLimit limit) const override; |
| const QRhiNativeHandles *nativeHandles() override; |
| void sendVMemStatsToProfiler() override; |
| bool makeThreadLocalNativeContextCurrent() override; |
| void releaseCachedResources() override; |
| bool isDeviceLost() const override; |
| |
| void executeDeferredReleases(bool forced = false); |
| void finishActiveReadbacks(bool forced = false); |
| qsizetype subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const; |
| void enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEncPtr, |
| int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc, |
| qsizetype *curOfs); |
| void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates); |
| void executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot); |
| void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD); |
| static const int SUPPORTED_STAGES = 3; |
| void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD, |
| QMetalCommandBuffer *cbD, |
| int dynamicOffsetCount, |
| const QRhiCommandBuffer::DynamicOffset *dynamicOffsets, |
| bool offsetOnlyChange, |
| const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[SUPPORTED_STAGES]); |
| int effectiveSampleCount(int sampleCount) const; |
| |
| bool importedDevice = false; |
| bool importedCmdQueue = false; |
| QMetalSwapChain *currentSwapChain = nullptr; |
| QSet<QMetalSwapChain *> swapchains; |
| QRhiMetalNativeHandles nativeHandlesStruct; |
| |
| struct { |
| int maxTextureSize = 4096; |
| } caps; |
| |
| QRhiMetalData *d = nullptr; |
| }; |
| |
| QT_END_NAMESPACE |
| |
| #endif |