1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#ifndef GrMtlCaps_DEFINED
9cb93a386Sopenharmony_ci#define GrMtlCaps_DEFINED
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "include/private/SkTDArray.h"
12cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h"
13cb93a386Sopenharmony_ci#include "src/gpu/mtl/GrMtlAttachment.h"
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_ci#import <Metal/Metal.h>
16cb93a386Sopenharmony_ci
17cb93a386Sopenharmony_ciclass GrShaderCaps;
18cb93a386Sopenharmony_ciclass GrMtlRenderTarget;
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ci/**
21cb93a386Sopenharmony_ci * Stores some capabilities of a Mtl backend.
22cb93a386Sopenharmony_ci */
23cb93a386Sopenharmony_ciclass GrMtlCaps : public GrCaps {
24cb93a386Sopenharmony_cipublic:
25cb93a386Sopenharmony_ci    GrMtlCaps(const GrContextOptions& contextOptions, id<MTLDevice> device);
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_ci    bool isFormatSRGB(const GrBackendFormat&) const override;
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci    bool isFormatTexturable(const GrBackendFormat&, GrTextureType) const override;
30cb93a386Sopenharmony_ci    bool isFormatTexturable(MTLPixelFormat) const;
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci    bool isFormatCopyable(const GrBackendFormat&) const override { return true; }
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci    bool isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
35cb93a386Sopenharmony_ci                                       int sampleCount = 1) const override;
36cb93a386Sopenharmony_ci    bool isFormatRenderable(const GrBackendFormat& format, int sampleCount) const override;
37cb93a386Sopenharmony_ci    bool isFormatRenderable(MTLPixelFormat, int sampleCount) const;
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ci    int getRenderTargetSampleCount(int requestedCount, const GrBackendFormat&) const override;
40cb93a386Sopenharmony_ci    int getRenderTargetSampleCount(int requestedCount, MTLPixelFormat) const;
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ci    int maxRenderTargetSampleCount(const GrBackendFormat&) const override;
43cb93a386Sopenharmony_ci    int maxRenderTargetSampleCount(MTLPixelFormat) const;
44cb93a386Sopenharmony_ci
45cb93a386Sopenharmony_ci    SupportedWrite supportedWritePixelsColorType(GrColorType surfaceColorType,
46cb93a386Sopenharmony_ci                                                 const GrBackendFormat& surfaceFormat,
47cb93a386Sopenharmony_ci                                                 GrColorType srcColorType) const override;
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override;
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ci    DstCopyRestrictions getDstCopyRestrictions(const GrRenderTargetProxy* src,
52cb93a386Sopenharmony_ci                                               GrColorType ct) const override;
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ci    /**
55cb93a386Sopenharmony_ci     * Returns both a supported and most prefered stencil format to use in draws.
56cb93a386Sopenharmony_ci     */
57cb93a386Sopenharmony_ci    MTLPixelFormat preferredStencilFormat() const {
58cb93a386Sopenharmony_ci        return fPreferredStencilFormat;
59cb93a386Sopenharmony_ci    }
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_ci    bool canCopyAsBlit(MTLPixelFormat dstFormat, int dstSampleCount,
62cb93a386Sopenharmony_ci                       MTLPixelFormat srcFormat, int srcSampleCount,
63cb93a386Sopenharmony_ci                       const SkIRect& srcRect, const SkIPoint& dstPoint,
64cb93a386Sopenharmony_ci                       bool areDstSrcSameObj) const;
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci    bool canCopyAsResolve(MTLPixelFormat dstFormat, int dstSampleCount,
67cb93a386Sopenharmony_ci                          MTLPixelFormat srcFormat, int srcSampleCount,
68cb93a386Sopenharmony_ci                          bool srcIsRenderTarget, const SkISize srcDimensions,
69cb93a386Sopenharmony_ci                          const SkIRect& srcRect,
70cb93a386Sopenharmony_ci                          const SkIPoint& dstPoint,
71cb93a386Sopenharmony_ci                          bool areDstSrcSameObj) const;
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci    GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci    MTLPixelFormat getFormatFromColorType(GrColorType colorType) const {
76cb93a386Sopenharmony_ci        int idx = static_cast<int>(colorType);
77cb93a386Sopenharmony_ci        return fColorTypeToFormatTable[idx];
78cb93a386Sopenharmony_ci    }
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_ci    GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override;
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_ci    uint64_t computeFormatKey(const GrBackendFormat&) const override;
83cb93a386Sopenharmony_ci
84cb93a386Sopenharmony_ci    GrProgramDesc makeDesc(GrRenderTarget*,
85cb93a386Sopenharmony_ci                           const GrProgramInfo&,
86cb93a386Sopenharmony_ci                           ProgramDescOverrideFlags) const override;
87cb93a386Sopenharmony_ci    MTLPixelFormat getStencilPixelFormat(const GrProgramDesc& desc);
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci    bool isMac() const { return fGPUFamily == GPUFamily::kMac; }
90cb93a386Sopenharmony_ci    bool isApple() const { return fGPUFamily == GPUFamily::kApple; }
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ci    size_t getMinBufferAlignment() const { return this->isMac() ? 4 : 1; }
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_ci    // if true, MTLStoreActionStoreAndMultiplesampleResolve is available
95cb93a386Sopenharmony_ci    bool storeAndMultisampleResolveSupport() const { return fStoreAndMultisampleResolveSupport; }
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ci    // If true when doing MSAA draws, we will prefer to discard the MSAA attachment on load
98cb93a386Sopenharmony_ci    // and stores. The use of this feature for specific draws depends on the render target having a
99cb93a386Sopenharmony_ci    // resolve attachment, and if we need to load previous data the resolve attachment must
100cb93a386Sopenharmony_ci    // be readable in a shader. Otherwise we will just write out and store the MSAA attachment
101cb93a386Sopenharmony_ci    // like normal.
102cb93a386Sopenharmony_ci    bool preferDiscardableMSAAAttachment() const { return fPreferDiscardableMSAAAttachment; }
103cb93a386Sopenharmony_ci    bool renderTargetSupportsDiscardableMSAA(const GrMtlRenderTarget*) const;
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ci#if GR_TEST_UTILS
106cb93a386Sopenharmony_ci    std::vector<TestFormatColorTypeCombination> getTestingCombinations() const override;
107cb93a386Sopenharmony_ci#endif
108cb93a386Sopenharmony_ci    void onDumpJSON(SkJSONWriter*) const override;
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_ciprivate:
111cb93a386Sopenharmony_ci    void initGPUFamily(id<MTLDevice> device);
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_ci    void initStencilFormat(id<MTLDevice> device);
114cb93a386Sopenharmony_ci
115cb93a386Sopenharmony_ci    void initGrCaps(id<MTLDevice> device);
116cb93a386Sopenharmony_ci    void initShaderCaps();
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci    void applyDriverCorrectnessWorkarounds(const GrContextOptions&, const id<MTLDevice>);
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_ci    void initFormatTable();
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ci    bool onSurfaceSupportsWritePixels(const GrSurface*) const override;
123cb93a386Sopenharmony_ci    bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
124cb93a386Sopenharmony_ci                          const SkIRect& srcRect, const SkIPoint& dstPoint) const override;
125cb93a386Sopenharmony_ci    GrBackendFormat onGetDefaultBackendFormat(GrColorType) const override;
126cb93a386Sopenharmony_ci    bool onAreColorTypeAndFormatCompatible(GrColorType, const GrBackendFormat&) const override;
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_ci    SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&,
129cb93a386Sopenharmony_ci                                                 GrColorType) const override;
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ci    GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci    // ColorTypeInfo for a specific format
134cb93a386Sopenharmony_ci    struct ColorTypeInfo {
135cb93a386Sopenharmony_ci        GrColorType fColorType = GrColorType::kUnknown;
136cb93a386Sopenharmony_ci        enum {
137cb93a386Sopenharmony_ci            kUploadData_Flag = 0x1,
138cb93a386Sopenharmony_ci            // Does Ganesh itself support rendering to this colorType & format pair. Renderability
139cb93a386Sopenharmony_ci            // still additionally depends on if the format itself is renderable.
140cb93a386Sopenharmony_ci            kRenderable_Flag = 0x2,
141cb93a386Sopenharmony_ci        };
142cb93a386Sopenharmony_ci        uint32_t fFlags = 0;
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ci        GrSwizzle fReadSwizzle;
145cb93a386Sopenharmony_ci        GrSwizzle fWriteSwizzle;
146cb93a386Sopenharmony_ci    };
147cb93a386Sopenharmony_ci
148cb93a386Sopenharmony_ci    struct FormatInfo {
149cb93a386Sopenharmony_ci        uint32_t colorTypeFlags(GrColorType colorType) const {
150cb93a386Sopenharmony_ci            for (int i = 0; i < fColorTypeInfoCount; ++i) {
151cb93a386Sopenharmony_ci                if (fColorTypeInfos[i].fColorType == colorType) {
152cb93a386Sopenharmony_ci                    return fColorTypeInfos[i].fFlags;
153cb93a386Sopenharmony_ci                }
154cb93a386Sopenharmony_ci            }
155cb93a386Sopenharmony_ci            return 0;
156cb93a386Sopenharmony_ci        }
157cb93a386Sopenharmony_ci
158cb93a386Sopenharmony_ci        enum {
159cb93a386Sopenharmony_ci            kTexturable_Flag  = 0x1,
160cb93a386Sopenharmony_ci            kRenderable_Flag  = 0x2, // Color attachment and blendable
161cb93a386Sopenharmony_ci            kMSAA_Flag        = 0x4,
162cb93a386Sopenharmony_ci            kResolve_Flag     = 0x8,
163cb93a386Sopenharmony_ci        };
164cb93a386Sopenharmony_ci        static const uint16_t kAllFlags = kTexturable_Flag | kRenderable_Flag |
165cb93a386Sopenharmony_ci                                          kMSAA_Flag | kResolve_Flag;
166cb93a386Sopenharmony_ci
167cb93a386Sopenharmony_ci        uint16_t fFlags = 0;
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ci        std::unique_ptr<ColorTypeInfo[]> fColorTypeInfos;
170cb93a386Sopenharmony_ci        int fColorTypeInfoCount = 0;
171cb93a386Sopenharmony_ci    };
172cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_IOS
173cb93a386Sopenharmony_ci    inline static constexpr size_t kNumMtlFormats = 17;
174cb93a386Sopenharmony_ci#else
175cb93a386Sopenharmony_ci    inline static constexpr size_t kNumMtlFormats = 16;
176cb93a386Sopenharmony_ci#endif
177cb93a386Sopenharmony_ci    static size_t GetFormatIndex(MTLPixelFormat);
178cb93a386Sopenharmony_ci    FormatInfo fFormatTable[kNumMtlFormats];
179cb93a386Sopenharmony_ci
180cb93a386Sopenharmony_ci    const FormatInfo& getFormatInfo(const MTLPixelFormat pixelFormat) const {
181cb93a386Sopenharmony_ci        size_t index = GetFormatIndex(pixelFormat);
182cb93a386Sopenharmony_ci        return fFormatTable[index];
183cb93a386Sopenharmony_ci    }
184cb93a386Sopenharmony_ci
185cb93a386Sopenharmony_ci    MTLPixelFormat fColorTypeToFormatTable[kGrColorTypeCnt];
186cb93a386Sopenharmony_ci    void setColorType(GrColorType, std::initializer_list<MTLPixelFormat> formats);
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_ci    enum class GPUFamily {
189cb93a386Sopenharmony_ci        kMac,
190cb93a386Sopenharmony_ci        kApple,
191cb93a386Sopenharmony_ci    };
192cb93a386Sopenharmony_ci    bool getGPUFamily(id<MTLDevice> device, GPUFamily* gpuFamily, int* group);
193cb93a386Sopenharmony_ci    bool getGPUFamilyFromFeatureSet(id<MTLDevice> device, GrMtlCaps::GPUFamily* gpuFamily,
194cb93a386Sopenharmony_ci                                    int* group);
195cb93a386Sopenharmony_ci
196cb93a386Sopenharmony_ci    GPUFamily fGPUFamily;
197cb93a386Sopenharmony_ci    int fFamilyGroup;
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_ci    SkTDArray<int> fSampleCounts;
200cb93a386Sopenharmony_ci
201cb93a386Sopenharmony_ci    MTLPixelFormat fPreferredStencilFormat;
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_ci    bool fStoreAndMultisampleResolveSupport : 1;
204cb93a386Sopenharmony_ci    bool fPreferDiscardableMSAAAttachment : 1;
205cb93a386Sopenharmony_ci
206cb93a386Sopenharmony_ci    using INHERITED = GrCaps;
207cb93a386Sopenharmony_ci};
208cb93a386Sopenharmony_ci
209cb93a386Sopenharmony_ci#endif
210