Skia
2D Graphics Library
SkRuntimeEffect.h
Go to the documentation of this file.
1 /*
2  * Copyright 2019 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 SkRuntimeEffect_DEFINED
9 #define SkRuntimeEffect_DEFINED
10 
11 #include "include/core/SkBlender.h" // IWYU pragma: keep
12 #include "include/core/SkColorFilter.h" // IWYU pragma: keep
13 #include "include/core/SkData.h"
15 #include "include/core/SkMatrix.h"
16 #include "include/core/SkRefCnt.h"
17 #include "include/core/SkShader.h"
18 #include "include/core/SkSpan.h"
19 #include "include/core/SkString.h"
20 #include "include/core/SkTypes.h"
21 #include "include/private/SkSLSampleUsage.h"
22 #include "include/private/base/SkOnce.h"
23 #include "include/private/base/SkTemplates.h"
24 #include "include/private/base/SkTo.h"
25 #include "include/private/base/SkTypeTraits.h"
26 #include "include/sksl/SkSLDebugTrace.h"
27 #include "include/sksl/SkSLVersion.h"
28 
29 #include <cstddef>
30 #include <cstdint>
31 #include <cstring>
32 #include <memory>
33 #include <optional>
34 #include <string>
35 #include <string_view>
36 #include <utility>
37 #include <vector>
38 
39 struct SkIPoint;
40 
41 namespace SkSL {
42 class DebugTracePriv;
43 class FunctionDefinition;
44 struct Program;
45 enum class ProgramKind : int8_t;
46 struct ProgramSettings;
47 } // namespace SkSL
48 
49 namespace SkSL::RP {
50 class Program;
51 }
52 
53 /*
54  * SkRuntimeEffect supports creating custom SkShader and SkColorFilter objects using Skia's SkSL
55  * shading language.
56  *
57  * NOTE: This API is experimental and subject to change.
58  */
59 class SK_API SkRuntimeEffect : public SkRefCnt {
60 public:
61  // Reflected description of a uniform variable in the effect's SkSL
62  struct SK_API Uniform {
63  enum class Type {
64  kFloat,
65  kFloat2,
66  kFloat3,
67  kFloat4,
68  kFloat2x2,
69  kFloat3x3,
70  kFloat4x4,
71  kInt,
72  kInt2,
73  kInt3,
74  kInt4,
75  };
76 
77  enum Flags {
78  // Uniform is declared as an array. 'count' contains array length.
79  kArray_Flag = 0x1,
80 
81  // Uniform is declared with layout(color). Colors should be supplied as unpremultiplied,
82  // extended-range (unclamped) sRGB (ie SkColor4f). The uniform will be automatically
83  // transformed to unpremultiplied extended-range working-space colors.
84  kColor_Flag = 0x2,
85 
86  // When used with SkMeshSpecification, indicates that the uniform is present in the
87  // vertex shader. Not used with SkRuntimeEffect.
88  kVertex_Flag = 0x4,
89 
90  // When used with SkMeshSpecification, indicates that the uniform is present in the
91  // fragment shader. Not used with SkRuntimeEffect.
92  kFragment_Flag = 0x8,
93 
94  // This flag indicates that the SkSL uniform uses a medium-precision type
95  // (i.e., `half` instead of `float`).
96  kHalfPrecision_Flag = 0x10,
97  };
98 
99  std::string_view name;
100  size_t offset;
102  int count;
103  uint32_t flags;
104 
105  bool isArray() const { return SkToBool(this->flags & kArray_Flag); }
106  bool isColor() const { return SkToBool(this->flags & kColor_Flag); }
107  size_t sizeInBytes() const;
108  };
109 
110  // Reflected description of a uniform child (shader or colorFilter) in the effect's SkSL
111  enum class ChildType {
112  kShader,
113  kColorFilter,
114  kBlender,
115  };
116 
117  struct Child {
118  std::string_view name;
120  int index;
121  };
122 
123  class Options {
124  public:
125  // For testing purposes, disables optimization and inlining. (Normally, Runtime Effects
126  // don't run the inliner directly, but they still get an inlining pass once they are
127  // painted.)
128  bool forceUnoptimized = false;
129 
130  private:
131  friend class SkRuntimeEffect;
132  friend class SkRuntimeEffectPriv;
133 
134  // This flag allows Runtime Effects to access Skia implementation details like sk_FragCoord
135  // and functions with private identifiers (e.g. $rgb_to_hsl).
136  bool allowPrivateAccess = false;
137 
138  // TODO(skia:11209) - Replace this with a promised SkCapabilities?
139  // This flag lifts the ES2 restrictions on Runtime Effects that are gated by the
140  // `strictES2Mode` check. Be aware that the software renderer and pipeline-stage effect are
141  // still largely ES3-unaware and can still fail or crash if post-ES2 features are used.
142  // This is only intended for use by tests and certain internally created effects.
143  SkSL::Version maxVersionAllowed = SkSL::Version::k100;
144  };
145 
146  // If the effect is compiled successfully, `effect` will be non-null.
147  // Otherwise, `errorText` will contain the reason for failure.
148  struct Result {
151  };
152 
153  // MakeForColorFilter and MakeForShader verify that the SkSL code is valid for those stages of
154  // the Skia pipeline. In all of the signatures described below, color parameters and return
155  // values are flexible. They are listed as being 'vec4', but they can also be 'half4' or
156  // 'float4'. ('vec4' is an alias for 'float4').
157 
158  // We can't use a default argument for `options` due to a bug in Clang.
159  // https://bugs.llvm.org/show_bug.cgi?id=36684
160 
161  // Color filter SkSL requires an entry point that looks like:
162  // vec4 main(vec4 inColor) { ... }
165  return MakeForColorFilter(std::move(sksl), Options{});
166  }
167 
168  // Shader SkSL requires an entry point that looks like:
169  // vec4 main(vec2 inCoords) { ... }
170  static Result MakeForShader(SkString sksl, const Options&);
172  return MakeForShader(std::move(sksl), Options{});
173  }
174 
175  // Blend SkSL requires an entry point that looks like:
176  // vec4 main(vec4 srcColor, vec4 dstColor) { ... }
177  static Result MakeForBlender(SkString sksl, const Options&);
179  return MakeForBlender(std::move(sksl), Options{});
180  }
181 
182  // Object that allows passing a SkShader, SkColorFilter or SkBlender as a child
183  class SK_API ChildPtr {
184  public:
185  ChildPtr() = default;
186  ChildPtr(sk_sp<SkShader> s) : fChild(std::move(s)) {}
187  ChildPtr(sk_sp<SkColorFilter> cf) : fChild(std::move(cf)) {}
188  ChildPtr(sk_sp<SkBlender> b) : fChild(std::move(b)) {}
189 
190  // Asserts that the flattenable is either null, or one of the legal derived types
192 
193  std::optional<ChildType> type() const;
194 
195  SkShader* shader() const;
197  SkBlender* blender() const;
198  SkFlattenable* flattenable() const { return fChild.get(); }
199 
200  using sk_is_trivially_relocatable = std::true_type;
201 
202  private:
203  sk_sp<SkFlattenable> fChild;
204 
205  static_assert(::sk_is_trivially_relocatable<decltype(fChild)>::value);
206  };
207 
209  sk_sp<SkShader> children[],
210  size_t childCount,
211  const SkMatrix* localMatrix = nullptr) const;
213  SkSpan<const ChildPtr> children,
214  const SkMatrix* localMatrix = nullptr) const;
215 
218  sk_sp<SkColorFilter> children[],
219  size_t childCount) const;
221  SkSpan<const ChildPtr> children) const;
222 
224  SkSpan<const ChildPtr> children = {}) const;
225 
238  struct TracedShader {
241  };
242  static TracedShader MakeTraced(sk_sp<SkShader> shader, const SkIPoint& traceCoord);
243 
244  // Returns the SkSL source of the runtime effect shader.
245  const std::string& source() const;
246 
247  // Combined size of all 'uniform' variables. When calling makeColorFilter or makeShader,
248  // provide an SkData of this size, containing values for all of those variables.
249  size_t uniformSize() const;
250 
251  SkSpan<const Uniform> uniforms() const { return SkSpan(fUniforms); }
252  SkSpan<const Child> children() const { return SkSpan(fChildren); }
253 
254  // Returns pointer to the named uniform variable's description, or nullptr if not found
255  const Uniform* findUniform(std::string_view name) const;
256 
257  // Returns pointer to the named child's description, or nullptr if not found
258  const Child* findChild(std::string_view name) const;
259 
260  // Allows the runtime effect type to be identified.
261  bool allowShader() const { return (fFlags & kAllowShader_Flag); }
262  bool allowColorFilter() const { return (fFlags & kAllowColorFilter_Flag); }
263  bool allowBlender() const { return (fFlags & kAllowBlender_Flag); }
264 
265  static void RegisterFlattenables();
266  ~SkRuntimeEffect() override;
267 
268 private:
269  enum Flags {
270  kUsesSampleCoords_Flag = 0x001,
271  kAllowColorFilter_Flag = 0x002,
272  kAllowShader_Flag = 0x004,
273  kAllowBlender_Flag = 0x008,
274  kSamplesOutsideMain_Flag = 0x010,
275  kUsesColorTransform_Flag = 0x020,
276  kAlwaysOpaque_Flag = 0x040,
277  kAlphaUnchanged_Flag = 0x080,
278  kDisableOptimization_Flag = 0x100,
279  };
280 
281  SkRuntimeEffect(std::unique_ptr<SkSL::Program> baseProgram,
282  const Options& options,
283  const SkSL::FunctionDefinition& main,
284  std::vector<Uniform>&& uniforms,
285  std::vector<Child>&& children,
286  std::vector<SkSL::SampleUsage>&& sampleUsages,
287  uint32_t flags);
288 
289  sk_sp<SkRuntimeEffect> makeUnoptimizedClone();
290 
291  static Result MakeFromSource(SkString sksl, const Options& options, SkSL::ProgramKind kind);
292 
293  static Result MakeInternal(std::unique_ptr<SkSL::Program> program,
294  const Options& options,
295  SkSL::ProgramKind kind);
296 
297  static SkSL::ProgramSettings MakeSettings(const Options& options);
298 
299  uint32_t hash() const { return fHash; }
300  bool usesSampleCoords() const { return (fFlags & kUsesSampleCoords_Flag); }
301  bool samplesOutsideMain() const { return (fFlags & kSamplesOutsideMain_Flag); }
302  bool usesColorTransform() const { return (fFlags & kUsesColorTransform_Flag); }
303  bool alwaysOpaque() const { return (fFlags & kAlwaysOpaque_Flag); }
304  bool isAlphaUnchanged() const { return (fFlags & kAlphaUnchanged_Flag); }
305 
306  const SkSL::RP::Program* getRPProgram(SkSL::DebugTracePriv* debugTrace) const;
307 
308 #if defined(SK_GANESH)
309  friend class GrSkSLFP; // fBaseProgram, fSampleUsages
310  friend class GrGLSLSkSLFP; //
311 #endif
312 
313  friend class SkRuntimeShader; // fBaseProgram, fMain, fSampleUsages, getRPProgram()
314  friend class SkRuntimeBlender; //
315  friend class SkRuntimeColorFilter; //
316 
317  friend class SkRuntimeEffectPriv;
318 
319  uint32_t fHash;
320 
321  std::unique_ptr<SkSL::Program> fBaseProgram;
322  std::unique_ptr<SkSL::RP::Program> fRPProgram;
323  mutable SkOnce fCompileRPProgramOnce;
324  const SkSL::FunctionDefinition& fMain;
325  std::vector<Uniform> fUniforms;
326  std::vector<Child> fChildren;
327  std::vector<SkSL::SampleUsage> fSampleUsages;
328 
329  uint32_t fFlags; // Flags
330 };
331 
334 public:
335  struct BuilderUniform {
336  // Copy 'val' to this variable. No type conversion is performed - 'val' must be same
337  // size as expected by the effect. Information about the variable can be queried by
338  // looking at fVar. If the size is incorrect, no copy will be performed, and debug
339  // builds will abort. If this is the result of querying a missing variable, fVar will
340  // be nullptr, and assigning will also do nothing (and abort in debug builds).
341  template <typename T>
342  std::enable_if_t<std::is_trivially_copyable<T>::value, BuilderUniform&> operator=(
343  const T& val) {
344  if (!fVar) {
345  SkDEBUGFAIL("Assigning to missing variable");
346  } else if (sizeof(val) != fVar->sizeInBytes()) {
347  SkDEBUGFAIL("Incorrect value size");
348  } else {
349  memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
350  &val, sizeof(val));
351  }
352  return *this;
353  }
354 
356  if (!fVar) {
357  SkDEBUGFAIL("Assigning to missing variable");
358  } else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
359  SkDEBUGFAIL("Incorrect value size");
360  } else {
361  float* data = SkTAddOffset<float>(fOwner->writableUniformData(),
362  (ptrdiff_t)fVar->offset);
363  data[0] = val.get(0); data[1] = val.get(3); data[2] = val.get(6);
364  data[3] = val.get(1); data[4] = val.get(4); data[5] = val.get(7);
365  data[6] = val.get(2); data[7] = val.get(5); data[8] = val.get(8);
366  }
367  return *this;
368  }
369 
370  template <typename T>
371  bool set(const T val[], const int count) {
372  static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
373  if (!fVar) {
374  SkDEBUGFAIL("Assigning to missing variable");
375  return false;
376  } else if (sizeof(T) * count != fVar->sizeInBytes()) {
377  SkDEBUGFAIL("Incorrect value size");
378  return false;
379  } else {
380  memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
381  val, sizeof(T) * count);
382  }
383  return true;
384  }
385 
387  const SkRuntimeEffect::Uniform* fVar; // nullptr if the variable was not found
388  };
389 
390  struct BuilderChild {
391  template <typename T> BuilderChild& operator=(sk_sp<T> val) {
392  if (!fChild) {
393  SkDEBUGFAIL("Assigning to missing child");
394  } else {
395  fOwner->fChildren[(size_t)fChild->index] = std::move(val);
396  }
397  return *this;
398  }
399 
400  BuilderChild& operator=(std::nullptr_t) {
401  if (!fChild) {
402  SkDEBUGFAIL("Assigning to missing child");
403  } else {
404  fOwner->fChildren[(size_t)fChild->index] = SkRuntimeEffect::ChildPtr{};
405  }
406  return *this;
407  }
408 
410  const SkRuntimeEffect::Child* fChild; // nullptr if the child was not found
411  };
412 
413  const SkRuntimeEffect* effect() const { return fEffect.get(); }
414 
415  BuilderUniform uniform(std::string_view name) { return { this, fEffect->findUniform(name) }; }
416  BuilderChild child(std::string_view name) { return { this, fEffect->findChild(name) }; }
417 
418  // Get access to the collated uniforms and children (in the order expected by APIs like
419  // makeShader on the effect):
420  sk_sp<const SkData> uniforms() const { return fUniforms; }
421  SkSpan<const SkRuntimeEffect::ChildPtr> children() const { return fChildren; }
422 
423 protected:
426  : fEffect(std::move(effect))
427  , fUniforms(SkData::MakeZeroInitialized(fEffect->uniformSize()))
428  , fChildren(fEffect->children().size()) {}
430  : fEffect(std::move(effect))
431  , fUniforms(std::move(uniforms))
432  , fChildren(fEffect->children().size()) {}
433 
436 
439 
440 private:
441  void* writableUniformData() {
442  if (!fUniforms->unique()) {
443  fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
444  }
445  return fUniforms->writable_data();
446  }
447 
448  sk_sp<SkRuntimeEffect> fEffect;
449  sk_sp<SkData> fUniforms;
450  std::vector<SkRuntimeEffect::ChildPtr> fChildren;
451 };
452 
474 public:
476  // This is currently required by Android Framework but may go away if that dependency
477  // can be removed.
480 
481  sk_sp<SkShader> makeShader(const SkMatrix* localMatrix = nullptr) const;
482 
483 private:
485  : SkRuntimeEffectBuilder(std::move(effect), std::move(uniforms)) {}
486 
487  friend class SkRuntimeImageFilter;
488 };
489 
494 public:
497 
500 
502 };
503 
508 public:
511 
514 
516 };
517 
518 #endif // SkRuntimeEffect_DEFINED
SkBlender represents a custom blend function in the Skia pipeline.
Definition: SkBlender.h:19
ColorFilters are optional objects in the drawing pipeline.
Definition: SkColorFilter.h:35
SkData holds an immutable data buffer.
Definition: SkData.h:25
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
Create a new dataref by copying the specified data.
SkFlattenable is the base class for objects that need to be flattened into a data stream for either t...
Definition: SkFlattenable.h:28
SkMatrix holds a 3x3 matrix for transforming coordinates.
Definition: SkMatrix.h:53
SkScalar get(int index) const
Returns one matrix value.
Definition: SkMatrix.h:391
Definition: SkRefCnt.h:119
SkRuntimeBlendBuilder is a utility to simplify creation and uniform setup of runtime blenders.
Definition: SkRuntimeEffect.h:507
sk_sp< SkBlender > makeBlender() const
SkRuntimeBlendBuilder(sk_sp< SkRuntimeEffect >)
SkRuntimeBlendBuilder(const SkRuntimeBlendBuilder &)=delete
SkRuntimeBlendBuilder & operator=(const SkRuntimeBlendBuilder &)=delete
SkRuntimeColorFilterBuilder makes it easy to setup and assign uniforms to runtime color filters.
Definition: SkRuntimeEffect.h:493
SkRuntimeColorFilterBuilder(sk_sp< SkRuntimeEffect >)
SkRuntimeColorFilterBuilder(const SkRuntimeColorFilterBuilder &)=delete
SkRuntimeColorFilterBuilder & operator=(const SkRuntimeColorFilterBuilder &)=delete
sk_sp< SkColorFilter > makeColorFilter() const
Base class for SkRuntimeShaderBuilder, defined below.
Definition: SkRuntimeEffect.h:333
BuilderUniform uniform(std::string_view name)
Definition: SkRuntimeEffect.h:415
SkSpan< const SkRuntimeEffect::ChildPtr > children() const
Definition: SkRuntimeEffect.h:421
const SkRuntimeEffect * effect() const
Definition: SkRuntimeEffect.h:413
SkRuntimeEffectBuilder(sk_sp< SkRuntimeEffect > effect)
Definition: SkRuntimeEffect.h:425
BuilderChild child(std::string_view name)
Definition: SkRuntimeEffect.h:416
SkRuntimeEffectBuilder(const SkRuntimeEffectBuilder &)=default
SkRuntimeEffectBuilder(sk_sp< SkRuntimeEffect > effect, sk_sp< SkData > uniforms)
Definition: SkRuntimeEffect.h:429
SkRuntimeEffectBuilder & operator=(SkRuntimeEffectBuilder &&)=delete
sk_sp< const SkData > uniforms() const
Definition: SkRuntimeEffect.h:420
SkRuntimeEffectBuilder()=delete
SkRuntimeEffectBuilder(SkRuntimeEffectBuilder &&)=default
SkRuntimeEffectBuilder & operator=(const SkRuntimeEffectBuilder &)=delete
Definition: SkRuntimeEffect.h:183
SkBlender * blender() const
ChildPtr(sk_sp< SkFlattenable > f)
ChildPtr(sk_sp< SkBlender > b)
Definition: SkRuntimeEffect.h:188
std::optional< ChildType > type() const
SkColorFilter * colorFilter() const
ChildPtr(sk_sp< SkShader > s)
Definition: SkRuntimeEffect.h:186
SkFlattenable * flattenable() const
Definition: SkRuntimeEffect.h:198
std::true_type sk_is_trivially_relocatable
Definition: SkRuntimeEffect.h:200
SkShader * shader() const
ChildPtr(sk_sp< SkColorFilter > cf)
Definition: SkRuntimeEffect.h:187
Definition: SkRuntimeEffect.h:123
Definition: SkRuntimeEffect.h:59
size_t uniformSize() const
const Uniform * findUniform(std::string_view name) const
sk_sp< SkShader > makeShader(sk_sp< const SkData > uniforms, SkSpan< const ChildPtr > children, const SkMatrix *localMatrix=nullptr) const
static TracedShader MakeTraced(sk_sp< SkShader > shader, const SkIPoint &traceCoord)
SkSpan< const Uniform > uniforms() const
Definition: SkRuntimeEffect.h:251
static void RegisterFlattenables()
sk_sp< SkShader > makeShader(sk_sp< const SkData > uniforms, sk_sp< SkShader > children[], size_t childCount, const SkMatrix *localMatrix=nullptr) const
sk_sp< SkColorFilter > makeColorFilter(sk_sp< const SkData > uniforms) const
bool allowColorFilter() const
Definition: SkRuntimeEffect.h:262
const std::string & source() const
~SkRuntimeEffect() override
sk_sp< SkColorFilter > makeColorFilter(sk_sp< const SkData > uniforms, sk_sp< SkColorFilter > children[], size_t childCount) const
static Result MakeForColorFilter(SkString sksl, const Options &)
static Result MakeForBlender(SkString sksl, const Options &)
bool allowBlender() const
Definition: SkRuntimeEffect.h:263
sk_sp< SkBlender > makeBlender(sk_sp< const SkData > uniforms, SkSpan< const ChildPtr > children={}) const
sk_sp< SkColorFilter > makeColorFilter(sk_sp< const SkData > uniforms, SkSpan< const ChildPtr > children) const
static Result MakeForShader(SkString sksl)
Definition: SkRuntimeEffect.h:171
static Result MakeForColorFilter(SkString sksl)
Definition: SkRuntimeEffect.h:164
const Child * findChild(std::string_view name) const
bool allowShader() const
Definition: SkRuntimeEffect.h:261
static Result MakeForBlender(SkString sksl)
Definition: SkRuntimeEffect.h:178
SkSpan< const Child > children() const
Definition: SkRuntimeEffect.h:252
ChildType
Definition: SkRuntimeEffect.h:111
static Result MakeForShader(SkString sksl, const Options &)
SkRuntimeShaderBuilder is a utility to simplify creating SkShader objects from SkRuntimeEffects.
Definition: SkRuntimeEffect.h:473
SkRuntimeShaderBuilder(sk_sp< SkRuntimeEffect >)
SkRuntimeShaderBuilder(const SkRuntimeShaderBuilder &)=default
sk_sp< SkShader > makeShader(const SkMatrix *localMatrix=nullptr) const
Shaders specify the source color(s) for what is being drawn.
Definition: SkShader.h:35
Light weight class for managing strings.
Definition: SkString.h:118
Definition: SkRuntimeEffect.h:49
Definition: SkCapabilities.h:15
Definition: SkRuntimeEffect.h:390
const SkRuntimeEffect::Child * fChild
Definition: SkRuntimeEffect.h:410
BuilderChild & operator=(sk_sp< T > val)
Definition: SkRuntimeEffect.h:391
SkRuntimeEffectBuilder * fOwner
Definition: SkRuntimeEffect.h:409
BuilderChild & operator=(std::nullptr_t)
Definition: SkRuntimeEffect.h:400
Definition: SkRuntimeEffect.h:335
BuilderUniform & operator=(const SkMatrix &val)
Definition: SkRuntimeEffect.h:355
std::enable_if_t< std::is_trivially_copyable< T >::value, BuilderUniform & > operator=(const T &val)
Definition: SkRuntimeEffect.h:342
const SkRuntimeEffect::Uniform * fVar
Definition: SkRuntimeEffect.h:387
SkRuntimeEffectBuilder * fOwner
Definition: SkRuntimeEffect.h:386
bool set(const T val[], const int count)
Definition: SkRuntimeEffect.h:371
Definition: SkRuntimeEffect.h:117
ChildType type
Definition: SkRuntimeEffect.h:119
int index
Definition: SkRuntimeEffect.h:120
std::string_view name
Definition: SkRuntimeEffect.h:118
Definition: SkRuntimeEffect.h:148
sk_sp< SkRuntimeEffect > effect
Definition: SkRuntimeEffect.h:149
SkString errorText
Definition: SkRuntimeEffect.h:150
Creates a new Runtime Effect patterned after an already-existing one.
Definition: SkRuntimeEffect.h:238
sk_sp< SkShader > shader
Definition: SkRuntimeEffect.h:239
sk_sp< SkSL::DebugTrace > debugTrace
Definition: SkRuntimeEffect.h:240
Definition: SkRuntimeEffect.h:62
Type type
Definition: SkRuntimeEffect.h:101
size_t offset
Definition: SkRuntimeEffect.h:100
size_t sizeInBytes() const
Type
Definition: SkRuntimeEffect.h:63
bool isArray() const
Definition: SkRuntimeEffect.h:105
std::string_view name
Definition: SkRuntimeEffect.h:99
int count
Definition: SkRuntimeEffect.h:102
bool isColor() const
Definition: SkRuntimeEffect.h:106
uint32_t flags
Definition: SkRuntimeEffect.h:103
Flags
Definition: SkRuntimeEffect.h:77