• 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_GraphicsPipelineDesc_DEFINED
9 #define skgpu_GraphicsPipelineDesc_DEFINED
10 
11 #include "include/core/SkTypes.h"
12 
13 #include "experimental/graphite/src/DrawTypes.h"
14 #include "include/private/SkTArray.h"
15 
16 namespace skgpu {
17 
18 /**
19  * GraphicsPipelineDesc represents the state needed to create a backend specific GraphicsPipeline,
20  * minus the target-specific properties that can be inferred from the DrawPass and RenderPassTask.
21  */
22 class GraphicsPipelineDesc {
23 public:
24     GraphicsPipelineDesc();
25 
26     /** Describes a vertex or instance attribute. */
27     class Attribute {
28     public:
29         constexpr Attribute() = default;
Attribute(const char * name,VertexAttribType cpuType,SLType gpuType)30         constexpr Attribute(const char* name,
31                             VertexAttribType cpuType,
32                             SLType gpuType)
33                 : fName(name), fCPUType(cpuType), fGPUType(gpuType) {
34             SkASSERT(name && gpuType != SLType::kVoid);
35         }
36         constexpr Attribute(const Attribute&) = default;
37 
38         Attribute& operator=(const Attribute&) = default;
39 
isInitialized()40         constexpr bool isInitialized() const { return fGPUType != SLType::kVoid; }
41 
name()42         constexpr const char* name() const { return fName; }
cpuType()43         constexpr VertexAttribType cpuType() const { return fCPUType; }
gpuType()44         constexpr SLType           gpuType() const { return fGPUType; }
45 
46         inline constexpr size_t size() const;
sizeAlign4()47         constexpr size_t sizeAlign4() const { return SkAlign4(this->size()); }
48 
49     private:
50         const char* fName = nullptr;
51         VertexAttribType fCPUType = VertexAttribType::kFloat;
52         SLType fGPUType = SLType::kVoid;
53     };
54 
55     class Iter {
56     public:
Iter()57         Iter() : fCurr(nullptr), fRemaining(0) {}
Iter(const Iter & iter)58         Iter(const Iter& iter) : fCurr(iter.fCurr), fRemaining(iter.fRemaining) {}
59         Iter& operator= (const Iter& iter) {
60             fCurr = iter.fCurr;
61             fRemaining = iter.fRemaining;
62             return *this;
63         }
Iter(const Attribute * attrs,int count)64         Iter(const Attribute* attrs, int count) : fCurr(attrs), fRemaining(count) {
65             this->skipUninitialized();
66         }
67 
68         bool operator!=(const Iter& that) const { return fCurr != that.fCurr; }
69         const Attribute& operator*() const { return *fCurr; }
70         void operator++() {
71             if (fRemaining) {
72                 fRemaining--;
73                 fCurr++;
74                 this->skipUninitialized();
75             }
76         }
77 
78     private:
skipUninitialized()79         void skipUninitialized() {
80             if (!fRemaining) {
81                 fCurr = nullptr;
82             } else {
83                 while (!fCurr->isInitialized()) {
84                     ++fCurr;
85                 }
86             }
87         }
88 
89         const Attribute* fCurr;
90         int fRemaining;
91     };
92 
93     class AttributeSet {
94     public:
begin()95         Iter begin() const { return Iter(fAttributes, fCount); }
end()96         Iter end() const { return Iter(); }
97 
count()98         int count() const { return fCount; }
stride()99         size_t stride() const { return fStride; }
100 
101     private:
102         friend class GraphicsPipelineDesc;
init(const Attribute * attrs,int count)103         void init(const Attribute* attrs, int count) {
104             fAttributes = attrs;
105             fRawCount = count;
106             fCount = 0;
107             fStride = 0;
108             for (int i = 0; i < count; ++i) {
109                 if (attrs[i].isInitialized()) {
110                     fCount++;
111                     fStride += attrs[i].sizeAlign4();
112                 }
113             }
114         }
115 
116         const Attribute* fAttributes = nullptr;
117         int              fRawCount = 0;
118         int              fCount = 0;
119         size_t           fStride = 0;
120     };
121 
122     // Returns this as a uint32_t array to be used as a key in the pipeline cache.
123     // TODO: Do we want to do anything here with a tuple or an SkSpan?
asKey()124     const uint32_t* asKey() const {
125         return fKey.data();
126     }
127 
128     // Gets the number of bytes in asKey(). It will be a 4-byte aligned value.
keyLength()129     uint32_t keyLength() const {
130         return fKey.size() * sizeof(uint32_t);
131     }
132 
133     bool operator==(const GraphicsPipelineDesc& that) const {
134         return this->fKey == that.fKey;
135     }
136 
137     bool operator!=(const GraphicsPipelineDesc& other) const {
138         return !(*this == other);
139     }
140 
141     // TODO: remove this once we have something real working
setTestingOnlyShaderIndex(int index)142     void setTestingOnlyShaderIndex(int index) {
143         fTestingOnlyShaderIndex = index;
144         if (fKey.count() >= 1) {
145             fKey[0] = index;
146         } else {
147             fKey.push_back(index);
148         }
149     }
testingOnlyShaderIndex()150     int testingOnlyShaderIndex() const {
151         return fTestingOnlyShaderIndex;
152     }
153 
setVertexAttributes(const Attribute * attrs,int attrCount)154     void setVertexAttributes(const Attribute* attrs, int attrCount) {
155         fVertexAttributes.init(attrs, attrCount);
156     }
setInstanceAttributes(const Attribute * attrs,int attrCount)157     void setInstanceAttributes(const Attribute* attrs, int attrCount) {
158         SkASSERT(attrCount >= 0);
159         fInstanceAttributes.init(attrs, attrCount);
160     }
161 
numVertexAttributes()162     int numVertexAttributes() const { return fVertexAttributes.fCount; }
vertexAttributes()163     const AttributeSet& vertexAttributes() const { return fVertexAttributes; }
numInstanceAttributes()164     int numInstanceAttributes() const { return fInstanceAttributes.fCount; }
instanceAttributes()165     const AttributeSet& instanceAttributes() const { return fInstanceAttributes; }
166 
hasVertexAttributes()167     bool hasVertexAttributes() const { return SkToBool(fVertexAttributes.fCount); }
hasInstanceAttributes()168     bool hasInstanceAttributes() const { return SkToBool(fInstanceAttributes.fCount); }
169 
170     /**
171      * A common practice is to populate the the vertex/instance's memory using an implicit array of
172      * structs. In this case, it is best to assert that:
173      *     stride == sizeof(struct)
174      */
vertexStride()175     size_t vertexStride() const { return fVertexAttributes.fStride; }
instanceStride()176     size_t instanceStride() const { return fInstanceAttributes.fStride; }
177 
178 private:
179     // Estimate of max expected key size
180     // TODO: flesh this out
181     inline static constexpr int kPreAllocSize = 1;
182 
183     SkSTArray<kPreAllocSize, uint32_t, true> fKey;
184 
185     int fTestingOnlyShaderIndex;
186 
187     AttributeSet fVertexAttributes;
188     AttributeSet fInstanceAttributes;
189 };
190 
191 //////////////////////////////////////////////////////////////////////////////
192 
193 /**
194  * Returns the size of the attrib type in bytes.
195  * Placed here in service of Skia dependents that build with C++11.
196  */
VertexAttribTypeSize(VertexAttribType type)197 static constexpr inline size_t VertexAttribTypeSize(VertexAttribType type) {
198     switch (type) {
199         case VertexAttribType::kFloat:
200             return sizeof(float);
201         case VertexAttribType::kFloat2:
202             return 2 * sizeof(float);
203         case VertexAttribType::kFloat3:
204             return 3 * sizeof(float);
205         case VertexAttribType::kFloat4:
206             return 4 * sizeof(float);
207         case VertexAttribType::kHalf:
208             return sizeof(uint16_t);
209         case VertexAttribType::kHalf2:
210             return 2 * sizeof(uint16_t);
211         case VertexAttribType::kHalf4:
212             return 4 * sizeof(uint16_t);
213         case VertexAttribType::kInt2:
214             return 2 * sizeof(int32_t);
215         case VertexAttribType::kInt3:
216             return 3 * sizeof(int32_t);
217         case VertexAttribType::kInt4:
218             return 4 * sizeof(int32_t);
219         case VertexAttribType::kByte:
220             return 1 * sizeof(char);
221         case VertexAttribType::kByte2:
222             return 2 * sizeof(char);
223         case VertexAttribType::kByte4:
224             return 4 * sizeof(char);
225         case VertexAttribType::kUByte:
226             return 1 * sizeof(char);
227         case VertexAttribType::kUByte2:
228             return 2 * sizeof(char);
229         case VertexAttribType::kUByte4:
230             return 4 * sizeof(char);
231         case VertexAttribType::kUByte_norm:
232             return 1 * sizeof(char);
233         case VertexAttribType::kUByte4_norm:
234             return 4 * sizeof(char);
235         case VertexAttribType::kShort2:
236             return 2 * sizeof(int16_t);
237         case VertexAttribType::kShort4:
238             return 4 * sizeof(int16_t);
239         case VertexAttribType::kUShort2: // fall through
240         case VertexAttribType::kUShort2_norm:
241             return 2 * sizeof(uint16_t);
242         case VertexAttribType::kInt:
243             return sizeof(int32_t);
244         case VertexAttribType::kUInt:
245             return sizeof(uint32_t);
246         case VertexAttribType::kUShort_norm:
247             return sizeof(uint16_t);
248         case VertexAttribType::kUShort4_norm:
249             return 4 * sizeof(uint16_t);
250     }
251     // GCC fails because SK_ABORT evaluates to non constexpr. clang and cl.exe think this is
252     // unreachable and don't complain.
253 #if defined(__clang__) || !defined(__GNUC__)
254     SK_ABORT("Unsupported type conversion");
255 #endif
256     return 0;
257 }
258 
size()259 constexpr size_t GraphicsPipelineDesc::Attribute::size() const {
260     return VertexAttribTypeSize(fCPUType);
261 }
262 
263 } // namespace skgpu
264 
265 #endif // skgpu_GraphicsPipelineDesc_DEFINED
266