• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef skgpu_graphite_ResourceTypes_DEFINED
9 #define skgpu_graphite_ResourceTypes_DEFINED
10 
11 #include "include/core/SkSamplingOptions.h"
12 #include "include/core/SkSpan.h"
13 #include "include/core/SkTileMode.h"
14 #include "include/gpu/graphite/GraphiteTypes.h"
15 #include "include/private/base/SkTo.h"
16 #include "src/base/SkEnumBitMask.h"
17 #include "src/base/SkMathPriv.h"
18 
19 namespace skgpu::graphite {
20 
21 class Buffer;
22 
23 // This declaration of the DepthStencilFlags' SkEnumBitMask ops is here bc, internally, we use
24 // DepthStencilFlags as bit fields but, externally (i.e., from the GraphiteTypes view), we want
25 // it to appear as just an enum class.
26 SK_MAKE_BITMASK_OPS(DepthStencilFlags)
27 
28 /**
29  * The strategy that a renderpass and/or pipeline use to access the current dst pixel when blending.
30  */
31 enum class DstReadStrategy : uint8_t {
32     kNoneRequired,
33     kTextureCopy,
34     kTextureSample,
35     kReadFromInput,
36     kFramebufferFetch,
37 
38     kLast = kFramebufferFetch
39 };
40 inline static constexpr int kDstReadStrategyCount = (int)(DstReadStrategy::kLast) + 1;
41 
42 /**
43  * This enum is used to specify the load operation to be used when a RenderPass begins execution.
44  */
45 enum class LoadOp : uint8_t {
46     kLoad,
47     kClear,
48     kDiscard,
49 
50     kLast = kDiscard
51 };
52 inline static constexpr int kLoadOpCount = (int)(LoadOp::kLast) + 1;
53 
54 /**
55  * This enum is used to specify the store operation to be used when a RenderPass ends execution.
56  */
57 enum class StoreOp : uint8_t {
58     kStore,
59     kDiscard,
60 
61     kLast = kDiscard
62 };
63 inline static constexpr int kStoreOpCount = (int)(StoreOp::kLast) + 1;
64 
65 /**
66  * What a GPU buffer will be used for
67  */
68 enum class BufferType : int {
69     kVertex,
70     kIndex,
71     kXferCpuToGpu,
72     kXferGpuToCpu,
73     kUniform,
74     kStorage,
75     kQuery,
76 
77     // GPU-only buffer types
78     kIndirect,
79     kVertexStorage,
80     kIndexStorage,
81 
82     kLast = kIndexStorage,
83 };
84 static const int kBufferTypeCount = static_cast<int>(BufferType::kLast) + 1;
85 
86 /**
87  * Data layout requirements on host-shareable buffer contents.
88  */
89 enum class Layout : uint8_t {
90     kInvalid = 0,
91     kStd140,
92     kStd430,
93     kMetal,
94 };
95 
LayoutString(Layout layout)96 static constexpr const char* LayoutString(Layout layout) {
97     switch(layout) {
98         case Layout::kStd140:  return "std140";
99         case Layout::kStd430:  return "std430";
100         case Layout::kMetal:   return "metal";
101         case Layout::kInvalid: return "invalid";
102     }
103     SkUNREACHABLE;
104 }
105 
106 /**
107  * Indicates the intended access pattern over resource memory. This is used to select the most
108  * efficient memory type during resource creation based on the capabilities of the platform.
109  *
110  * This is only a hint and the actual memory type will be determined based on the resource type and
111  * backend capabilities.
112  */
113 enum class AccessPattern : uint8_t {
114     // GPU-only memory does not need to support reads/writes from the CPU. GPU-private memory will
115     // be preferred if the backend supports an efficient private memory type.
116     kGpuOnly,
117 
118     // The resource needs to be CPU visible, e.g. for read-back or as a copy/upload source.
119     kHostVisible,
120 };
121 
122 /**
123  * Determines whether the contents of a GPU buffer sub-allocation gets cleared to 0 before being
124  * used in a GPU command submission.
125  */
126 enum class ClearBuffer : bool {
127     kNo = false,
128     kYes = true,
129 };
130 
131 /**
132  * Must the contents of the Resource be preserved af a render pass or can a more efficient
133  * representation be chosen when supported by hardware.
134  */
135 enum class Discardable : bool {
136     kNo = false,
137     kYes = true
138 };
139 
140 enum class Ownership : uint8_t {
141     kOwned,
142     kWrapped,
143 };
144 
145 /** Uniquely identifies the type of resource that is cached with a GraphiteResourceKey. */
146 using ResourceType = uint32_t;
147 
148 /**
149  * Can the resource be held by multiple users at the same time?
150  * For example, stencil buffers, pipelines, etc.
151  */
152 enum class Shareable : uint8_t {
153     kNo,      // The resource is visible in the ResourceCache once all its usage refs are dropped
154     kScratch, // The resource is visible to other Recorders, but acts like kNo within a Recording
155     kYes,     // The resource is always visible in the ResourceCache
156 };
157 
158 /*
159  * Struct that can be passed into bind buffer calls on the CommandBuffer. The ownership of the
160  * buffer and its usage in command submission must be tracked by the caller (e.g. as with
161  * buffers created by DrawBufferManager).
162  */
163 struct BindBufferInfo {
164     const Buffer* fBuffer = nullptr;
165     uint32_t fOffset = 0;
166     uint32_t fSize = 0;
167 
168     operator bool() const { return SkToBool(fBuffer); }
169 
170     bool operator==(const BindBufferInfo& o) const {
171         return fBuffer == o.fBuffer && (!fBuffer || (fOffset == o.fOffset && fSize == o.fSize));
172     }
173     bool operator!=(const BindBufferInfo& o) const { return !(*this == o); }
174 };
175 
176 struct ImmutableSamplerInfo {
177     // If the sampler requires YCbCr conversion, backends can place that information here.
178     // In order to fit within SamplerDesc's uint32 desc field, backends can only utilize up to
179     // kMaxNumConversionInfoBits bits.
180     uint32_t fNonFormatYcbcrConversionInfo = 0;
181     // fFormat represents known OR external format numerical representation.
182     uint64_t fFormat = 0;
183 };
184 
185 
186 /**
187  * Struct used to describe how a Texture/TextureProxy/TextureProxyView is sampled.
188  */
189 struct SamplerDesc {
190     static_assert(kSkTileModeCount <= 4 && kSkFilterModeCount <= 2 && kSkMipmapModeCount <= 4);
191 
SamplerDescSamplerDesc192     constexpr SamplerDesc(const SkSamplingOptions& samplingOptions, SkTileMode tileMode)
193             : SamplerDesc(samplingOptions, {tileMode, tileMode}) {}
194 
195     constexpr SamplerDesc(const SkSamplingOptions& samplingOptions,
196                 const std::pair<SkTileMode, SkTileMode> tileModes,
197                 const ImmutableSamplerInfo info = {})
198             : fDesc((static_cast<int>(tileModes.first)            << kTileModeXShift           ) |
199                     (static_cast<int>(tileModes.second)           << kTileModeYShift           ) |
200                     (static_cast<int>(samplingOptions.filter)     << kFilterModeShift          ) |
201                     (static_cast<int>(samplingOptions.mipmap)     << kMipmapModeShift          ) |
202                     (info.fNonFormatYcbcrConversionInfo           << kImmutableSamplerInfoShift) )
203             , fFormat(info.fFormat)
204             , fExternalFormatMostSignificantBits(info.fFormat >> 32) {
205 
206         // Cubic sampling is handled in a shader, with the actual texture sampled by with NN,
207         // but that is what a cubic SkSamplingOptions is set to if you ignore 'cubic', which let's
208         // us simplify how we construct SamplerDec's from the options passed to high-level draws.
209         SkASSERT(!samplingOptions.useCubic || (samplingOptions.filter == SkFilterMode::kNearest &&
210                                                samplingOptions.mipmap == SkMipmapMode::kNone));
211 
212         // TODO: Add aniso value when used.
213 
214         // Assert that fYcbcrConversionInfo does not exceed kMaxNumConversionInfoBits such that
215         // the conversion information can fit within an uint32.
216         SkASSERT(info.fNonFormatYcbcrConversionInfo >> kMaxNumConversionInfoBits == 0);
217     }
218     constexpr SamplerDesc() = default;
219     constexpr SamplerDesc(const SamplerDesc&) = default;
220 
221     bool operator==(const SamplerDesc& o) const {
222         return o.fDesc == fDesc && o.fFormat == fFormat &&
223                o.fExternalFormatMostSignificantBits == fExternalFormatMostSignificantBits;
224     }
225 
226     bool operator!=(const SamplerDesc& o) const { return !(*this == o); }
227 
tileModeXSamplerDesc228     SkTileMode tileModeX()          const { return static_cast<SkTileMode>((fDesc >> 0) & 0b11); }
tileModeYSamplerDesc229     SkTileMode tileModeY()          const { return static_cast<SkTileMode>((fDesc >> 2) & 0b11); }
descSamplerDesc230     uint32_t   desc()               const { return fDesc;                                        }
formatSamplerDesc231     uint32_t   format()             const { return fFormat;                                      }
externalFormatMSBsSamplerDesc232     uint32_t   externalFormatMSBs() const { return fExternalFormatMostSignificantBits;           }
isImmutableSamplerDesc233     bool       isImmutable()        const { return (fDesc >> kImmutableSamplerInfoShift) != 0;   }
usesExternalFormatSamplerDesc234     bool       usesExternalFormat() const { return (fDesc >> kImmutableSamplerInfoShift) & 0b1;  }
235 
236     // NOTE: returns the HW sampling options to use, so a bicubic SkSamplingOptions will become
237     // nearest-neighbor sampling in HW.
samplingOptionsSamplerDesc238     SkSamplingOptions samplingOptions() const {
239         // TODO: Add support for anisotropic filtering
240         SkFilterMode filter = static_cast<SkFilterMode>((fDesc >> 4) & 0b01);
241         SkMipmapMode mipmap = static_cast<SkMipmapMode>((fDesc >> 5) & 0b11);
242         return SkSamplingOptions(filter, mipmap);
243     }
244 
immutableSamplerInfoSamplerDesc245     ImmutableSamplerInfo immutableSamplerInfo() const {
246         return {this->desc() >> kImmutableSamplerInfoShift,
247                 ((uint64_t) this->externalFormatMSBs() << 32) | (uint64_t) this->format()};
248     }
249 
asSpanSamplerDesc250     SkSpan<const uint32_t> asSpan() const {
251         // Span length depends upon whether the sampler is immutable and if it uses a known format
252         return {&fDesc, 1 + this->isImmutable() + this->usesExternalFormat()};
253     }
254 
255     // These are public such that backends can bitshift data in order to determine whatever
256     // sampler qualities they need from fDesc.
257     static constexpr int kNumTileModeBits   = SkNextLog2_portable(int(SkTileMode::kLastTileMode)+1);
258     static constexpr int kNumFilterModeBits = SkNextLog2_portable(int(SkFilterMode::kLast)+1);
259     static constexpr int kNumMipmapModeBits = SkNextLog2_portable(int(SkMipmapMode::kLast)+1);
260     static constexpr int kMaxNumConversionInfoBits =
261             32 - kNumFilterModeBits - kNumMipmapModeBits - kNumTileModeBits;
262 
263     static constexpr int kTileModeXShift            = 0;
264     static constexpr int kTileModeYShift            = kTileModeXShift  + kNumTileModeBits;
265     static constexpr int kFilterModeShift           = kTileModeYShift  + kNumTileModeBits;
266     static constexpr int kMipmapModeShift           = kFilterModeShift + kNumFilterModeBits;
267     static constexpr int kImmutableSamplerInfoShift = kMipmapModeShift + kNumMipmapModeBits;
268 
269     // Only relevant when using immutable samplers. Otherwise, can be ignored. The number of uint32s
270     // required to represent all relevant sampler desc information depends upon whether we are using
271     // a known or external format.
272     static constexpr int kInt32sNeededKnownFormat = 2;
273     static constexpr int kInt32sNeededExternalFormat = 3;
274 
275 private:
276     // Note: The order of these member attributes matters to keep unique object representation
277     // such that SkGoodHash can be used to hash SamplerDesc objects.
278     uint32_t fDesc = 0;
279 
280     // Data fields populated by backend Caps which store texture format information (needed for
281     // YCbCr sampling). Only relevant when using immutable samplers. Otherwise, can be ignored.
282     // Known formats only require a uint32, but external formats can be up to a uint64. We store
283     // this as two separate uint32s such that has_unique_object_representation can be true, allowing
284     // this structure to be easily hashed using SkGoodHash. So, external formats can be represented
285     // with (fExternalFormatMostSignificantBits << 32) | fFormat.
286     uint32_t fFormat = 0;
287     uint32_t fExternalFormatMostSignificantBits = 0;
288 };
289 
290 };  // namespace skgpu::graphite
291 
292 #endif // skgpu_graphite_ResourceTypes_DEFINED
293