blob: e8524b263b2987754dd74f3d4dd74aa6bde84d27 [file] [log] [blame]
joshualittb0a8a372014-09-23 09:50:21 -07001/*
2 * Copyright 2013 Google Inc.
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 GrGeometryProcessor_DEFINED
9#define GrGeometryProcessor_DEFINED
10
Robert Phillips787fd9d2021-03-22 14:48:09 -040011#include "src/gpu/GrColor.h"
12#include "src/gpu/GrNonAtomicRef.h"
13#include "src/gpu/GrProcessor.h"
14#include "src/gpu/GrShaderVar.h"
15#include "src/gpu/GrSwizzle.h"
16
Robert Phillips787fd9d2021-03-22 14:48:09 -040017class GrGLSLUniformHandler;
18
joshualitt9b989322014-12-15 14:16:27 -080019/**
Robert Phillips787fd9d2021-03-22 14:48:09 -040020 * The GrGeometryProcessor represents some kind of geometric primitive. This includes the shape
21 * of the primitive and the inherent color of the primitive. The GrGeometryProcessor is
22 * responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through
23 * optimization, Ganesh may decide a different color, no color, and / or no coverage are required
24 * from the GrGeometryProcessor, so the GrGeometryProcessor must be able to support this
25 * functionality.
26 *
27 * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
28 * GrGeometryProcessor. These loops run on the CPU and to determine known properties of the final
29 * color and coverage inputs to the GrXferProcessor in order to perform optimizations that preserve
30 * correctness. The GrDrawOp seeds these loops with initial color and coverage, in its
31 * getProcessorAnalysisInputs implementation. These seed values are processed by the
32 * subsequent stages of the rendering pipeline and the output is then fed back into the GrDrawOp
33 * in the applyPipelineOptimizations call, where the op can use the information to inform
34 * decisions about GrGeometryProcessor creation.
Robert Phillips7cd0bfe2019-11-20 16:08:10 -050035 *
36 * Note that all derived classes should hide their constructors and provide a Make factory
Robert Phillips787fd9d2021-03-22 14:48:09 -040037 * function that takes an arena (except for Tesselation-specific classes). This is because
38 * geometry processors can be created in either the record-time or flush-time arenas which
39 * define their lifetimes (i.e., a DDLs life time in the first case and a single flush in
40 * the second case).
41 *
42 * TODO: This class does not really need to be ref counted. Instances should be allocated using
43 * GrOpFlushState's arena and destroyed when the arena is torn down.
joshualitt9b989322014-12-15 14:16:27 -080044 */
Robert Phillips787fd9d2021-03-22 14:48:09 -040045class GrGeometryProcessor : public GrProcessor, public GrNonAtomicRef<GrGeometryProcessor> {
joshualitt9b989322014-12-15 14:16:27 -080046public:
Brian Salomonf95940b2021-08-09 15:56:24 -040047 /**
48 * Any GrGeometryProcessor is capable of creating a subclass of ProgramImpl. The ProgramImpl
49 * emits the shader code that implements the GrGeometryProcessor, is attached to the generated
50 * backend API pipeline/program and used to extract uniform data from GrGeometryProcessor
51 * instances.
52 */
53 class ProgramImpl;
54
Robert Phillips787fd9d2021-03-22 14:48:09 -040055 class TextureSampler;
56
57 /** Describes a vertex or instance attribute. */
58 class Attribute {
59 public:
60 constexpr Attribute() = default;
61 constexpr Attribute(const char* name,
62 GrVertexAttribType cpuType,
63 GrSLType gpuType)
64 : fName(name), fCPUType(cpuType), fGPUType(gpuType) {
65 SkASSERT(name && gpuType != kVoid_GrSLType);
66 }
67 constexpr Attribute(const Attribute&) = default;
68
69 Attribute& operator=(const Attribute&) = default;
70
71 constexpr bool isInitialized() const { return fGPUType != kVoid_GrSLType; }
72
73 constexpr const char* name() const { return fName; }
74 constexpr GrVertexAttribType cpuType() const { return fCPUType; }
75 constexpr GrSLType gpuType() const { return fGPUType; }
76
77 inline constexpr size_t size() const;
78 constexpr size_t sizeAlign4() const { return SkAlign4(this->size()); }
79
80 GrShaderVar asShaderVar() const {
81 return {fName, fGPUType, GrShaderVar::TypeModifier::In};
82 }
83
84 private:
85 const char* fName = nullptr;
86 GrVertexAttribType fCPUType = kFloat_GrVertexAttribType;
87 GrSLType fGPUType = kVoid_GrSLType;
88 };
89
90 class Iter {
91 public:
92 Iter() : fCurr(nullptr), fRemaining(0) {}
93 Iter(const Iter& iter) : fCurr(iter.fCurr), fRemaining(iter.fRemaining) {}
94 Iter& operator= (const Iter& iter) {
95 fCurr = iter.fCurr;
96 fRemaining = iter.fRemaining;
97 return *this;
98 }
99 Iter(const Attribute* attrs, int count) : fCurr(attrs), fRemaining(count) {
100 this->skipUninitialized();
101 }
102
103 bool operator!=(const Iter& that) const { return fCurr != that.fCurr; }
104 const Attribute& operator*() const { return *fCurr; }
105 void operator++() {
106 if (fRemaining) {
107 fRemaining--;
108 fCurr++;
109 this->skipUninitialized();
110 }
111 }
112
113 private:
114 void skipUninitialized() {
115 if (!fRemaining) {
116 fCurr = nullptr;
117 } else {
118 while (!fCurr->isInitialized()) {
119 ++fCurr;
120 }
121 }
122 }
123
124 const Attribute* fCurr;
125 int fRemaining;
126 };
127
128 class AttributeSet {
129 public:
130 Iter begin() const { return Iter(fAttributes, fCount); }
131 Iter end() const { return Iter(); }
132
133 int count() const { return fCount; }
134 size_t stride() const { return fStride; }
135
136 private:
137 friend class GrGeometryProcessor;
138
139 void init(const Attribute* attrs, int count) {
140 fAttributes = attrs;
141 fRawCount = count;
142 fCount = 0;
143 fStride = 0;
144 for (int i = 0; i < count; ++i) {
145 if (attrs[i].isInitialized()) {
146 fCount++;
147 fStride += attrs[i].sizeAlign4();
148 }
149 }
150 }
151
152 const Attribute* fAttributes = nullptr;
153 int fRawCount = 0;
154 int fCount = 0;
155 size_t fStride = 0;
156 };
157
158 GrGeometryProcessor(ClassID);
159
160 int numTextureSamplers() const { return fTextureSamplerCnt; }
161 const TextureSampler& textureSampler(int index) const;
162 int numVertexAttributes() const { return fVertexAttributes.fCount; }
163 const AttributeSet& vertexAttributes() const { return fVertexAttributes; }
164 int numInstanceAttributes() const { return fInstanceAttributes.fCount; }
165 const AttributeSet& instanceAttributes() const { return fInstanceAttributes; }
166
167 bool hasVertexAttributes() const { return SkToBool(fVertexAttributes.fCount); }
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 */
175 size_t vertexStride() const { return fVertexAttributes.fStride; }
176 size_t instanceStride() const { return fInstanceAttributes.fStride; }
177
178 bool willUseTessellationShaders() const {
179 return fShaders & (kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag);
180 }
181
182 bool willUseGeoShader() const {
183 return fShaders & kGeometry_GrShaderFlag;
184 }
185
186 /**
187 * Computes a key for the transforms owned by an FP based on the shader code that will be
188 * emitted by the primitive processor to implement them.
189 */
190 static uint32_t ComputeCoordTransformsKey(const GrFragmentProcessor& fp);
191
192 static constexpr int kCoordTransformKeyBits = 4;
193
194 /**
Brian Salomon13b28732021-08-06 15:33:58 -0400195 * Adds a key on the GrProcessorKeyBuilder that reflects any variety in the code that the
196 * geometry processor subclass can emit.
Robert Phillips787fd9d2021-03-22 14:48:09 -0400197 */
Brian Salomon13b28732021-08-06 15:33:58 -0400198 virtual void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
Robert Phillips787fd9d2021-03-22 14:48:09 -0400199
200 void getAttributeKey(GrProcessorKeyBuilder* b) const {
201 // Ensure that our CPU and GPU type fields fit together in a 32-bit value, and we never
202 // collide with the "uninitialized" value.
203 static_assert(kGrVertexAttribTypeCount < (1 << 8), "");
204 static_assert(kGrSLTypeCount < (1 << 8), "");
205
206 auto add_attributes = [=](const Attribute* attrs, int attrCount) {
207 for (int i = 0; i < attrCount; ++i) {
208 const Attribute& attr = attrs[i];
209 b->appendComment(attr.isInitialized() ? attr.name() : "unusedAttr");
210 b->addBits(8, attr.isInitialized() ? attr.cpuType() : 0xff, "attrType");
211 b->addBits(8, attr.isInitialized() ? attr.gpuType() : 0xff, "attrGpuType");
212 }
213 };
214 b->add32(fVertexAttributes.fRawCount, "numVertexAttributes");
215 add_attributes(fVertexAttributes.fAttributes, fVertexAttributes.fRawCount);
216 b->add32(fInstanceAttributes.fRawCount, "numInstanceAttributes");
217 add_attributes(fInstanceAttributes.fAttributes, fInstanceAttributes.fRawCount);
218 }
219
Brian Salomonf95940b2021-08-09 15:56:24 -0400220 /**
221 * Returns a new instance of the appropriate implementation class for the given
222 * GrGeometryProcessor.
223 */
224 virtual std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const = 0;
Robert Phillips787fd9d2021-03-22 14:48:09 -0400225
joshualittb0a8a372014-09-23 09:50:21 -0700226protected:
Brian Osman2715bf52019-12-06 14:38:47 -0500227 // GPs that need to use either float or ubyte colors can just call this to get a correctly
Brian Osmanc906d252018-12-04 11:17:46 -0500228 // configured Attribute struct
229 static Attribute MakeColorAttribute(const char* name, bool wideColor) {
230 return { name,
Brian Osman2715bf52019-12-06 14:38:47 -0500231 wideColor ? kFloat4_GrVertexAttribType : kUByte4_norm_GrVertexAttribType,
Brian Osmanc906d252018-12-04 11:17:46 -0500232 kHalf4_GrSLType };
233 }
234
Robert Phillips787fd9d2021-03-22 14:48:09 -0400235 void setVertexAttributes(const Attribute* attrs, int attrCount) {
236 fVertexAttributes.init(attrs, attrCount);
237 }
238 void setInstanceAttributes(const Attribute* attrs, int attrCount) {
239 SkASSERT(attrCount >= 0);
240 fInstanceAttributes.init(attrs, attrCount);
241 }
242 void setWillUseTessellationShaders() {
243 fShaders |= kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag;
244 }
245 void setWillUseGeoShader() { fShaders |= kGeometry_GrShaderFlag; }
246 void setTextureSamplerCnt(int cnt) {
247 SkASSERT(cnt >= 0);
248 fTextureSamplerCnt = cnt;
249 }
250
251 /**
252 * Helper for implementing onTextureSampler(). E.g.:
253 * return IthTexureSampler(i, fMyFirstSampler, fMySecondSampler, fMyThirdSampler);
254 */
255 template <typename... Args>
256 static const TextureSampler& IthTextureSampler(int i, const TextureSampler& samp0,
257 const Args&... samps) {
258 return (0 == i) ? samp0 : IthTextureSampler(i - 1, samps...);
259 }
260 inline static const TextureSampler& IthTextureSampler(int i);
261
joshualittb0a8a372014-09-23 09:50:21 -0700262private:
Robert Phillips787fd9d2021-03-22 14:48:09 -0400263 virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); }
264
265 GrShaderFlags fShaders = kVertex_GrShaderFlag | kFragment_GrShaderFlag;
266
267 AttributeSet fVertexAttributes;
268 AttributeSet fInstanceAttributes;
269
270 int fTextureSamplerCnt = 0;
271 using INHERITED = GrProcessor;
joshualittb0a8a372014-09-23 09:50:21 -0700272};
joshualitt56995b52014-12-11 15:44:02 -0800273
Robert Phillips787fd9d2021-03-22 14:48:09 -0400274//////////////////////////////////////////////////////////////////////////////
275
276/**
277 * Used to capture the properties of the GrTextureProxies required/expected by a primitiveProcessor
278 * along with an associated GrSamplerState. The actual proxies used are stored in either the
279 * fixed or dynamic state arrays. TextureSamplers don't perform any coord manipulation to account
280 * for texture origin.
281 */
282class GrGeometryProcessor::TextureSampler {
283public:
284 TextureSampler() = default;
285
286 TextureSampler(GrSamplerState, const GrBackendFormat&, const GrSwizzle&);
287
288 TextureSampler(const TextureSampler&) = delete;
289 TextureSampler& operator=(const TextureSampler&) = delete;
290
291 void reset(GrSamplerState, const GrBackendFormat&, const GrSwizzle&);
292
293 const GrBackendFormat& backendFormat() const { return fBackendFormat; }
294 GrTextureType textureType() const { return fBackendFormat.textureType(); }
295
296 GrSamplerState samplerState() const { return fSamplerState; }
297 const GrSwizzle& swizzle() const { return fSwizzle; }
298
299 bool isInitialized() const { return fIsInitialized; }
300
301private:
302 GrSamplerState fSamplerState;
303 GrBackendFormat fBackendFormat;
304 GrSwizzle fSwizzle;
305 bool fIsInitialized = false;
306};
307
308const GrGeometryProcessor::TextureSampler& GrGeometryProcessor::IthTextureSampler(int i) {
309 SK_ABORT("Illegal texture sampler index");
310 static const TextureSampler kBogus;
311 return kBogus;
312}
313
314//////////////////////////////////////////////////////////////////////////////
315
316/**
317 * Returns the size of the attrib type in bytes.
318 * This was moved from include/private/GrTypesPriv.h in service of Skia dependents that build
319 * with C++11.
320 */
321static constexpr inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {
322 switch (type) {
323 case kFloat_GrVertexAttribType:
324 return sizeof(float);
325 case kFloat2_GrVertexAttribType:
326 return 2 * sizeof(float);
327 case kFloat3_GrVertexAttribType:
328 return 3 * sizeof(float);
329 case kFloat4_GrVertexAttribType:
330 return 4 * sizeof(float);
331 case kHalf_GrVertexAttribType:
332 return sizeof(uint16_t);
333 case kHalf2_GrVertexAttribType:
334 return 2 * sizeof(uint16_t);
335 case kHalf4_GrVertexAttribType:
336 return 4 * sizeof(uint16_t);
337 case kInt2_GrVertexAttribType:
338 return 2 * sizeof(int32_t);
339 case kInt3_GrVertexAttribType:
340 return 3 * sizeof(int32_t);
341 case kInt4_GrVertexAttribType:
342 return 4 * sizeof(int32_t);
343 case kByte_GrVertexAttribType:
344 return 1 * sizeof(char);
345 case kByte2_GrVertexAttribType:
346 return 2 * sizeof(char);
347 case kByte4_GrVertexAttribType:
348 return 4 * sizeof(char);
349 case kUByte_GrVertexAttribType:
350 return 1 * sizeof(char);
351 case kUByte2_GrVertexAttribType:
352 return 2 * sizeof(char);
353 case kUByte4_GrVertexAttribType:
354 return 4 * sizeof(char);
355 case kUByte_norm_GrVertexAttribType:
356 return 1 * sizeof(char);
357 case kUByte4_norm_GrVertexAttribType:
358 return 4 * sizeof(char);
359 case kShort2_GrVertexAttribType:
360 return 2 * sizeof(int16_t);
361 case kShort4_GrVertexAttribType:
362 return 4 * sizeof(int16_t);
363 case kUShort2_GrVertexAttribType: // fall through
364 case kUShort2_norm_GrVertexAttribType:
365 return 2 * sizeof(uint16_t);
366 case kInt_GrVertexAttribType:
367 return sizeof(int32_t);
368 case kUint_GrVertexAttribType:
369 return sizeof(uint32_t);
370 case kUShort_norm_GrVertexAttribType:
371 return sizeof(uint16_t);
372 case kUShort4_norm_GrVertexAttribType:
373 return 4 * sizeof(uint16_t);
374 }
375 // GCC fails because SK_ABORT evaluates to non constexpr. clang and cl.exe think this is
376 // unreachable and don't complain.
377#if defined(__clang__) || !defined(__GNUC__)
378 SK_ABORT("Unsupported type conversion");
379#endif
380 return 0;
381}
382
383constexpr size_t GrGeometryProcessor::Attribute::size() const {
384 return GrVertexAttribTypeSize(fCPUType);
385}
386
joshualittb0a8a372014-09-23 09:50:21 -0700387#endif