Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Static Public Attributes | List of all members
SkSL::Swizzle Class Referencefinal

#include <SkSLSwizzle.h>

Inheritance diagram for SkSL::Swizzle:
SkSL::Expression SkSL::IRNode SkSL::Poolable

Public Types

using Component = SwizzleComponent::Type
 
- Public Types inherited from SkSL::Expression
enum class  ComparisonResult { kUnknown = -1 , kNotEqual , kEqual }
 
using Kind = ExpressionKind
 

Public Member Functions

 Swizzle (const Context &context, Position pos, std::unique_ptr< Expression > base, const ComponentArray &components)
 
std::unique_ptr< Expression > & base ()
 
const std::unique_ptr< Expression > & base () const
 
const ComponentArraycomponents () const
 
std::unique_ptr< Expressionclone (Position pos) const override
 
std::string description (OperatorPrecedence) const override
 
- Public Member Functions inherited from SkSL::Expression
 Expression (Position pos, Kind kind, const Type *type)
 
Kind kind () const
 
virtual const Typetype () const
 
bool isAnyConstructor () const
 
bool isIntLiteral () const
 
bool isFloatLiteral () const
 
bool isBoolLiteral () const
 
AnyConstructorasAnyConstructor ()
 
const AnyConstructorasAnyConstructor () const
 
bool isIncomplete (const Context &context) const
 
virtual ComparisonResult compareConstant (const Expression &other) const
 
CoercionCost coercionCost (const Type &target) const
 
virtual bool supportsConstantValues () const
 
virtual std::optional< double > getConstantValue (int n) const
 
std::unique_ptr< Expressionclone () const
 
std::string description () const final
 
- Public Member Functions inherited from SkSL::IRNode
virtual ~IRNode ()
 
 IRNode (const IRNode &)=delete
 
IRNodeoperator= (const IRNode &)=delete
 
Position position () const
 
void setPosition (Position p)
 
template<typename T >
bool is () const
 
template<typename T >
const Tas () const
 
template<typename T >
Tas ()
 

Static Public Member Functions

static std::unique_ptr< ExpressionConvert (const Context &context, Position pos, Position maskPos, std::unique_ptr< Expression > base, ComponentArray inComponents)
 
static std::unique_ptr< ExpressionConvert (const Context &context, Position pos, Position maskPos, std::unique_ptr< Expression > base, std::string_view maskString)
 
static std::unique_ptr< ExpressionMake (const Context &context, Position pos, std::unique_ptr< Expression > expr, ComponentArray inComponents)
 
static std::string MaskString (const ComponentArray &inComponents)
 
- Static Public Member Functions inherited from SkSL::Poolable
static void * operator new (const size_t size)
 
static void operator delete (void *ptr)
 

Static Public Attributes

static constexpr Kind kIRNodeKind = Kind::kSwizzle
 

Additional Inherited Members

- Public Attributes inherited from SkSL::IRNode
Position fPosition
 
- Protected Member Functions inherited from SkSL::IRNode
 IRNode (Position position, int kind)
 
- Protected Attributes inherited from SkSL::IRNode
int fKind
 

Detailed Description

Represents a vector swizzle operation such as 'float3(1, 2, 3).zyx'.

Definition at line 45 of file SkSLSwizzle.h.

Member Typedef Documentation

◆ Component

Definition at line 49 of file SkSLSwizzle.h.

Constructor & Destructor Documentation

◆ Swizzle()

SkSL::Swizzle::Swizzle ( const Context context,
Position  pos,
std::unique_ptr< Expression base,
const ComponentArray components 
)
inline

Definition at line 51 of file SkSLSwizzle.h.

53 : INHERITED(pos, kIRNodeKind,
54 &base->type().componentType().toCompound(context, components.size(), 1))
55 , fBase(std::move(base))
56 , fComponents(components) {
57 SkASSERT(this->components().size() >= 1 && this->components().size() <= 4);
58 }
SkPoint pos
#define SkASSERT(cond)
Definition SkAssert.h:116
static constexpr Kind kIRNodeKind
Definition SkSLSwizzle.h:47
const ComponentArray & components() const
Definition SkSLSwizzle.h:90
int size() const
Definition SkTArray.h:416
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259

Member Function Documentation

◆ base() [1/2]

std::unique_ptr< Expression > & SkSL::Swizzle::base ( )
inline

Definition at line 82 of file SkSLSwizzle.h.

82 {
83 return fBase;
84 }

◆ base() [2/2]

const std::unique_ptr< Expression > & SkSL::Swizzle::base ( ) const
inline

Definition at line 86 of file SkSLSwizzle.h.

86 {
87 return fBase;
88 }

◆ clone()

std::unique_ptr< Expression > SkSL::Swizzle::clone ( Position  pos) const
inlineoverridevirtual

Implements SkSL::Expression.

Definition at line 94 of file SkSLSwizzle.h.

94 {
95 return std::unique_ptr<Expression>(new Swizzle(pos, &this->type(), this->base()->clone(),
96 this->components()));
97 }
virtual const Type & type() const
std::unique_ptr< Expression > clone() const
Swizzle(const Context &context, Position pos, std::unique_ptr< Expression > base, const ComponentArray &components)
Definition SkSLSwizzle.h:51
std::unique_ptr< Expression > & base()
Definition SkSLSwizzle.h:82

◆ components()

const ComponentArray & SkSL::Swizzle::components ( ) const
inline

Definition at line 90 of file SkSLSwizzle.h.

90 {
91 return fComponents;
92 }

◆ Convert() [1/2]

std::unique_ptr< Expression > SkSL::Swizzle::Convert ( const Context context,
Position  pos,
Position  maskPos,
std::unique_ptr< Expression base,
ComponentArray  inComponents 
)
static

Definition at line 287 of file SkSLSwizzle.cpp.

291 {
292 if (inComponents.size() > 4) {
293 context.fErrors->error(Position::Range(maskPos.startOffset() + 4,
294 maskPos.endOffset()),
295 "too many components in swizzle mask");
296 return nullptr;
297 }
298
299 if (!validate_swizzle_domain(inComponents)) {
300 context.fErrors->error(maskPos, "invalid swizzle mask '" + MaskString(inComponents) + "'");
301 return nullptr;
302 }
303
304 const Type& baseType = base->type().scalarTypeForLiteral();
305
306 if (!baseType.isVector() && !baseType.isScalar()) {
307 context.fErrors->error(pos, "cannot swizzle value of type '" +
308 baseType.displayName() + "'");
309 return nullptr;
310 }
311
312 ComponentArray maskComponents;
313 bool foundXYZW = false;
314 for (int i = 0; i < inComponents.size(); ++i) {
315 switch (inComponents[i]) {
318 // Skip over constant fields for now.
319 break;
324 foundXYZW = true;
325 maskComponents.push_back(SwizzleComponent::X);
326 break;
331 foundXYZW = true;
332 if (baseType.columns() >= 2) {
333 maskComponents.push_back(SwizzleComponent::Y);
334 break;
335 }
336 [[fallthrough]];
341 foundXYZW = true;
342 if (baseType.columns() >= 3) {
343 maskComponents.push_back(SwizzleComponent::Z);
344 break;
345 }
346 [[fallthrough]];
351 foundXYZW = true;
352 if (baseType.columns() >= 4) {
353 maskComponents.push_back(SwizzleComponent::W);
354 break;
355 }
356 [[fallthrough]];
357 default:
358 // The swizzle component references a field that doesn't exist in the base type.
359 context.fErrors->error(Position::Range(maskPos.startOffset() + i,
360 maskPos.startOffset() + i + 1),
361 String::printf("invalid swizzle component '%c'",
362 mask_char(inComponents[i])));
363 return nullptr;
364 }
365 }
366
367 if (!foundXYZW) {
368 context.fErrors->error(maskPos, "swizzle must refer to base expression");
369 return nullptr;
370 }
371
372 // Coerce literals in expressions such as `(12345).xxx` to their actual type.
373 base = baseType.coerceExpression(std::move(base), context);
374 if (!base) {
375 return nullptr;
376 }
377
378 // First, we need a vector expression that is the non-constant portion of the swizzle, packed:
379 // scalar.xxx -> type3(scalar)
380 // scalar.x0x0 -> type2(scalar)
381 // vector.zyx -> vector.zyx
382 // vector.x0y0 -> vector.xy
383 std::unique_ptr<Expression> expr = Swizzle::Make(context, pos, std::move(base), maskComponents);
384
385 // If we have processed the entire swizzle, we're done.
386 if (maskComponents.size() == inComponents.size()) {
387 return expr;
388 }
389
390 // Now we create a constructor that has the correct number of elements for the final swizzle,
391 // with all fields at the start. It's not finished yet; constants we need will be added below.
392 // scalar.x0x0 -> type4(type2(x), ...)
393 // vector.y111 -> type4(vector.y, ...)
394 // vector.z10x -> type4(vector.zx, ...)
395 //
396 // The constructor will have at most three arguments: { base expr, constant 0, constant 1 }
397 ExpressionArray constructorArgs;
398 constructorArgs.reserve_exact(3);
399 constructorArgs.push_back(std::move(expr));
400
401 // Apply another swizzle to shuffle the constants into the correct place. Any constant values we
402 // need are also tacked on to the end of the constructor.
403 // scalar.x0x0 -> type4(type2(x), 0).xyxy
404 // vector.y111 -> type2(vector.y, 1).xyyy
405 // vector.z10x -> type4(vector.zx, 1, 0).xzwy
406 const Type* scalarType = &baseType.componentType();
407 ComponentArray swizzleComponents;
408 int maskFieldIdx = 0;
409 int constantFieldIdx = maskComponents.size();
410 int constantZeroIdx = -1, constantOneIdx = -1;
411
412 for (int i = 0; i < inComponents.size(); i++) {
413 switch (inComponents[i]) {
415 if (constantZeroIdx == -1) {
416 // Synthesize a '0' argument at the end of the constructor.
417 constructorArgs.push_back(Literal::Make(pos, /*value=*/0, scalarType));
418 constantZeroIdx = constantFieldIdx++;
419 }
420 swizzleComponents.push_back(constantZeroIdx);
421 break;
423 if (constantOneIdx == -1) {
424 // Synthesize a '1' argument at the end of the constructor.
425 constructorArgs.push_back(Literal::Make(pos, /*value=*/1, scalarType));
426 constantOneIdx = constantFieldIdx++;
427 }
428 swizzleComponents.push_back(constantOneIdx);
429 break;
430 default:
431 // The non-constant fields are already in the expected order.
432 swizzleComponents.push_back(maskFieldIdx++);
433 break;
434 }
435 }
436
437 expr = ConstructorCompound::Make(context, pos,
438 scalarType->toCompound(context, constantFieldIdx, /*rows=*/1),
439 std::move(constructorArgs));
440
441 // Create (and potentially optimize-away) the resulting swizzle-expression.
442 return Swizzle::Make(context, pos, std::move(expr), swizzleComponents);
443}
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, ExpressionArray args)
static std::unique_ptr< Literal > Make(Position pos, double value, const Type *type)
Definition SkSLLiteral.h:81
static Position Range(int startOffset, int endOffset)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, std::unique_ptr< Expression > expr, ComponentArray inComponents)
static std::string MaskString(const ComponentArray &inComponents)
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
skia_private::STArray< 4, int8_t > ComponentArray
Definition SkSLDefines.h:24
static bool validate_swizzle_domain(const ComponentArray &fields)
static char mask_char(int8_t component)

◆ Convert() [2/2]

std::unique_ptr< Expression > SkSL::Swizzle::Convert ( const Context context,
Position  pos,
Position  maskPos,
std::unique_ptr< Expression base,
std::string_view  maskString 
)
static

Definition at line 245 of file SkSLSwizzle.cpp.

249 {
251 for (size_t i = 0; i < maskString.length(); ++i) {
252 char field = maskString[i];
253 switch (field) {
256 case 'x': components.push_back(SwizzleComponent::X); break;
257 case 'r': components.push_back(SwizzleComponent::R); break;
258 case 's': components.push_back(SwizzleComponent::S); break;
259 case 'L': components.push_back(SwizzleComponent::UL); break;
260 case 'y': components.push_back(SwizzleComponent::Y); break;
261 case 'g': components.push_back(SwizzleComponent::G); break;
262 case 't': components.push_back(SwizzleComponent::T); break;
263 case 'T': components.push_back(SwizzleComponent::UT); break;
264 case 'z': components.push_back(SwizzleComponent::Z); break;
265 case 'b': components.push_back(SwizzleComponent::B); break;
266 case 'p': components.push_back(SwizzleComponent::P); break;
267 case 'R': components.push_back(SwizzleComponent::UR); break;
268 case 'w': components.push_back(SwizzleComponent::W); break;
269 case 'a': components.push_back(SwizzleComponent::A); break;
270 case 'q': components.push_back(SwizzleComponent::Q); break;
271 case 'B': components.push_back(SwizzleComponent::UB); break;
272 default:
273 context.fErrors->error(Position::Range(maskPos.startOffset() + i,
274 maskPos.startOffset() + i + 1),
275 String::printf("invalid swizzle component '%c'", field));
276 return nullptr;
277 }
278 }
279 return Convert(context, pos, maskPos, std::move(base), std::move(components));
280}
static std::unique_ptr< Expression > Convert(const Context &context, Position pos, Position maskPos, std::unique_ptr< Expression > base, ComponentArray inComponents)

◆ description()

std::string SkSL::Swizzle::description ( OperatorPrecedence  ) const
overridevirtual

Implements SkSL::Expression.

Definition at line 537 of file SkSLSwizzle.cpp.

537 {
538 return this->base()->description(OperatorPrecedence::kPostfix) + "." +
539 MaskString(this->components());
540}

◆ Make()

std::unique_ptr< Expression > SkSL::Swizzle::Make ( const Context context,
Position  pos,
std::unique_ptr< Expression expr,
ComponentArray  inComponents 
)
static

Definition at line 445 of file SkSLSwizzle.cpp.

448 {
449 const Type& exprType = expr->type();
450 SkASSERTF(exprType.isVector() || exprType.isScalar(),
451 "cannot swizzle type '%s'", exprType.description().c_str());
452 SkASSERT(components.size() >= 1 && components.size() <= 4);
453
454 // Confirm that the component array only contains X/Y/Z/W. (Call MakeWith01 if you want support
455 // for ZERO and ONE. Once initial IR generation is complete, no swizzles should have zeros or
456 // ones in them.)
457 SkASSERT(std::all_of(components.begin(), components.end(), [](int8_t component) {
458 return component >= SwizzleComponent::X &&
459 component <= SwizzleComponent::W;
460 }));
461
462 // SkSL supports splatting a scalar via `scalar.xxxx`, but not all versions of GLSL allow this.
463 // Replace swizzles with equivalent splat constructors (`scalar.xxx` --> `half3(value)`).
464 if (exprType.isScalar()) {
465 return ConstructorSplat::Make(context, pos,
466 exprType.toCompound(context, components.size(), /*rows=*/1),
467 std::move(expr));
468 }
469
470 // Detect identity swizzles like `color.rgba` and optimize it away.
471 if (components.size() == exprType.columns()) {
472 bool identity = true;
473 for (int i = 0; i < components.size(); ++i) {
474 if (components[i] != i) {
475 identity = false;
476 break;
477 }
478 }
479 if (identity) {
480 expr->fPosition = pos;
481 return expr;
482 }
483 }
484
485 // Optimize swizzles of swizzles, e.g. replace `foo.argb.rggg` with `foo.arrr`.
486 if (expr->is<Swizzle>()) {
487 Swizzle& base = expr->as<Swizzle>();
488 ComponentArray combined;
489 for (int8_t c : components) {
490 combined.push_back(base.components()[c]);
491 }
492
493 // It may actually be possible to further simplify this swizzle. Go again.
494 // (e.g. `color.abgr.abgr` --> `color.rgba` --> `color`.)
495 return Swizzle::Make(context, pos, std::move(base.base()), combined);
496 }
497
498 // If we are swizzling a constant expression, we can use its value instead here (so that
499 // swizzles like `colorWhite.x` can be simplified to `1`).
501
502 // `half4(scalar).zyy` can be optimized to `half3(scalar)`, and `half3(scalar).y` can be
503 // optimized to just `scalar`. The swizzle components don't actually matter, as every field
504 // in a splat constructor holds the same value.
505 if (value->is<ConstructorSplat>()) {
506 const ConstructorSplat& splat = value->as<ConstructorSplat>();
508 context, pos,
509 splat.type().componentType().toCompound(context, components.size(), /*rows=*/1),
510 splat.argument()->clone());
511 }
512
513 // Swizzles on casts, like `half4(myFloat4).zyy`, can optimize to `half3(myFloat4.zyy)`.
514 if (value->is<ConstructorCompoundCast>()) {
515 const ConstructorCompoundCast& cast = value->as<ConstructorCompoundCast>();
516 const Type& castType = cast.type().componentType().toCompound(context, components.size(),
517 /*rows=*/1);
518 std::unique_ptr<Expression> swizzled = Swizzle::Make(context, pos, cast.argument()->clone(),
519 std::move(components));
520 return (castType.columns() > 1)
521 ? ConstructorCompoundCast::Make(context, pos, castType, std::move(swizzled))
522 : ConstructorScalarCast::Make(context, pos, castType, std::move(swizzled));
523 }
524
525 // Swizzles on compound constructors, like `half4(1, 2, 3, 4).yw`, can become `half2(2, 4)`.
526 if (value->is<ConstructorCompound>()) {
527 const ConstructorCompound& ctor = value->as<ConstructorCompound>();
528 if (auto replacement = optimize_constructor_swizzle(context, pos, ctor, components)) {
529 return replacement;
530 }
531 }
532
533 // The swizzle could not be simplified, so apply the requested swizzle to the base expression.
534 return std::make_unique<Swizzle>(context, pos, std::move(expr), components);
535}
#define SkASSERTF(cond, fmt,...)
Definition SkAssert.h:117
SI D cast(const S &v)
static const Expression * GetConstantValueForVariable(const Expression &value)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, std::unique_ptr< Expression > arg)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, std::unique_ptr< Expression > arg)
Expression(Position pos, Kind kind, const Type *type)
uint8_t value
static std::unique_ptr< Expression > optimize_constructor_swizzle(const Context &context, Position pos, const ConstructorCompound &base, ComponentArray components)
Definition ref_ptr.h:256

◆ MaskString()

std::string SkSL::Swizzle::MaskString ( const ComponentArray inComponents)
static

Definition at line 111 of file SkSLSwizzle.cpp.

111 {
112 std::string result;
113 for (int8_t component : components) {
114 result += mask_char(component);
115 }
116 return result;
117}
GAsyncResult * result

Member Data Documentation

◆ kIRNodeKind

constexpr Kind SkSL::Swizzle::kIRNodeKind = Kind::kSwizzle
inlinestaticconstexpr

Definition at line 47 of file SkSLSwizzle.h.


The documentation for this class was generated from the following files: