Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Namespaces | Classes | Typedefs | Enumerations | Functions | Variables
SkSL Namespace Reference

Namespaces

namespace  Analysis
 
namespace  Constructor
 
namespace  Intrinsics
 
namespace  PipelineStage
 
namespace  RP
 
namespace  String
 
namespace  SwizzleComponent
 
namespace  Transform
 

Classes

class  AliasType
 
class  AnyConstructor
 
class  ArrayType
 
class  AtomicType
 
class  AutoAttachPoolToThread
 
class  AutoOutputStream
 
class  AutoProgramConfig
 
class  BinaryExpression
 
class  Block
 
class  BreakStatement
 
class  BuiltinTypes
 
class  ChildCall
 
class  CodeGenerator
 
struct  CoercionCost
 
struct  CompactEntry
 
class  Compiler
 
class  ConstantFolder
 
class  ConstructorArray
 
class  ConstructorArrayCast
 
class  ConstructorCompound
 
class  ConstructorCompoundCast
 
class  ConstructorDiagonalMatrix
 
class  ConstructorMatrixResize
 
class  ConstructorScalarCast
 
class  ConstructorSplat
 
class  ConstructorStruct
 
class  Context
 
class  ContinueStatement
 
class  CountReturnsWithLimit
 
class  DebugTrace
 
class  DebugTracePriv
 
class  DiscardStatement
 
class  DoStatement
 
class  EmptyExpression
 
class  ErrorReporter
 
class  Expression
 
class  ExpressionArray
 
class  ExpressionStatement
 
class  ExtendedVariable
 
class  Extension
 
struct  Field
 
class  FieldAccess
 
class  FieldSymbol
 
class  FileOutputStream
 
struct  ForLoopPositions
 
class  ForStatement
 
struct  FullEntry
 
class  FunctionCall
 
struct  FunctionDebugInfo
 
class  FunctionDeclaration
 
class  FunctionDefinition
 
class  FunctionPrototype
 
class  FunctionReference
 
class  GenericType
 
class  GlobalVarDeclaration
 
class  GLSLCodeGenerator
 
class  IfStatement
 
class  IndexExpression
 
struct  InlineCandidate
 
class  InlineCandidateAnalyzer
 
struct  InlineCandidateList
 
class  Inliner
 
class  InterfaceBlock
 
struct  IRHelpers
 
class  IRNode
 
struct  Layout
 
class  Lexer
 
class  Literal
 
class  LiteralType
 
struct  LoopUnrollInfo
 
class  Mangler
 
class  MatrixType
 
class  MemoryLayout
 
class  MemoryPool
 
class  MetalCodeGenerator
 
class  MethodReference
 
class  ModifierFlags
 
struct  Modifiers
 
class  ModifiersDeclaration
 
struct  Module
 
class  ModuleLoader
 
class  MultiArgumentConstructor
 
class  NoOpErrorReporter
 
class  Nop
 
class  Operator
 
class  OutputStream
 
class  Parser
 
class  PointerLValue
 
class  Poison
 
class  Pool
 
class  Poolable
 
class  Position
 
class  PostfixExpression
 
class  PrefixExpression
 
struct  Program
 
struct  ProgramConfig
 
class  ProgramElement
 
struct  ProgramInterface
 
struct  ProgramSettings
 
class  ProgramUsage
 
class  ProgramVisitor
 
struct  ProgramVisitorTypes
 
class  ProgramWriter
 
struct  ProgramWriterTypes
 
class  ReturnStatement
 
class  SamplerType
 
class  SampleUsage
 
class  ScalarType
 
class  Setting
 
struct  ShaderCaps
 
class  ShaderCapsFactory
 
class  SingleArgumentConstructor
 
class  SkSLDebugTracePlayer
 
struct  SlotDebugInfo
 
class  SPIRVCodeGenerator
 
class  Statement
 
class  StringStream
 
class  StructDefinition
 
class  StructType
 
class  SwitchCase
 
class  SwitchStatement
 
class  Swizzle
 
class  SwizzleLValue
 
class  Symbol
 
class  SymbolTable
 
class  TernaryExpression
 
class  TestingOnly_AbortErrorReporter
 
class  TextureType
 
struct  Token
 
class  TProgramVisitor
 
class  TraceHook
 
struct  TraceInfo
 
class  Tracer
 
class  Type
 
class  TypeReference
 
struct  UniformInfo
 
class  VarDeclaration
 
class  Variable
 
class  VariableReference
 
class  VectorType
 
class  WGSLCodeGenerator
 

Typedefs

using IntrinsicArguments = std::array< const Expression *, 3 >
 
using CoalesceFn = double(*)(double, double, double)
 
using FinalizeFn = double(*)(double)
 
using CompareFn = bool(*)(double, double)
 
using EvaluateFn = double(*)(double, double, double)
 
using LayoutFlags = SkEnumBitMask< SkSL::LayoutFlag >
 
using ComponentArray = skia_private::STArray< 4, int8_t >
 
using StatementArray = skia_private::STArray< 2, std::unique_ptr< Statement > >
 
using IntrinsicMap = skia_private::THashMap< std::string_view, IntrinsicKind >
 
using State = uint16_t
 
using IndexEntry = int16_t
 
using BuiltinTypePtr = const std::unique_ptr< Type > BuiltinTypes::*
 

Enumerations

enum class  Version { k100 , k300 }
 
enum class  FieldAccessOwnerKind : int8_t { kDefault , kAnonymousInterfaceBlock }
 
enum class  ProgramElementKind {
  kExtension = 0 , kFunction , kFunctionPrototype , kGlobalVar ,
  kInterfaceBlock , kModifiers , kStructDefinition , kFirst = kExtension ,
  kLast = kStructDefinition
}
 
enum class  SymbolKind {
  kExternal = (int) ProgramElementKind::kLast + 1 , kField , kFunctionDeclaration , kType ,
  kVariable , kFirst = kExternal , kLast = kVariable
}
 
enum class  StatementKind {
  kBlock = (int) SymbolKind::kLast + 1 , kBreak , kContinue , kDiscard ,
  kDo , kExpression , kFor , kIf ,
  kNop , kReturn , kSwitch , kSwitchCase ,
  kVarDeclaration , kFirst = kBlock , kLast = kVarDeclaration
}
 
enum class  ExpressionKind {
  kBinary = (int) StatementKind::kLast + 1 , kChildCall , kConstructorArray , kConstructorArrayCast ,
  kConstructorCompound , kConstructorCompoundCast , kConstructorDiagonalMatrix , kConstructorMatrixResize ,
  kConstructorScalarCast , kConstructorSplat , kConstructorStruct , kEmpty ,
  kFieldAccess , kFunctionReference , kFunctionCall , kIndex ,
  kLiteral , kMethodReference , kPoison , kPostfix ,
  kPrefix , kSetting , kSwizzle , kTernary ,
  kTypeReference , kVariableReference , kFirst = kBinary , kLast = kVariableReference
}
 
enum class  LayoutFlag : int {
  kNone = 0 , kAll = ~0 , kOriginUpperLeft = 1 << 0 , kPushConstant = 1 << 1 ,
  kBlendSupportAllEquations = 1 << 2 , kColor = 1 << 3 , kLocation = 1 << 4 , kOffset = 1 << 5 ,
  kBinding = 1 << 6 , kTexture = 1 << 7 , kSampler = 1 << 8 , kIndex = 1 << 9 ,
  kSet = 1 << 10 , kBuiltin = 1 << 11 , kInputAttachmentIndex = 1 << 12 , kVulkan = 1 << 13 ,
  kMetal = 1 << 14 , kWebGPU = 1 << 15 , kDirect3D = 1 << 16 , kAllBackends = kVulkan | kMetal | kWebGPU | kDirect3D ,
  kRGBA8 = 1 << 17 , kRGBA32F = 1 << 18 , kR32F = 1 << 19 , kAllPixelFormats = kRGBA8 | kRGBA32F | kR32F ,
  kLocalSizeX = 1 << 20 , kLocalSizeY = 1 << 21 , kLocalSizeZ = 1 << 22
}
 
enum class  ModifierFlag : int {
  kNone = 0 , kFlat = 1 << 0 , kNoPerspective = 1 << 1 , kConst = 1 << 2 ,
  kUniform = 1 << 3 , kIn = 1 << 4 , kOut = 1 << 5 , kHighp = 1 << 6 ,
  kMediump = 1 << 7 , kLowp = 1 << 8 , kReadOnly = 1 << 9 , kWriteOnly = 1 << 10 ,
  kBuffer = 1 << 11 , kPixelLocal = 1 << 12 , kWorkgroup = 1 << 13 , kExport = 1 << 14 ,
  kES3 = 1 << 15 , kPure = 1 << 16 , kInline = 1 << 17 , kNoInline = 1 << 18
}
 
enum class  VariableStorage : int8_t { kGlobal , kInterfaceBlock , kLocal , kParameter }
 
enum class  VariableRefKind : int8_t { kRead , kWrite , kReadWrite , kPointer }
 
enum class  GLSLGeneration {
  k110 , k100es = k110 , k130 , k140 ,
  k150 , k330 , k300es = k330 , k400 ,
  k420 , k310es , k320es
}
 
enum  IntrinsicKind : int8_t { kNotIntrinsic = -1 , SKSL_INTRINSIC_LIST }
 
enum class  OperatorKind : uint8_t {
  PLUS , MINUS , STAR , SLASH ,
  PERCENT , SHL , SHR , LOGICALNOT ,
  LOGICALAND , LOGICALOR , LOGICALXOR , BITWISENOT ,
  BITWISEAND , BITWISEOR , BITWISEXOR , EQ ,
  EQEQ , NEQ , LT , GT ,
  LTEQ , GTEQ , PLUSEQ , MINUSEQ ,
  STAREQ , SLASHEQ , PERCENTEQ , SHLEQ ,
  SHREQ , BITWISEANDEQ , BITWISEOREQ , BITWISEXOREQ ,
  PLUSPLUS , MINUSMINUS , COMMA
}
 
enum class  OperatorPrecedence : uint8_t {
  kParentheses = 1 , kPostfix = 2 , kPrefix = 3 , kMultiplicative = 4 ,
  kAdditive = 5 , kShift = 6 , kRelational = 7 , kEquality = 8 ,
  kBitwiseAnd = 9 , kBitwiseXor = 10 , kBitwiseOr = 11 , kLogicalAnd = 12 ,
  kLogicalXor = 13 , kLogicalOr = 14 , kTernary = 15 , kAssignment = 16 ,
  kSequence = 17 , kExpression = kSequence , kStatement = 18
}
 
enum class  ProgramKind : int8_t {
  kFragment , kVertex , kCompute , kGraphiteFragment ,
  kGraphiteVertex , kGraphiteFragmentES2 , kGraphiteVertexES2 , kRuntimeColorFilter ,
  kRuntimeShader , kRuntimeBlender , kPrivateRuntimeColorFilter , kPrivateRuntimeShader ,
  kPrivateRuntimeBlender , kMeshVertex , kMeshFragment
}
 

Functions

static int calculate_count (double start, double end, double delta, bool forwards, bool inclusive)
 
static int count_returns_at_end_of_control_flow (const FunctionDefinition &funcDef)
 
static bool contains_matching_data (const ProgramUsage &a, const ProgramUsage &b)
 
static bool is_abs (Expression &expr)
 
bool is_sk_position (const Expression &expr)
 
bool is_sk_samplemask (const Expression &expr)
 
bool ToGLSL (Program &program, const ShaderCaps *caps, OutputStream &out)
 
bool ToGLSL (Program &program, const ShaderCaps *caps, std::string *out)
 
bool ToHLSL (Program &program, const ShaderCaps *caps, OutputStream &out)
 
bool ToHLSL (Program &program, const ShaderCaps *caps, std::string *out)
 
static const char * operator_name (Operator op)
 
static bool pass_by_reference (const Type &type, ModifierFlags flags)
 
static bool needs_address_space (const Type &type, ModifierFlags modifiers)
 
static bool is_buffer (const InterfaceBlock &block)
 
static bool is_readonly (const InterfaceBlock &block)
 
static bool is_compute_builtin (const Variable &var)
 
static bool is_input (const Variable &var)
 
static bool is_output (const Variable &var)
 
static bool is_uniforms (const Variable &var)
 
static bool is_threadgroup (const Variable &var)
 
static bool is_in_globals (const Variable &var)
 
static bool is_block_ending_with_return (const Statement *stmt)
 
bool ToMetal (Program &program, const ShaderCaps *caps, OutputStream &out)
 
bool ToMetal (Program &program, const ShaderCaps *caps, std::string *out)
 
std::unique_ptr< RP::ProgramMakeRasterPipelineProgram (const SkSL::Program &program, const FunctionDefinition &function, DebugTracePriv *debugTrace, bool writeTraceOps)
 
static bool is_float (const Type &type)
 
static bool is_signed (const Type &type)
 
static bool is_unsigned (const Type &type)
 
static bool is_bool (const Type &type)
 
template<typename T >
static T pick_by_type (const Type &type, T ifFloat, T ifInt, T ifUInt, T ifBool)
 
static bool is_out (ModifierFlags f)
 
static bool is_in (ModifierFlags f)
 
static bool is_control_flow_op (SpvOp_ op)
 
static bool is_globally_reachable_op (SpvOp_ op)
 
static SpvImageFormat layout_flags_to_image_format (LayoutFlags flags)
 
static SpvStorageClass_ get_storage_class_for_global_variable (const Variable &var, SpvStorageClass_ fallbackStorageClass)
 
static SpvStorageClass_ get_storage_class (const Expression &expr)
 
static bool types_match (const Type &a, const Type &b)
 
static bool is_vardecl_compile_time_constant (const VarDeclaration &varDecl)
 
static SymbolTableget_top_level_symbol_table (const FunctionDeclaration &anyFunc)
 
bool ToSPIRV (Program &program, const ShaderCaps *caps, OutputStream &out)
 
bool ToSPIRV (Program &program, const ShaderCaps *caps, std::string *out)
 
bool SPIRVtoHLSL (const std::string &, std::string *)
 
static bool is_nontrivial_expression (const Expression &expr)
 
static bool binary_op_is_ambiguous_in_wgsl (Operator op)
 
static bool all_arguments_constant (const ExpressionArray &arguments)
 
bool ToWGSL (Program &program, const ShaderCaps *caps, OutputStream &out)
 
bool ToWGSL (Program &program, const ShaderCaps *caps, std::string *out)
 
static bool call_signature_is_valid (const Context &context, const Variable &child, const ExpressionArray &arguments)
 
static std::unique_ptr< Expressionconvert_compound_constructor (const Context &context, Position pos, const Type &type, ExpressionArray args)
 
static std::unique_ptr< Expressioncast_constant_array (const Context &context, Position pos, const Type &destType, std::unique_ptr< Expression > constCtor)
 
static bool is_safe_to_eliminate (const Type &type, const Expression &arg)
 
static const Expressionmake_splat_from_arguments (const Type &type, const ExpressionArray &args)
 
static std::unique_ptr< Expressioncast_constant_composite (const Context &context, Position pos, const Type &destType, std::unique_ptr< Expression > constCtor)
 
static bool arguments_match_field_types (const ExpressionArray &args, const Type &type)
 
static std::unique_ptr< Expressionextract_field (Position pos, const ConstructorStruct &ctor, int fieldIndex)
 
static bool is_vardecl_block_initializer (const Statement *stmt)
 
static bool is_simple_initializer (const Statement *stmt)
 
static void hoist_vardecl_symbols_into_outer_scope (const Context &context, const Block &initBlock, SymbolTable *innerSymbols, SymbolTable *hoistedSymbols)
 
static bool has_compile_time_constant_arguments (const ExpressionArray &arguments)
 
template<typename T >
static void type_check_expression (const Expression &expr)
 
template<>
void type_check_expression< float > (const Expression &expr)
 
template<>
void type_check_expression< SKSL_INT > (const Expression &expr)
 
template<>
void type_check_expression< bool > (const Expression &expr)
 
static std::unique_ptr< Expressioncoalesce_n_way_vector (const Expression *arg0, const Expression *arg1, double startingState, const Type &returnType, CoalesceFn coalesce, FinalizeFn finalize)
 
template<typename T >
static std::unique_ptr< Expressioncoalesce_vector (const IntrinsicArguments &arguments, double startingState, const Type &returnType, CoalesceFn coalesce, FinalizeFn finalize)
 
template<typename T >
static std::unique_ptr< Expressioncoalesce_pairwise_vectors (const IntrinsicArguments &arguments, double startingState, const Type &returnType, CoalesceFn coalesce, FinalizeFn finalize)
 
static std::unique_ptr< Expressionoptimize_comparison (const Context &context, const IntrinsicArguments &arguments, CompareFn compare)
 
static std::unique_ptr< Expressionevaluate_n_way_intrinsic (const Context &context, const Expression *arg0, const Expression *arg1, const Expression *arg2, const Type &returnType, EvaluateFn eval)
 
template<typename T >
static std::unique_ptr< Expressionevaluate_intrinsic (const Context &context, const IntrinsicArguments &arguments, const Type &returnType, EvaluateFn eval)
 
static std::unique_ptr< Expressionevaluate_intrinsic_numeric (const Context &context, const IntrinsicArguments &arguments, const Type &returnType, EvaluateFn eval)
 
static std::unique_ptr< Expressionevaluate_pairwise_intrinsic (const Context &context, const IntrinsicArguments &arguments, const Type &returnType, EvaluateFn eval)
 
static std::unique_ptr< Expressionevaluate_3_way_intrinsic (const Context &context, const IntrinsicArguments &arguments, const Type &returnType, EvaluateFn eval)
 
template<typename T1 , typename T2 >
static double pun_value (double val)
 
static void extract_matrix (const Expression *expr, float mat[16])
 
static std::unique_ptr< Expressionoptimize_intrinsic_call (const Context &context, Position pos, IntrinsicKind intrinsic, const ExpressionArray &argArray, const Type &returnType)
 
static bool argument_and_parameter_flags_match (const Expression &argument, const Variable &parameter)
 
static CoercionCost call_cost (const Context &context, const FunctionDeclaration &function, const ExpressionArray &arguments)
 
static std::string build_argument_type_list (SkSpan< const std::unique_ptr< Expression > > arguments)
 
static bool check_modifiers (const Context &context, Position pos, ModifierFlags modifierFlags)
 
static bool check_return_type (const Context &context, Position pos, const Type &returnType)
 
static bool check_parameters (const Context &context, TArray< std::unique_ptr< Variable > > &parameters, ModifierFlags modifierFlags, IntrinsicKind intrinsicKind)
 
static bool type_is_valid_for_color (const Type &type)
 
static bool type_is_valid_for_coords (const Type &type)
 
static bool check_main_signature (const Context &context, Position pos, const Type &returnType, TArray< std::unique_ptr< Variable > > &parameters)
 
static int find_generic_index (const Type &concreteType, const Type &genericType, bool allowNarrowing)
 
static bool type_generically_matches (const Type &concreteType, const Type &maybeGenericType)
 
static bool parameters_match (SkSpan< const std::unique_ptr< Variable > > params, SkSpan< Variable *const > otherParams)
 
static bool find_existing_declaration (const Context &context, Position pos, ModifierFlags modifierFlags, IntrinsicKind intrinsicKind, std::string_view name, TArray< std::unique_ptr< Variable > > &parameters, Position returnTypePos, const Type *returnType, FunctionDeclaration **outExistingDecl)
 
static void append_rtadjust_fixup_to_vertex_main (const Context &context, const FunctionDeclaration &decl, Block &body)
 
static std::unique_ptr< Statementreplace_empty_with_nop (std::unique_ptr< Statement > stmt, bool isEmpty)
 
static bool index_out_of_range (const Context &context, Position pos, SKSL_INT index, const Expression &base)
 
static std::optional< intfind_rt_adjust_index (SkSpan< const Field > fields)
 
static ExpressionArray negate_operands (const Context &context, Position pos, const ExpressionArray &operands)
 
static double negate_value (double value)
 
static double bitwise_not_value (double value)
 
static std::unique_ptr< Expressionapply_to_elements (const Context &context, Position pos, const Expression &expr, double(*fn)(double))
 
static std::unique_ptr< Expressionsimplify_negation (const Context &context, Position pos, const Expression &originalExpr)
 
static std::unique_ptr< Expressionnegate_operand (const Context &context, Position pos, std::unique_ptr< Expression > value)
 
static std::unique_ptr< Expressionlogical_not_operand (const Context &context, Position pos, std::unique_ptr< Expression > operand)
 
static std::unique_ptr< Expressionbitwise_not_operand (const Context &context, Position pos, std::unique_ptr< Expression > operand)
 
static std::forward_list< const SwitchCase * > find_duplicate_case_values (const StatementArray &cases)
 
static void remove_break_statements (std::unique_ptr< Statement > &stmt)
 
static bool block_for_case (Statement *caseBlock, SwitchCase *caseToCapture)
 
static bool validate_swizzle_domain (const ComponentArray &fields)
 
static char mask_char (int8_t component)
 
static std::unique_ptr< Expressionoptimize_constructor_swizzle (const Context &context, Position pos, const ConstructorCompound &base, ComponentArray components)
 
static bool is_vec_or_mat (const Type &type)
 
static std::unique_ptr< Expressioneliminate_no_op_boolean (Position pos, const Expression &left, Operator op, const Expression &right)
 
static std::unique_ptr< Expressionshort_circuit_boolean (Position pos, const Expression &left, Operator op, const Expression &right)
 
static std::unique_ptr< Expressionsimplify_constant_equality (const Context &context, Position pos, const Expression &left, Operator op, const Expression &right)
 
static std::unique_ptr< Expressionsimplify_matrix_multiplication (const Context &context, Position pos, const Expression &left, const Expression &right, int leftColumns, int leftRows, int rightColumns, int rightRows)
 
static std::unique_ptr< Expressionsimplify_matrix_times_matrix (const Context &context, Position pos, const Expression &left, const Expression &right)
 
static std::unique_ptr< Expressionsimplify_vector_times_matrix (const Context &context, Position pos, const Expression &left, const Expression &right)
 
static std::unique_ptr< Expressionsimplify_matrix_times_vector (const Context &context, Position pos, const Expression &left, const Expression &right)
 
static std::unique_ptr< Expressionsimplify_componentwise (const Context &context, Position pos, const Expression &left, Operator op, const Expression &right)
 
static std::unique_ptr< Expressionsplat_scalar (const Context &context, const Expression &scalar, const Type &type)
 
static std::unique_ptr< Expressioncast_expression (const Context &context, Position pos, const Expression &expr, const Type &type)
 
static std::unique_ptr< Expressionzero_expression (const Context &context, Position pos, const Type &type)
 
static std::unique_ptr< Expressionnegate_expression (const Context &context, Position pos, const Expression &expr, const Type &type)
 
static bool contains_constant_zero (const Expression &expr)
 
static bool is_constant_diagonal (const Expression &expr, double value)
 
static bool is_constant_value (const Expression &expr, double value)
 
static std::unique_ptr< Expressionmake_reciprocal_expression (const Context &context, const Expression &right)
 
static bool error_on_divide_by_zero (const Context &context, Position pos, Operator op, const Expression &right)
 
static bool is_scalar_op_matrix (const Expression &left, const Expression &right)
 
static bool is_matrix_op_scalar (const Expression &left, const Expression &right)
 
static std::unique_ptr< Expressionsimplify_arithmetic (const Context &context, Position pos, const Expression &left, Operator op, const Expression &right, const Type &resultType)
 
static std::unique_ptr< Expressionone_over_scalar (const Context &context, const Expression &right)
 
static std::unique_ptr< Expressionsimplify_matrix_division (const Context &context, Position pos, const Expression &left, Operator op, const Expression &right, const Type &resultType)
 
static std::unique_ptr< Expressionfold_expression (Position pos, double result, const Type *resultType)
 
static bool argument_needs_scratch_variable (const Expression *arg, const Variable *param, const ProgramUsage &usage)
 
static const FunctionDeclarationcandidate_func (const InlineCandidate &candidate)
 
const IntrinsicMapGetIntrinsicMap ()
 
IntrinsicKind FindIntrinsicKind (std::string_view functionName)
 
static State get_transition (uint8_t transition, State state)
 
static std::unique_ptr< Modulecompile_and_shrink (SkSL::Compiler *compiler, ProgramKind kind, const char *moduleName, std::string moduleSource, const Module *parent)
 
static ModifierFlags parse_modifier_token (Token::Kind token)
 
static bool is_whitespace (Token::Kind kind)
 
static Position range_of_at_least_one_char (int start, int end)
 
static MemoryPoolget_thread_local_memory_pool ()
 
static void set_thread_local_memory_pool (MemoryPool *memPool)
 
bool stod (std::string_view s, SKSL_FLOAT *value)
 
bool stoi (std::string_view s, SKSL_INT *value)
 
void write_stringstream (const StringStream &s, OutputStream &out)
 
bool type_to_sksltype (const Context &context, const Type &type, SkSLType *outType)
 
static bool dead_function_predicate (const ProgramElement *element, ProgramUsage *usage)
 
static bool is_dead_variable (const ProgramElement &element, ProgramUsage *usage, bool onlyPrivateGlobals)
 
static bool eliminate_dead_local_variables (const Context &context, SkSpan< std::unique_ptr< ProgramElement > > elements, ProgramUsage *usage)
 
static void eliminate_empty_statements (SkSpan< std::unique_ptr< ProgramElement > > elements)
 
static void eliminate_unnecessary_braces (SkSpan< std::unique_ptr< ProgramElement > > elements)
 
static void eliminate_unreachable_code (SkSpan< std::unique_ptr< ProgramElement > > elements, ProgramUsage *usage)
 
static bool contains_builtin_struct (const ProgramUsage &usage)
 
static void get_struct_definitions_from_module (Program &program, const Module &module, std::vector< const ProgramElement * > *addedStructDefs)
 
static void strip_export_flag (Context &context, const FunctionDeclaration *funcDecl, SymbolTable *symbols)
 

Variables

static constexpr int kLoopTerminationLimit = 100000
 
static constexpr char kDeterminant2 []
 
static constexpr char kDeterminant3 []
 
static constexpr char kDeterminant4 []
 
static constexpr char kInverse2 []
 
static constexpr char kInverse3 []
 
static constexpr char kInverse4 []
 
static constexpr char kInverse2x2 []
 
static constexpr char kInverse3x3 []
 
static constexpr char kInverse4x4 []
 
static const int32_t SKSL_MAGIC = 0x001F0000
 
static constexpr char kInverse2x2 []
 
static constexpr char kInverse3x3 []
 
static constexpr char kInverse4x4 []
 
static constexpr int kMaxStructDepth = 8
 
static constexpr Layout kDefaultLayout
 
static constexpr int kDefaultInlineThreshold = 50
 
static constexpr int kVariableSlotLimit = 100000
 
static constexpr uint8_t kInvalidChar = 18
 
static constexpr uint8_t kMappings [118]
 
static constexpr FullEntry kFull []
 
static constexpr CompactEntry kCompact []
 
static constexpr IndexEntry kIndices []
 
static const uint8_t kAccepts [427]
 
static constexpr BuiltinTypePtr kRootTypes []
 
static constexpr BuiltinTypePtr kPrivateTypes []
 
static constexpr int kMaxParseDepth = 50
 
static thread_local MemoryPoolsMemPool = nullptr
 

Typedef Documentation

◆ BuiltinTypePtr

using SkSL::BuiltinTypePtr = typedef const std::unique_ptr<Type> BuiltinTypes::*

Definition at line 20 of file SkSLModuleLoader.h.

◆ CoalesceFn

using SkSL::CoalesceFn = typedef double (*)(double, double, double)

Definition at line 81 of file SkSLFunctionCall.cpp.

◆ CompareFn

using SkSL::CompareFn = typedef bool (*)(double, double)

Definition at line 174 of file SkSLFunctionCall.cpp.

◆ ComponentArray

using SkSL::ComponentArray = typedef skia_private::STArray<4, int8_t>

Definition at line 24 of file SkSLDefines.h.

◆ EvaluateFn

using SkSL::EvaluateFn = typedef double (*)(double, double, double)

Definition at line 204 of file SkSLFunctionCall.cpp.

◆ FinalizeFn

using SkSL::FinalizeFn = typedef double (*)(double)

Definition at line 82 of file SkSLFunctionCall.cpp.

◆ IndexEntry

using SkSL::IndexEntry = typedef int16_t

Definition at line 24 of file SkSLLexer.cpp.

◆ IntrinsicArguments

using SkSL::IntrinsicArguments = typedef std::array<const Expression*, 3>

Definition at line 51 of file SkSLFunctionCall.cpp.

◆ IntrinsicMap

using SkSL::IntrinsicMap = typedef skia_private::THashMap<std::string_view, IntrinsicKind>

Definition at line 134 of file SkSLIntrinsicList.h.

◆ LayoutFlags

Definition at line 68 of file SkSLLayout.h.

◆ State

using SkSL::State = typedef uint16_t

Definition at line 14 of file SkSLLexer.cpp.

◆ StatementArray

using SkSL::StatementArray = typedef skia_private::STArray<2, std::unique_ptr<Statement> >

Definition at line 34 of file SkSLDefines.h.

Enumeration Type Documentation

◆ ExpressionKind

enum class SkSL::ExpressionKind
strong
Enumerator
kBinary 
kChildCall 
kConstructorArray 
kConstructorArrayCast 
kConstructorCompound 
kConstructorCompoundCast 
kConstructorDiagonalMatrix 
kConstructorMatrixResize 
kConstructorScalarCast 
kConstructorSplat 
kConstructorStruct 
kEmpty 
kFieldAccess 
kFunctionReference 
kFunctionCall 
kIndex 
kLiteral 
kMethodReference 
kPoison 
kPostfix 
kPrefix 
kSetting 
kSwizzle 
kTernary 
kTypeReference 
kVariableReference 
kFirst 
kLast 

Definition at line 62 of file SkSLIRNode.h.

62 {
63 kBinary = (int) StatementKind::kLast + 1,
64 kChildCall,
65 kConstructorArray,
66 kConstructorArrayCast,
67 kConstructorCompound,
68 kConstructorCompoundCast,
69 kConstructorDiagonalMatrix,
70 kConstructorMatrixResize,
71 kConstructorScalarCast,
72 kConstructorSplat,
73 kConstructorStruct,
74 kEmpty,
75 kFieldAccess,
76 kFunctionReference,
77 kFunctionCall,
78 kIndex,
79 kLiteral,
80 kMethodReference,
81 kPoison,
82 kPostfix,
83 kPrefix,
84 kSetting,
85 kSwizzle,
86 kTernary,
87 kTypeReference,
88 kVariableReference,
89
90 kFirst = kBinary,
91 kLast = kVariableReference
92};
Type::kYUV Type::kRGBA() int(0.7 *637)

◆ FieldAccessOwnerKind

enum class SkSL::FieldAccessOwnerKind : int8_t
strong
Enumerator
kDefault 
kAnonymousInterfaceBlock 

Definition at line 29 of file SkSLFieldAccess.h.

29 : int8_t {
31 // this field access is to a field of an anonymous interface block (and thus, the field name
32 // is actually in global scope, so only the field name needs to be written in GLSL)
34};

◆ GLSLGeneration

enum class SkSL::GLSLGeneration
strong
Enumerator
k110 

Desktop GLSL 1.10 and ES2 shading language (based on desktop GLSL 1.20)

k100es 
k130 

Desktop GLSL 1.30

k140 

Desktop GLSL 1.40

k150 

Desktop GLSL 1.50

k330 

Desktop GLSL 3.30, and ES GLSL 3.00

k300es 
k400 

Desktop GLSL 4.00

k420 

Desktop GLSL 4.20

k310es 

ES GLSL 3.10 only TODO Make GLSLCap objects to make this more granular

k320es 

ES GLSL 3.20

Definition at line 15 of file SkSLGLSL.h.

15 {
16 /**
17 * Desktop GLSL 1.10 and ES2 shading language (based on desktop GLSL 1.20)
18 */
19 k110,
20 k100es = k110,
21 /**
22 * Desktop GLSL 1.30
23 */
24 k130,
25 /**
26 * Desktop GLSL 1.40
27 */
28 k140,
29 /**
30 * Desktop GLSL 1.50
31 */
32 k150,
33 /**
34 * Desktop GLSL 3.30, and ES GLSL 3.00
35 */
36 k330,
37 k300es = k330,
38 /**
39 * Desktop GLSL 4.00
40 */
41 k400,
42 /**
43 * Desktop GLSL 4.20
44 */
45 k420,
46 /**
47 * ES GLSL 3.10 only TODO Make GLSLCap objects to make this more granular
48 */
49 k310es,
50 /**
51 * ES GLSL 3.20
52 */
53 k320es,
54};

◆ IntrinsicKind

enum SkSL::IntrinsicKind : int8_t
Enumerator
kNotIntrinsic 
SKSL_INTRINSIC_LIST 

Definition at line 127 of file SkSLIntrinsicList.h.

127 : int8_t {
128 kNotIntrinsic = -1,
130};
#define SKSL_INTRINSIC_LIST

◆ LayoutFlag

enum class SkSL::LayoutFlag : int
strong
Enumerator
kNone 
kAll 
kOriginUpperLeft 
kPushConstant 
kBlendSupportAllEquations 
kColor 
kLocation 
kOffset 
kBinding 
kTexture 
kSampler 
kIndex 
kSet 
kBuiltin 
kInputAttachmentIndex 
kVulkan 
kMetal 
kWebGPU 
kDirect3D 
kAllBackends 
kRGBA8 
kRGBA32F 
kR32F 
kAllPixelFormats 
kLocalSizeX 
kLocalSizeY 
kLocalSizeZ 

Definition at line 20 of file SkSLLayout.h.

20 : int {
21 kNone = 0,
22 kAll = ~0,
23
24 kOriginUpperLeft = 1 << 0,
25 kPushConstant = 1 << 1,
27 kColor = 1 << 3,
28
29 // These flags indicate if the qualifier appeared, regardless of the accompanying value.
30 kLocation = 1 << 4,
31 kOffset = 1 << 5,
32 kBinding = 1 << 6,
33 kTexture = 1 << 7,
34 kSampler = 1 << 8,
35 kIndex = 1 << 9,
36 kSet = 1 << 10,
37 kBuiltin = 1 << 11,
38 kInputAttachmentIndex = 1 << 12,
39
40 // These flags indicate the backend type; only one at most can be set.
41 kVulkan = 1 << 13,
42 kMetal = 1 << 14,
43 kWebGPU = 1 << 15,
44 kDirect3D = 1 << 16,
45
47
48 // These flags indicate the pixel format; only one at most can be set.
49 // (https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)#Image_formats)
50 kRGBA8 = 1 << 17,
51 kRGBA32F = 1 << 18,
52 kR32F = 1 << 19,
53
55
56 // The local invocation size of a compute program.
57 kLocalSizeX = 1 << 20,
58 kLocalSizeY = 1 << 21,
59 kLocalSizeZ = 1 << 22,
60};
static constexpr SkColor kColor
static constexpr uint64_t kOffset
Definition DrawPass.cpp:54
@ kVulkan
Definition embedder.h:86
@ kMetal
Definition embedder.h:85

◆ ModifierFlag

enum class SkSL::ModifierFlag : int
strong
Enumerator
kNone 
kFlat 
kNoPerspective 
kConst 
kUniform 
kIn 
kOut 
kHighp 
kMediump 
kLowp 
kReadOnly 
kWriteOnly 
kBuffer 
kPixelLocal 
kWorkgroup 
kExport 
kES3 
kPure 
kInline 
kNoInline 

Definition at line 21 of file SkSLModifierFlags.h.

21 : int {
22 kNone = 0,
23 // Real GLSL modifiers
24 kFlat = 1 << 0,
25 kNoPerspective = 1 << 1,
26 kConst = 1 << 2,
27 kUniform = 1 << 3,
28 kIn = 1 << 4,
29 kOut = 1 << 5,
30 kHighp = 1 << 6,
31 kMediump = 1 << 7,
32 kLowp = 1 << 8,
33 kReadOnly = 1 << 9,
34 kWriteOnly = 1 << 10,
35 kBuffer = 1 << 11,
36 kPixelLocal = 1 << 12,
37 // Corresponds to the GLSL 'shared' modifier. Only allowed in a compute program.
38 kWorkgroup = 1 << 13,
39 // SkSL extensions, not present in GLSL
40 kExport = 1 << 14,
41 kES3 = 1 << 15,
42 kPure = 1 << 16,
43 kInline = 1 << 17,
44 kNoInline = 1 << 18,
45};

◆ OperatorKind

enum class SkSL::OperatorKind : uint8_t
strong
Enumerator
PLUS 
MINUS 
STAR 
SLASH 
PERCENT 
SHL 
SHR 
LOGICALNOT 
LOGICALAND 
LOGICALOR 
LOGICALXOR 
BITWISENOT 
BITWISEAND 
BITWISEOR 
BITWISEXOR 
EQ 
EQEQ 
NEQ 
LT 
GT 
LTEQ 
GTEQ 
PLUSEQ 
MINUSEQ 
STAREQ 
SLASHEQ 
PERCENTEQ 
SHLEQ 
SHREQ 
BITWISEANDEQ 
BITWISEOREQ 
BITWISEXOREQ 
PLUSPLUS 
MINUSMINUS 
COMMA 

Definition at line 19 of file SkSLOperator.h.

19 : uint8_t {
20 PLUS,
21 MINUS,
22 STAR,
23 SLASH,
24 PERCENT,
25 SHL,
26 SHR,
35 EQ,
36 EQEQ,
37 NEQ,
38 LT,
39 GT,
40 LTEQ,
41 GTEQ,
42 PLUSEQ,
43 MINUSEQ,
44 STAREQ,
45 SLASHEQ,
47 SHLEQ,
48 SHREQ,
54 COMMA
55};
#define COMMA

◆ OperatorPrecedence

enum class SkSL::OperatorPrecedence : uint8_t
strong
Enumerator
kParentheses 
kPostfix 
kPrefix 
kMultiplicative 
kAdditive 
kShift 
kRelational 
kEquality 
kBitwiseAnd 
kBitwiseXor 
kBitwiseOr 
kLogicalAnd 
kLogicalXor 
kLogicalOr 
kTernary 
kAssignment 
kSequence 
kExpression 
kStatement 

Definition at line 57 of file SkSLOperator.h.

57 : uint8_t {
58 kParentheses = 1,
59 kPostfix = 2,
60 kPrefix = 3,
62 kAdditive = 5,
63 kShift = 6,
64 kRelational = 7,
65 kEquality = 8,
66 kBitwiseAnd = 9,
67 kBitwiseXor = 10,
68 kBitwiseOr = 11,
69 kLogicalAnd = 12,
70 kLogicalXor = 13,
71 kLogicalOr = 14,
72 kTernary = 15,
73 kAssignment = 16,
74 kSequence = 17, // a comma-separated sequence
75 kExpression = kSequence, // a top-level expression, anywhere in a statement
76 kStatement = 18, // a standalone expression-statement
77};

◆ ProgramElementKind

enum class SkSL::ProgramElementKind
strong
Enumerator
kExtension 
kFunction 
kFunctionPrototype 
kGlobalVar 
kInterfaceBlock 
kModifiers 
kStructDefinition 
kFirst 
kLast 

Definition at line 19 of file SkSLIRNode.h.

◆ ProgramKind

enum class SkSL::ProgramKind : int8_t
strong

SkSL supports several different program kinds.

Enumerator
kFragment 
kVertex 
kCompute 
kGraphiteFragment 
kGraphiteVertex 
kGraphiteFragmentES2 
kGraphiteVertexES2 
kRuntimeColorFilter 
kRuntimeShader 
kRuntimeBlender 
kPrivateRuntimeColorFilter 
kPrivateRuntimeShader 
kPrivateRuntimeBlender 
kMeshVertex 
kMeshFragment 

Definition at line 18 of file SkSLProgramKind.h.

18 : int8_t {
19 kFragment,
20 kVertex,
21 kCompute,
26 kRuntimeColorFilter, // Runtime effect only suitable as SkColorFilter
27 kRuntimeShader, // " " " " " SkShader
28 kRuntimeBlender, // " " " " " SkBlender
29 kPrivateRuntimeColorFilter, // Runtime color filter with public restrictions lifted
30 kPrivateRuntimeShader, // Runtime shader " " " "
31 kPrivateRuntimeBlender, // Runtime blender " " " "
32 kMeshVertex, // Vertex portion of a custom mesh
33 kMeshFragment, // Fragment " " " " "
34};

◆ StatementKind

enum class SkSL::StatementKind
strong
Enumerator
kBlock 
kBreak 
kContinue 
kDiscard 
kDo 
kExpression 
kFor 
kIf 
kNop 
kReturn 
kSwitch 
kSwitchCase 
kVarDeclaration 
kFirst 
kLast 

Definition at line 43 of file SkSLIRNode.h.

43 {
44 kBlock = (int) SymbolKind::kLast + 1,
45 kBreak,
46 kContinue,
48 kDo,
49 kExpression,
50 kFor,
51 kIf,
52 kNop,
53 kReturn,
54 kSwitch,
55 kSwitchCase,
56 kVarDeclaration,
57
58 kFirst = kBlock,
59 kLast = kVarDeclaration,
60};

◆ SymbolKind

enum class SkSL::SymbolKind
strong
Enumerator
kExternal 
kField 
kFunctionDeclaration 
kType 
kVariable 
kFirst 
kLast 

Definition at line 32 of file SkSLIRNode.h.

32 {
33 kExternal = (int) ProgramElementKind::kLast + 1,
34 kField,
35 kFunctionDeclaration,
36 kType,
37 kVariable,
38
39 kFirst = kExternal,
40 kLast = kVariable
41};

◆ VariableRefKind

enum class SkSL::VariableRefKind : int8_t
strong
Enumerator
kRead 
kWrite 
kReadWrite 
kPointer 

Definition at line 25 of file SkSLVariableReference.h.

25 : int8_t {
26 kRead,
27 kWrite,
28 kReadWrite,
29 // taking the address of a variable - we consider this a read & write but don't complain if
30 // the variable was not previously assigned
32};

◆ VariableStorage

enum class SkSL::VariableStorage : int8_t
strong
Enumerator
kGlobal 
kInterfaceBlock 
kLocal 
kParameter 

Definition at line 36 of file SkSLVariable.h.

◆ Version

enum class SkSL::Version
strong
Enumerator
k100 

Desktop GLSL 1.10, GLSL ES 1.00, WebGL 1.0

k300 

Desktop GLSL 3.30, GLSL ES 3.00, WebGL 2.0

Definition at line 13 of file SkSLVersion.h.

13 {
14 /**
15 * Desktop GLSL 1.10, GLSL ES 1.00, WebGL 1.0
16 */
17 k100,
18
19 /**
20 * Desktop GLSL 3.30, GLSL ES 3.00, WebGL 2.0
21 */
22 k300,
23};

Function Documentation

◆ all_arguments_constant()

static bool SkSL::all_arguments_constant ( const ExpressionArray arguments)
static

Definition at line 2780 of file SkSLWGSLCodeGenerator.cpp.

2780 {
2781 // Returns true if all arguments in the ExpressionArray are compile-time constants. If we are
2782 // calling an intrinsic and all of its inputs are constant, but we didn't constant-fold it, this
2783 // generally indicates that constant-folding resulted in an infinity or nan. The WGSL compiler
2784 // will reject such an expression with a compile-time error. We can dodge the error, taking on
2785 // the risk of indeterminate behavior instead, by replacing one of the constant values with a
2786 // scratch let-variable. (skia:14385)
2787 for (const std::unique_ptr<Expression>& arg : arguments) {
2788 if (!ConstantFolder::GetConstantValueOrNull(*arg)) {
2789 return false;
2790 }
2791 }
2792 return true;
2793}

◆ append_rtadjust_fixup_to_vertex_main()

static void SkSL::append_rtadjust_fixup_to_vertex_main ( const Context context,
const FunctionDeclaration decl,
Block body 
)
static

Definition at line 43 of file SkSLFunctionDefinition.cpp.

45 {
46 // If this program uses RTAdjust...
47 if (const SkSL::Symbol* rtAdjust = context.fSymbolTable->find(Compiler::RTADJUST_NAME)) {
48 // ...append a line to the end of the function body which fixes up sk_Position.
49 struct AppendRTAdjustFixupHelper : public IRHelpers {
50 AppendRTAdjustFixupHelper(const Context& ctx, const SkSL::Symbol* rtAdjust)
51 : IRHelpers(ctx)
52 , fRTAdjust(rtAdjust) {
53 fSkPositionField = &fContext.fSymbolTable->find(Compiler::POSITION_NAME)
54 ->as<FieldSymbol>();
55 }
56
57 std::unique_ptr<Expression> Pos() const {
58 return Field(&fSkPositionField->owner(), fSkPositionField->fieldIndex());
59 }
60
61 std::unique_ptr<Expression> Adjust() const {
62 return fRTAdjust->instantiate(fContext, Position());
63 }
64
65 std::unique_ptr<Statement> makeFixupStmt() const {
66 // sk_Position = float4(sk_Position.xy * rtAdjust.xz + sk_Position.ww * rtAdjust.yw,
67 // 0,
68 // sk_Position.w);
69 return Assign(
70 Pos(),
71 CtorXYZW(Add(Mul(Swizzle(Pos(), {SwizzleComponent::X, SwizzleComponent::Y}),
72 Swizzle(Adjust(), {SwizzleComponent::X, SwizzleComponent::Z})),
73 Mul(Swizzle(Pos(), {SwizzleComponent::W, SwizzleComponent::W}),
74 Swizzle(Adjust(), {SwizzleComponent::Y, SwizzleComponent::W}))),
75 Float(0.0),
76 Swizzle(Pos(), {SwizzleComponent::W})));
77 }
78
79 const FieldSymbol* fSkPositionField;
80 const SkSL::Symbol* fRTAdjust;
81 };
82
83 AppendRTAdjustFixupHelper helper(context, rtAdjust);
84 body.children().push_back(helper.makeFixupStmt());
85 }
86}
const Context & fContext
const StatementArray & children() const
Definition SkSLBlock.h:71
SymbolTable * fSymbolTable
Definition SkSLContext.h:48
const Symbol * find(std::string_view name) const
std::unique_ptr< Expression > Add(std::unique_ptr< Expression > l, std::unique_ptr< Expression > r) const
std::unique_ptr< Expression > Mul(std::unique_ptr< Expression > l, std::unique_ptr< Expression > r) const
std::unique_ptr< Expression > CtorXYZW(std::unique_ptr< Expression > xy, std::unique_ptr< Expression > z, std::unique_ptr< Expression > w) const
std::unique_ptr< Expression > Float(float value) const
std::unique_ptr< Statement > Assign(std::unique_ptr< Expression > l, std::unique_ptr< Expression > r) const

◆ apply_to_elements()

static std::unique_ptr< Expression > SkSL::apply_to_elements ( const Context context,
Position  pos,
const Expression expr,
double(*)(double)  fn 
)
static

Definition at line 43 of file SkSLPrefixExpression.cpp.

46 {
47 const Type& elementType = expr.type().componentType();
48
49 double values[16];
50 size_t numSlots = expr.type().slotCount();
51 if (numSlots > std::size(values)) {
52 // The expression has more slots than we expected.
53 return nullptr;
54 }
55
56 for (size_t index = 0; index < numSlots; ++index) {
57 if (std::optional<double> slotValue = expr.getConstantValue(index)) {
58 values[index] = fn(*slotValue);
59 if (elementType.checkForOutOfRangeLiteral(context, values[index], pos)) {
60 // We can't simplify the expression if the new value is out-of-range for the type.
61 return nullptr;
62 }
63 } else {
64 // There's a non-constant element; we can't simplify this expression.
65 return nullptr;
66 }
67 }
68 return ConstructorCompound::MakeFromConstants(context, pos, expr.type(), values);
69}
SkPoint pos
virtual const Type & type() const
virtual std::optional< double > getConstantValue(int n) const
virtual const Type & componentType() const
Definition SkSLType.h:404
virtual size_t slotCount() const
Definition SkSLType.h:457
bool checkForOutOfRangeLiteral(const Context &context, const Expression &expr) const

◆ argument_and_parameter_flags_match()

static bool SkSL::argument_and_parameter_flags_match ( const Expression argument,
const Variable parameter 
)
static

Definition at line 1021 of file SkSLFunctionCall.cpp.

1022 {
1023 // If the function parameter has a pixel format, the argument being passed in must have a
1024 // matching pixel format.
1025 LayoutFlags paramPixelFormat = parameter.layout().fFlags & LayoutFlag::kAllPixelFormats;
1026 if (paramPixelFormat != LayoutFlag::kNone) {
1027 // The only SkSL type that supports pixel-format qualifiers is a storage texture.
1028 if (parameter.type().isStorageTexture()) {
1029 // Storage textures are opaquely typed, so there's no way to specify one other than by
1030 // directly accessing a variable.
1031 if (!argument.is<VariableReference>()) {
1032 return false;
1033 }
1034
1035 // The variable's pixel-format flags must match. (Only one pixel-format bit can be set.)
1036 const Variable& var = *argument.as<VariableReference>().variable();
1037 if ((var.layout().fFlags & LayoutFlag::kAllPixelFormats) != paramPixelFormat) {
1038 return false;
1039 }
1040 }
1041 }
1042
1043 // The only other supported parameter flags are `const` and `in/out`, which do not allow
1044 // multiple overloads.
1045 return true;
1046}
bool is() const
Definition SkSLIRNode.h:124
const T & as() const
Definition SkSLIRNode.h:133
const Type & type() const
Definition SkSLSymbol.h:42
bool isStorageTexture() const
Definition SkSLType.h:371
virtual const Layout & layout() const
LayoutFlags fFlags
Definition SkSLLayout.h:112

◆ argument_needs_scratch_variable()

static bool SkSL::argument_needs_scratch_variable ( const Expression arg,
const Variable param,
const ProgramUsage usage 
)
static

Definition at line 518 of file SkSLInliner.cpp.

520 {
521 // If the parameter isn't written to within the inline function ...
522 const ProgramUsage::VariableCounts& paramUsage = usage.get(*param);
523 if (!paramUsage.fWrite) {
524 // ... and can be inlined trivially (e.g. a swizzle, or a constant array index),
525 // or any expression without side effects that is only accessed at most once...
526 if ((paramUsage.fRead > 1) ? Analysis::IsTrivialExpression(*arg)
527 : !Analysis::HasSideEffects(*arg)) {
528 // ... we don't need to copy it at all! We can just use the existing expression.
529 return false;
530 }
531 }
532 // We need a scratch variable.
533 return true;
534}
static void usage(char *argv0)

◆ arguments_match_field_types()

static bool SkSL::arguments_match_field_types ( const ExpressionArray args,
const Type type 
)
static

Definition at line 62 of file SkSLConstructorStruct.cpp.

63 {
64 SkASSERT(type.fields().size() == SkToSizeT(args.size()));
65
66 for (int index = 0; index < args.size(); ++index) {
67 const std::unique_ptr<Expression>& argument = args[index];
68 const Field& field = type.fields()[index];
69 if (!argument->type().matches(*field.fType)) {
70 return false;
71 }
72 }
73
74 return true;
75}
#define SkASSERT(cond)
Definition SkAssert.h:116
constexpr size_t SkToSizeT(S x)
Definition SkTo.h:31
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const Type * fType
Definition SkSLType.h:88

◆ binary_op_is_ambiguous_in_wgsl()

static bool SkSL::binary_op_is_ambiguous_in_wgsl ( Operator  op)
static

Definition at line 2496 of file SkSLWGSLCodeGenerator.cpp.

2496 {
2497 // WGSL always requires parentheses for some operators which are deemed to be ambiguous.
2498 // (8.19. Operator Precedence and Associativity)
2499 switch (op.kind()) {
2500 case OperatorKind::LOGICALOR:
2501 case OperatorKind::LOGICALAND:
2502 case OperatorKind::BITWISEOR:
2503 case OperatorKind::BITWISEAND:
2504 case OperatorKind::BITWISEXOR:
2505 case OperatorKind::SHL:
2506 case OperatorKind::SHR:
2507 case OperatorKind::LT:
2508 case OperatorKind::GT:
2509 case OperatorKind::LTEQ:
2510 case OperatorKind::GTEQ:
2511 return true;
2512
2513 default:
2514 return false;
2515 }
2516}
Kind kind() const

◆ bitwise_not_operand()

static std::unique_ptr< Expression > SkSL::bitwise_not_operand ( const Context context,
Position  pos,
std::unique_ptr< Expression operand 
)
static

Definition at line 198 of file SkSLPrefixExpression.cpp.

200 {
201 SkASSERT(operand->type().componentType().isInteger());
202
203 const Expression* value = ConstantFolder::GetConstantValueForVariable(*operand);
204
205 switch (value->kind()) {
206 case Expression::Kind::kLiteral:
207 case Expression::Kind::kConstructorSplat:
208 case Expression::Kind::kConstructorCompound: {
209 // Convert ~vecN(1, 2, ...) to vecN(~1, ~2, ...).
210 if (std::unique_ptr<Expression> expr = apply_to_elements(context, pos, *value,
211 bitwise_not_value)) {
212 return expr;
213 }
214 break;
215 }
216 case Expression::Kind::kPrefix: {
217 // Convert `~(~expression)` into `expression`.
218 PrefixExpression& prefix = operand->as<PrefixExpression>();
219 if (prefix.getOperator().kind() == Operator::Kind::BITWISENOT) {
220 prefix.operand()->fPosition = pos;
221 return std::move(prefix.operand());
222 }
223 break;
224 }
225 default:
226 break;
227 }
228
229 // No simplified form; convert expression to Prefix(BITWISENOT, expression).
230 return std::make_unique<PrefixExpression>(pos, Operator::Kind::BITWISENOT, std::move(operand));
231}
uint8_t value
static std::unique_ptr< Expression > apply_to_elements(const Context &context, Position pos, const Expression &expr, double(*fn)(double))

◆ bitwise_not_value()

static double SkSL::bitwise_not_value ( double  value)
static

Definition at line 39 of file SkSLPrefixExpression.cpp.

39 {
40 return ~static_cast<SKSL_INT>(value);
41}

◆ block_for_case()

static bool SkSL::block_for_case ( Statement caseBlock,
SwitchCase caseToCapture 
)
static

Definition at line 86 of file SkSLSwitchStatement.cpp.

86 {
87 // This function reduces a switch to the matching case (or cases, if fallthrough occurs) when
88 // the switch-value is known and no conditional breaks exist. If conversion is not possible,
89 // false is returned and no changes are made. Conversion can fail if the switch contains
90 // conditional breaks.
91 //
92 // We have to be careful to not move any of the pointers until after we're sure we're going to
93 // succeed, so before we make any changes at all, we check the switch-cases to decide on a plan
94 // of action.
95 //
96 // First, we identify the code that would be run if the switch's value matches `caseToCapture`.
97 StatementArray& cases = caseBlock->as<Block>().children();
98 auto iter = cases.begin();
99 for (; iter != cases.end(); ++iter) {
100 const SwitchCase& sc = (*iter)->as<SwitchCase>();
101 if (&sc == caseToCapture) {
102 break;
103 }
104 }
105
106 // Next, walk forward through the rest of the switch. If we find a conditional break, we're
107 // stuck and can't simplify at all. If we find an unconditional break, we have a range of
108 // statements that we can use for simplification.
109 auto startIter = iter;
110 bool removeBreakStatements = false;
111 for (; iter != cases.end(); ++iter) {
112 std::unique_ptr<Statement>& stmt = (*iter)->as<SwitchCase>().statement();
113 if (Analysis::SwitchCaseContainsConditionalExit(*stmt)) {
114 // We can't reduce switch-cases to a block when they have conditional exits.
115 return false;
116 }
117 if (Analysis::SwitchCaseContainsUnconditionalExit(*stmt)) {
118 // We found an unconditional exit. We can use this block, but we'll need to strip
119 // out the break statement if there is one.
120 removeBreakStatements = true;
121 ++iter;
122 break;
123 }
124 }
125
126 // We fell off the bottom of the switch or encountered a break. Next, we must strip down
127 // `caseBlock` to hold only the statements needed to execute `caseToCapture`. To do this, we
128 // eliminate the SwitchCase elements. This converts each `case n: stmt;` element into just
129 // `stmt;`. While doing this, we also move the elements to the front of the array if they
130 // weren't already there.
131 int numElements = SkToInt(std::distance(startIter, iter));
132 for (int index = 0; index < numElements; ++index, ++startIter) {
133 cases[index] = std::move((*startIter)->as<SwitchCase>().statement());
134 }
135
136 // Next, we shrink the statement array to destroy the excess statements.
137 cases.pop_back_n(cases.size() - numElements);
138
139 // If we found an unconditional break at the end, we need to eliminate that break.
140 if (removeBreakStatements) {
142 }
143
144 // We've stripped down `caseBlock` to contain only the captured case. Return true.
145 return true;
146}
constexpr int SkToInt(S x)
Definition SkTo.h:29
void pop_back_n(int n)
Definition SkTArray.h:325
int size() const
Definition SkTArray.h:416
static void remove_break_statements(std::unique_ptr< Statement > &stmt)

◆ build_argument_type_list()

static std::string SkSL::build_argument_type_list ( SkSpan< const std::unique_ptr< Expression > >  arguments)
static

Definition at line 1107 of file SkSLFunctionCall.cpp.

1107 {
1108 std::string result = "(";
1109 auto separator = SkSL::String::Separator();
1110 for (const std::unique_ptr<Expression>& arg : arguments) {
1111 result += separator();
1112 result += arg->type().displayName();
1113 }
1114 return result + ")";
1115}
GAsyncResult * result
std::string void void auto Separator()
Definition SkSLString.h:30

◆ calculate_count()

static int SkSL::calculate_count ( double  start,
double  end,
double  delta,
bool  forwards,
bool  inclusive 
)
static

Definition at line 38 of file SkSLGetLoopUnrollInfo.cpp.

38 {
39 if ((forwards && start > end) || (!forwards && start < end)) {
40 // The loop starts in a completed state (the start has already advanced past the end).
41 return 0;
42 }
43 if ((delta == 0.0) || forwards != (delta > 0.0)) {
44 // The loop does not progress toward a completed state, and will never terminate.
45 return kLoopTerminationLimit;
46 }
47 double iterations = sk_ieee_double_divide(end - start, delta);
48 double count = std::ceil(iterations);
49 if (inclusive && (count == iterations)) {
50 count += 1.0;
51 }
52 if (count > kLoopTerminationLimit || !std::isfinite(count)) {
53 // The loop runs for more iterations than we can safely unroll.
55 }
56 return (int)count;
57}
int count
static constexpr double sk_ieee_double_divide(double numer, double denom)
glong glong end
static constexpr int kLoopTerminationLimit

◆ call_cost()

static CoercionCost SkSL::call_cost ( const Context context,
const FunctionDeclaration function,
const ExpressionArray arguments 
)
static

Used to determine the best overload for a function call by calculating the cost of coercing the arguments of the function to the required types. Cost has no particular meaning other than "lower costs are preferred". Returns CoercionCost::Impossible() if the call is not valid. This is never called for functions with only one definition.

Definition at line 1054 of file SkSLFunctionCall.cpp.

1056 {
1057 // Strict-ES2 programs can never call an `$es3` function.
1058 if (context.fConfig->strictES2Mode() && function.modifierFlags().isES3()) {
1059 return CoercionCost::Impossible();
1060 }
1061 // Functions with the wrong number of parameters are never a match.
1062 if (function.parameters().size() != SkToSizeT(arguments.size())) {
1063 return CoercionCost::Impossible();
1064 }
1065 // If the arguments cannot be coerced to the parameter types, the function is never a match.
1066 FunctionDeclaration::ParamTypes types;
1067 const Type* ignored;
1068 if (!function.determineFinalTypes(arguments, &types, &ignored)) {
1069 return CoercionCost::Impossible();
1070 }
1071 // If the arguments do not match the parameter types due to mismatched modifiers, the function
1072 // is never a match.
1073 for (int i = 0; i < arguments.size(); i++) {
1074 const Expression& arg = *arguments[i];
1075 const Variable& param = *function.parameters()[i];
1076 if (!argument_and_parameter_flags_match(arg, param)) {
1077 return CoercionCost::Impossible();
1078 }
1079 }
1080 // Return the sum of coercion costs of each argument.
1081 CoercionCost total = CoercionCost::Free();
1082 for (int i = 0; i < arguments.size(); i++) {
1083 total = total + arguments[i]->coercionCost(*types[i]);
1084 }
1085 return total;
1086}
ProgramConfig * fConfig
Definition SkSLContext.h:33
Dart_NativeFunction function
Definition fuchsia.cc:51
static bool argument_and_parameter_flags_match(const Expression &argument, const Variable &parameter)

◆ call_signature_is_valid()

static bool SkSL::call_signature_is_valid ( const Context context,
const Variable child,
const ExpressionArray arguments 
)
static

Definition at line 39 of file SkSLChildCall.cpp.

41 {
42 const Type* half4 = context.fTypes.fHalf4.get();
43 const Type* float2 = context.fTypes.fFloat2.get();
44
45 auto params = [&]() -> STArray<2, const Type*> {
46 switch (child.type().typeKind()) {
47 case Type::TypeKind::kBlender: return { half4, half4 };
48 case Type::TypeKind::kColorFilter: return { half4 };
49 case Type::TypeKind::kShader: return { float2 };
50 default:
52 }
53 }();
54
55 if (params.size() != arguments.size()) {
56 return false;
57 }
58 for (int i = 0; i < arguments.size(); i++) {
59 if (!arguments[i]->type().matches(*params[i])) {
60 return false;
61 }
62 }
63 return true;
64}
#define SkUNREACHABLE
Definition SkAssert.h:135
const std::unique_ptr< Type > fFloat2
const std::unique_ptr< Type > fHalf4
const BuiltinTypes & fTypes
Definition SkSLContext.h:30
TypeKind typeKind() const
Definition SkSLType.h:283
const EmbeddedViewParams * params

◆ candidate_func()

static const FunctionDeclaration & SkSL::candidate_func ( const InlineCandidate candidate)
static

Definition at line 964 of file SkSLInliner.cpp.

964 {
965 return (*candidate.fCandidateExpr)->as<FunctionCall>().function();
966}
std::unique_ptr< Expression > * fCandidateExpr

◆ cast_constant_array()

static std::unique_ptr< Expression > SkSL::cast_constant_array ( const Context context,
Position  pos,
const Type destType,
std::unique_ptr< Expression constCtor 
)
static

Definition at line 22 of file SkSLConstructorArrayCast.cpp.

25 {
26 const Type& scalarType = destType.componentType();
27
28 // Create a ConstructorArray(...) which typecasts each argument inside.
29 auto inputArgs = constCtor->as<ConstructorArray>().argumentSpan();
30 ExpressionArray typecastArgs;
31 typecastArgs.reserve_exact(inputArgs.size());
32 for (std::unique_ptr<Expression>& arg : inputArgs) {
33 Position argPos = arg->fPosition;
34 if (arg->type().isScalar()) {
35 typecastArgs.push_back(ConstructorScalarCast::Make(context, argPos, scalarType,
36 std::move(arg)));
37 } else {
38 typecastArgs.push_back(ConstructorCompoundCast::Make(context, argPos, scalarType,
39 std::move(arg)));
40 }
41 }
42
43 return ConstructorArray::Make(context, pos, destType, std::move(typecastArgs));
44}
const T & as() const
Definition SkSLType.h:210
void reserve_exact(int n)
Definition SkTArray.h:176

◆ cast_constant_composite()

static std::unique_ptr< Expression > SkSL::cast_constant_composite ( const Context context,
Position  pos,
const Type destType,
std::unique_ptr< Expression constCtor 
)
static

Definition at line 25 of file SkSLConstructorCompoundCast.cpp.

28 {
29 const Type& scalarType = destType.componentType();
30
31 // We generate nicer code for splats and diagonal matrices by handling them separately instead
32 // of relying on the constant-subexpression code below. This is not truly necessary but it makes
33 // our output look a little better; human beings prefer `half4(0)` to `half4(0, 0, 0, 0)`.
34 if (constCtor->is<ConstructorSplat>()) {
35 // This is a typecast of a splat containing a constant value, e.g. `half4(7)`. We can
36 // replace it with a splat of a different type, e.g. `int4(7)`.
37 ConstructorSplat& splat = constCtor->as<ConstructorSplat>();
38 return ConstructorSplat::Make(
39 context, pos, destType,
40 ConstructorScalarCast::Make(context, pos, scalarType, std::move(splat.argument())));
41 }
42
43 if (constCtor->is<ConstructorDiagonalMatrix>() && destType.isMatrix()) {
44 // This is a typecast of a constant diagonal matrix, e.g. `float3x3(2)`. We can replace it
45 // with a diagonal matrix of a different type, e.g. `half3x3(2)`.
46 ConstructorDiagonalMatrix& matrixCtor = constCtor->as<ConstructorDiagonalMatrix>();
47 return ConstructorDiagonalMatrix::Make(
48 context, pos, destType,
49 ConstructorScalarCast::Make(context, pos, scalarType,
50 std::move(matrixCtor.argument())));
51 }
52
53 // Create a compound Constructor(literal, ...) which typecasts each scalar value inside.
54 size_t numSlots = destType.slotCount();
55 SkASSERT(numSlots == constCtor->type().slotCount());
56
57 double typecastArgs[16];
58 SkASSERT(numSlots <= std::size(typecastArgs));
59 for (size_t index = 0; index < numSlots; ++index) {
60 std::optional<double> slotVal = constCtor->getConstantValue(index);
61 if (scalarType.checkForOutOfRangeLiteral(context, *slotVal, constCtor->fPosition)) {
62 // We've reported an error because the literal is out of range for this type. Zero out
63 // the value to avoid a cascade of errors.
64 *slotVal = 0.0;
65 }
66 typecastArgs[index] = *slotVal;
67 }
68
69 return ConstructorCompound::MakeFromConstants(context, pos, destType, typecastArgs);
70}
std::unique_ptr< Expression > & argument()
virtual bool isMatrix() const
Definition SkSLType.h:528

◆ cast_expression()

static std::unique_ptr< Expression > SkSL::cast_expression ( const Context context,
Position  pos,
const Expression expr,
const Type type 
)
static

Definition at line 279 of file SkSLConstantFolder.cpp.

282 {
283 SkASSERT(type.componentType().matches(expr.type().componentType()));
284 if (expr.type().isScalar()) {
285 if (type.isMatrix()) {
286 return ConstructorDiagonalMatrix::Make(context, pos, type, expr.clone());
287 }
288 if (type.isVector()) {
289 return ConstructorSplat::Make(context, pos, type, expr.clone());
290 }
291 }
292 if (type.matches(expr.type())) {
293 return expr.clone(pos);
294 }
295 // We can't cast matrices into vectors or vice-versa.
296 return nullptr;
297}
virtual std::unique_ptr< Expression > clone(Position pos) const =0
virtual bool isScalar() const
Definition SkSLType.h:512

◆ check_main_signature()

static bool SkSL::check_main_signature ( const Context context,
Position  pos,
const Type returnType,
TArray< std::unique_ptr< Variable > > &  parameters 
)
static

Definition at line 132 of file SkSLFunctionDeclaration.cpp.

133 {
134 ErrorReporter& errors = *context.fErrors;
135 ProgramKind kind = context.fConfig->fKind;
136
137 auto typeIsValidForAttributes = [](const Type& type) {
138 return type.isStruct() && type.name() == "Attributes";
139 };
140
141 auto typeIsValidForVaryings = [](const Type& type) {
142 return type.isStruct() && type.name() == "Varyings";
143 };
144
145 auto paramIsCoords = [&](int idx) {
146 const Variable& p = *parameters[idx];
147 return type_is_valid_for_coords(p.type()) && p.modifierFlags() == ModifierFlag::kNone;
148 };
149
150 auto paramIsColor = [&](int idx) {
151 const Variable& p = *parameters[idx];
152 return type_is_valid_for_color(p.type()) && p.modifierFlags() == ModifierFlag::kNone;
153 };
154
155 auto paramIsConstInAttributes = [&](int idx) {
156 const Variable& p = *parameters[idx];
157 return typeIsValidForAttributes(p.type()) && p.modifierFlags() == ModifierFlag::kConst;
158 };
159
160 auto paramIsConstInVaryings = [&](int idx) {
161 const Variable& p = *parameters[idx];
162 return typeIsValidForVaryings(p.type()) && p.modifierFlags() == ModifierFlag::kConst;
163 };
164
165 auto paramIsOutColor = [&](int idx) {
166 const Variable& p = *parameters[idx];
167 return type_is_valid_for_color(p.type()) && p.modifierFlags() == ModifierFlag::kOut;
168 };
169
170 switch (kind) {
171 case ProgramKind::kRuntimeColorFilter:
172 case ProgramKind::kPrivateRuntimeColorFilter: {
173 // (half4|float4) main(half4|float4)
174 if (!type_is_valid_for_color(returnType)) {
175 errors.error(pos, "'main' must return: 'vec4', 'float4', or 'half4'");
176 return false;
177 }
178 bool validParams = (parameters.size() == 1 && paramIsColor(0));
179 if (!validParams) {
180 errors.error(pos, "'main' parameter must be 'vec4', 'float4', or 'half4'");
181 return false;
182 }
183 break;
184 }
185 case ProgramKind::kRuntimeShader:
186 case ProgramKind::kPrivateRuntimeShader: {
187 // (half4|float4) main(float2)
188 if (!type_is_valid_for_color(returnType)) {
189 errors.error(pos, "'main' must return: 'vec4', 'float4', or 'half4'");
190 return false;
191 }
192 if (!(parameters.size() == 1 && paramIsCoords(0))) {
193 errors.error(pos, "'main' parameter must be 'float2' or 'vec2'");
194 return false;
195 }
196 break;
197 }
198 case ProgramKind::kRuntimeBlender:
199 case ProgramKind::kPrivateRuntimeBlender: {
200 // (half4|float4) main(half4|float4, half4|float4)
201 if (!type_is_valid_for_color(returnType)) {
202 errors.error(pos, "'main' must return: 'vec4', 'float4', or 'half4'");
203 return false;
204 }
205 if (!(parameters.size() == 2 && paramIsColor(0) && paramIsColor(1))) {
206 errors.error(pos, "'main' parameters must be (vec4|float4|half4, "
207 "vec4|float4|half4)");
208 return false;
209 }
210 break;
211 }
212 case ProgramKind::kMeshVertex: {
213 // Varyings main(const Attributes)
214 if (!typeIsValidForVaryings(returnType)) {
215 errors.error(pos, "'main' must return 'Varyings'.");
216 return false;
217 }
218 if (!(parameters.size() == 1 && paramIsConstInAttributes(0))) {
219 errors.error(pos, "'main' parameter must be 'const Attributes'.");
220 return false;
221 }
222 break;
223 }
224 case ProgramKind::kMeshFragment: {
225 // float2 main(const Varyings) -or- float2 main(const Varyings, out half4|float4)
226 if (!type_is_valid_for_coords(returnType)) {
227 errors.error(pos, "'main' must return: 'vec2' or 'float2'");
228 return false;
229 }
230 if (!((parameters.size() == 1 && paramIsConstInVaryings(0)) ||
231 (parameters.size() == 2 && paramIsConstInVaryings(0) && paramIsOutColor(1)))) {
232 errors.error(pos,
233 "'main' parameters must be (const Varyings, (out (half4|float4))?)");
234 return false;
235 }
236 break;
237 }
238 case ProgramKind::kFragment:
239 case ProgramKind::kGraphiteFragment:
240 case ProgramKind::kGraphiteFragmentES2: {
241 bool validParams = (parameters.size() == 0) ||
242 (parameters.size() == 1 && paramIsCoords(0));
243 if (!validParams) {
244 errors.error(pos, "shader 'main' must be main() or main(float2)");
245 return false;
246 }
247 break;
248 }
249 case ProgramKind::kVertex:
250 case ProgramKind::kGraphiteVertex:
251 case ProgramKind::kGraphiteVertexES2:
252 case ProgramKind::kCompute:
253 if (!returnType.matches(*context.fTypes.fVoid)) {
254 errors.error(pos, "'main' must return 'void'");
255 return false;
256 }
257 if (parameters.size()) {
258 errors.error(pos, "shader 'main' must have zero parameters");
259 return false;
260 }
261 break;
262 }
263 return true;
264}
const std::unique_ptr< Type > fVoid
ErrorReporter * fErrors
Definition SkSLContext.h:36
bool matches(const Type &other) const
Definition SkSLType.h:269
static bool type_is_valid_for_coords(const Type &type)
static bool type_is_valid_for_color(const Type &type)

◆ check_modifiers()

static bool SkSL::check_modifiers ( const Context context,
Position  pos,
ModifierFlags  modifierFlags 
)
static

Definition at line 38 of file SkSLFunctionDeclaration.cpp.

38 {
39 const ModifierFlags permitted = ModifierFlag::kInline |
40 ModifierFlag::kNoInline |
41 (context.fConfig->fIsBuiltinCode ? ModifierFlag::kES3 |
42 ModifierFlag::kPure |
43 ModifierFlag::kExport
44 : ModifierFlag::kNone);
45 modifierFlags.checkPermittedFlags(context, pos, permitted);
46 if (modifierFlags.isInline() && modifierFlags.isNoInline()) {
47 context.fErrors->error(pos, "functions cannot be both 'inline' and 'noinline'");
48 return false;
49 }
50 return true;
51}
void error(Position position, std::string_view msg)
bool checkPermittedFlags(const Context &context, Position pos, ModifierFlags permittedModifierFlags) const

◆ check_parameters()

static bool SkSL::check_parameters ( const Context context,
TArray< std::unique_ptr< Variable > > &  parameters,
ModifierFlags  modifierFlags,
IntrinsicKind  intrinsicKind 
)
static

Definition at line 71 of file SkSLFunctionDeclaration.cpp.

74 {
75 // Check modifiers on each function parameter.
76 for (auto& param : parameters) {
77 const Type& type = param->type();
78 ModifierFlags permittedFlags = ModifierFlag::kConst | ModifierFlag::kIn;
79 LayoutFlags permittedLayoutFlags = LayoutFlag::kNone;
80 if (!type.isOpaque()) {
81 permittedFlags |= ModifierFlag::kOut;
82 }
83 if (type.isStorageTexture()) {
84 // We allow `readonly`, `writeonly` and `layout(pixel-format)` on storage textures.
85 permittedFlags |= ModifierFlag::kReadOnly | ModifierFlag::kWriteOnly;
86 permittedLayoutFlags |= LayoutFlag::kAllPixelFormats;
87
88 // Intrinsics are allowed to accept any pixel format, but user code must explicitly
89 // specify a pixel format like `layout(rgba32f)`.
90 if (intrinsicKind == kNotIntrinsic &&
91 !(param->layout().fFlags & LayoutFlag::kAllPixelFormats)) {
92 context.fErrors->error(param->fPosition, "storage texture parameters must specify "
93 "a pixel format layout-qualifier");
94 return false;
95 }
96 }
97 param->modifierFlags().checkPermittedFlags(context, param->modifiersPosition(),
98 permittedFlags);
99 param->layout().checkPermittedLayout(context, param->modifiersPosition(),
100 permittedLayoutFlags);
101 // Only the (builtin) declarations of 'sample' are allowed to have shader/colorFilter or FP
102 // parameters. You can pass other opaque types to functions safely; this restriction is
103 // specific to "child" objects.
104 if (type.isEffectChild() && !context.fConfig->fIsBuiltinCode) {
105 context.fErrors->error(param->fPosition, "parameters of type '" + type.displayName() +
106 "' not allowed");
107 return false;
108 }
109
110 // Pure functions should not change any state, and should be safe to eliminate if their
111 // result is not used; this is incompatible with out-parameters, so we forbid it here.
112 // (We don't exhaustively guard against pure functions changing global state in other ways,
113 // though, since they aren't allowed in user code.)
114 if (modifierFlags.isPure() && (param->modifierFlags() & ModifierFlag::kOut)) {
115 context.fErrors->error(param->modifiersPosition(),
116 "pure functions cannot have out parameters");
117 return false;
118 }
119 }
120 return true;
121}

◆ check_return_type()

static bool SkSL::check_return_type ( const Context context,
Position  pos,
const Type returnType 
)
static

Definition at line 53 of file SkSLFunctionDeclaration.cpp.

53 {
54 ErrorReporter& errors = *context.fErrors;
55 if (returnType.isArray()) {
56 errors.error(pos, "functions may not return type '" + returnType.displayName() + "'");
57 return false;
58 }
59 if (context.fConfig->strictES2Mode() && returnType.isOrContainsArray()) {
60 errors.error(pos, "functions may not return structs containing arrays");
61 return false;
62 }
63 if (!context.fConfig->fIsBuiltinCode && returnType.componentType().isOpaque()) {
64 errors.error(pos, "functions may not return opaque type '" + returnType.displayName() +
65 "'");
66 return false;
67 }
68 return true;
69}
virtual bool isArray() const
Definition SkSLType.h:532
virtual bool isOrContainsArray() const
Definition SkSLType.h:578
bool isOpaque() const
Definition SkSLType.h:353
std::string displayName() const
Definition SkSLType.h:234

◆ coalesce_n_way_vector()

static std::unique_ptr< Expression > SkSL::coalesce_n_way_vector ( const Expression arg0,
const Expression arg1,
double  startingState,
const Type returnType,
CoalesceFn  coalesce,
FinalizeFn  finalize 
)
static

Definition at line 84 of file SkSLFunctionCall.cpp.

89 {
90 // Takes up to two vector or scalar arguments and coalesces them in sequence:
91 // scalar = startingState;
92 // scalar = coalesce(scalar, arg0.x, arg1.x);
93 // scalar = coalesce(scalar, arg0.y, arg1.y);
94 // scalar = coalesce(scalar, arg0.z, arg1.z);
95 // scalar = coalesce(scalar, arg0.w, arg1.w);
96 // scalar = finalize(scalar);
97 //
98 // If an argument is null, zero is passed to the coalesce function. If the arguments are a mix
99 // of scalars and vectors, the scalars are interpreted as a vector containing the same value for
100 // every component.
101
102 Position pos = arg0->fPosition;
103 double minimumValue = returnType.componentType().minimumValue();
104 double maximumValue = returnType.componentType().maximumValue();
105
106 const Type& vecType = arg0->type().isVector() ? arg0->type() :
107 (arg1 && arg1->type().isVector()) ? arg1->type() :
108 arg0->type();
109 SkASSERT( arg0->type().componentType().matches(vecType.componentType()));
110 SkASSERT(!arg1 || arg1->type().componentType().matches(vecType.componentType()));
111
112 double value = startingState;
113 int arg0Index = 0;
114 int arg1Index = 0;
115 for (int index = 0; index < vecType.columns(); ++index) {
116 std::optional<double> arg0Value = arg0->getConstantValue(arg0Index);
117 arg0Index += arg0->type().isVector() ? 1 : 0;
118 SkASSERT(arg0Value.has_value());
119
120 std::optional<double> arg1Value = 0.0;
121 if (arg1) {
122 arg1Value = arg1->getConstantValue(arg1Index);
123 arg1Index += arg1->type().isVector() ? 1 : 0;
124 SkASSERT(arg1Value.has_value());
125 }
126
127 value = coalesce(value, *arg0Value, *arg1Value);
128
129 if (value >= minimumValue && value <= maximumValue) {
130 // This result will fit inside the return type.
131 } else {
132 // The value is outside the float range or is NaN (all if-checks fail); do not optimize.
133 return nullptr;
134 }
135 }
136
137 if (finalize) {
138 value = finalize(value);
139 }
140
141 return Literal::Make(pos, value, &returnType);
142}
Position fPosition
Definition SkSLIRNode.h:109
virtual bool isVector() const
Definition SkSLType.h:524
virtual int columns() const
Definition SkSLType.h:429
virtual double maximumValue() const
Definition SkSLType.h:449
virtual double minimumValue() const
Definition SkSLType.h:444

◆ coalesce_pairwise_vectors()

template<typename T >
static std::unique_ptr< Expression > SkSL::coalesce_pairwise_vectors ( const IntrinsicArguments arguments,
double  startingState,
const Type returnType,
CoalesceFn  coalesce,
FinalizeFn  finalize 
)
static

Definition at line 159 of file SkSLFunctionCall.cpp.

163 {
164 SkASSERT(arguments[0]);
165 SkASSERT(arguments[1]);
166 SkASSERT(!arguments[2]);
167 type_check_expression<T>(*arguments[0]);
168 type_check_expression<T>(*arguments[1]);
169
170 return coalesce_n_way_vector(arguments[0], arguments[1],
171 startingState, returnType, coalesce, finalize);
172}
static std::unique_ptr< Expression > coalesce_n_way_vector(const Expression *arg0, const Expression *arg1, double startingState, const Type &returnType, CoalesceFn coalesce, FinalizeFn finalize)

◆ coalesce_vector()

template<typename T >
static std::unique_ptr< Expression > SkSL::coalesce_vector ( const IntrinsicArguments arguments,
double  startingState,
const Type returnType,
CoalesceFn  coalesce,
FinalizeFn  finalize 
)
static

Definition at line 145 of file SkSLFunctionCall.cpp.

149 {
150 SkASSERT(arguments[0]);
151 SkASSERT(!arguments[1]);
152 type_check_expression<T>(*arguments[0]);
153
154 return coalesce_n_way_vector(arguments[0], /*arg1=*/nullptr,
155 startingState, returnType, coalesce, finalize);
156}

◆ compile_and_shrink()

static std::unique_ptr< Module > SkSL::compile_and_shrink ( SkSL::Compiler compiler,
ProgramKind  kind,
const char *  moduleName,
std::string  moduleSource,
const Module parent 
)
static

Definition at line 205 of file SkSLModuleLoader.cpp.

209 {
210 std::unique_ptr<Module> m = compiler->compileModule(kind,
211 moduleName,
212 std::move(moduleSource),
213 parent,
214 /*shouldInline=*/true);
215 if (!m) {
216 SK_ABORT("Unable to load module %s", moduleName);
217 }
218
219 // We can eliminate FunctionPrototypes without changing the meaning of the module; the function
220 // declaration is still safely in the symbol table. This only impacts our ability to recreate
221 // the input verbatim, which we don't care about at runtime.
222 m->fElements.erase(std::remove_if(m->fElements.begin(), m->fElements.end(),
223 [](const std::unique_ptr<ProgramElement>& element) {
224 switch (element->kind()) {
225 case ProgramElement::Kind::kFunction:
226 case ProgramElement::Kind::kGlobalVar:
227 case ProgramElement::Kind::kInterfaceBlock:
228 case ProgramElement::Kind::kStructDefinition:
229 // We need to preserve these.
230 return false;
231
232 case ProgramElement::Kind::kFunctionPrototype:
233 // These are already in the symbol table; the
234 // ProgramElement isn't needed anymore.
235 return true;
236
237 default:
238 SkDEBUGFAILF("Unsupported element: %s\n",
239 element->description().c_str());
240 return false;
241 }
242 }),
243 m->fElements.end());
244
245 m->fElements.shrink_to_fit();
246 return m;
247}
#define SK_ABORT(message,...)
Definition SkAssert.h:70

◆ contains_builtin_struct()

static bool SkSL::contains_builtin_struct ( const ProgramUsage usage)
static

Definition at line 27 of file SkSLFindAndDeclareBuiltinStructs.cpp.

27 {
28 for (const auto& [symbol, count] : usage.fStructCounts) {
29 const Type& type = symbol->as<Type>();
30 if (type.isBuiltin()) {
31 return true;
32 }
33 }
34 return false;
35}

◆ contains_constant_zero()

static bool SkSL::contains_constant_zero ( const Expression expr)
static

Definition at line 343 of file SkSLConstantFolder.cpp.

343 {
344 int numSlots = expr.type().slotCount();
345 for (int index = 0; index < numSlots; ++index) {
346 std::optional<double> slotVal = expr.getConstantValue(index);
347 if (slotVal.has_value() && *slotVal == 0.0) {
348 return true;
349 }
350 }
351 return false;
352}

◆ contains_matching_data()

static bool SkSL::contains_matching_data ( const ProgramUsage a,
const ProgramUsage b 
)
static

Definition at line 220 of file SkSLProgramUsage.cpp.

220 {
221 constexpr bool kReportMismatch = false;
222
223 for (const auto& [varA, varCountA] : a.fVariableCounts) {
224 // Skip variable entries with zero reported usage.
225 if (!varCountA.fVarExists && !varCountA.fRead && !varCountA.fWrite) {
226 continue;
227 }
228 // Find the matching variable in the other map and ensure that its counts match.
229 const ProgramUsage::VariableCounts* varCountB = b.fVariableCounts.find(varA);
230 if (!varCountB || 0 != memcmp(&varCountA, varCountB, sizeof(varCountA))) {
231 if constexpr (kReportMismatch) {
232 SkDebugf("VariableCounts mismatch: '%.*s' (E%d R%d W%d != E%d R%d W%d)\n",
233 (int)varA->name().size(), varA->name().data(),
234 varCountA.fVarExists,
235 varCountA.fRead,
236 varCountA.fWrite,
237 varCountB ? varCountB->fVarExists : 0,
238 varCountB ? varCountB->fRead : 0,
239 varCountB ? varCountB->fWrite : 0);
240 }
241 return false;
242 }
243 }
244
245 for (const auto& [callA, callCountA] : a.fCallCounts) {
246 // Skip function-call entries with zero reported usage.
247 if (!callCountA) {
248 continue;
249 }
250 // Find the matching function in the other map and ensure that its call-count matches.
251 const int* callCountB = b.fCallCounts.find(callA);
252 if (!callCountB || callCountA != *callCountB) {
253 if constexpr (kReportMismatch) {
254 SkDebugf("CallCounts mismatch: '%.*s' (%d != %d)\n",
255 (int)callA->name().size(), callA->name().data(),
256 callCountA,
257 callCountB ? *callCountB : 0);
258 }
259 return false;
260 }
261 }
262
263 for (const auto& [structA, structCountA] : a.fStructCounts) {
264 // Skip struct entries with zero reported usage.
265 if (!structCountA) {
266 continue;
267 }
268 // Find the matching struct in the other map and ensure that its usage-count matches.
269 const int* structCountB = b.fStructCounts.find(structA);
270 if (!structCountB || structCountA != *structCountB) {
271 if constexpr (kReportMismatch) {
272 SkDebugf("StructCounts mismatch: '%.*s' (%d != %d)\n",
273 (int)structA->name().size(), structA->name().data(),
274 structCountA,
275 structCountB ? *structCountB : 0);
276 }
277 return false;
278 }
279 }
280
281 // Every non-zero entry in A has a matching non-zero entry in B.
282 return true;
283}
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static bool b
struct MyStruct a[10]

◆ convert_compound_constructor()

static std::unique_ptr< Expression > SkSL::convert_compound_constructor ( const Context context,
Position  pos,
const Type type,
ExpressionArray  args 
)
static

Definition at line 28 of file SkSLConstructor.cpp.

31 {
32 SkASSERT(type.isVector() || type.isMatrix());
33
34 // The meaning of a compound constructor containing a single argument varies significantly in
35 // GLSL/SkSL, depending on the argument type.
36 if (args.size() == 1) {
37 std::unique_ptr<Expression>& argument = args.front();
38 if (type.isVector() && argument->type().isVector() &&
39 argument->type().componentType().matches(type.componentType()) &&
40 argument->type().slotCount() > type.slotCount()) {
41 // Casting a vector-type into a smaller matching vector-type is a slice in GLSL.
42 // We don't allow those casts in SkSL; recommend a swizzle instead.
43 // Only `.xy` and `.xyz` are valid recommendations here, because `.x` would imply a
44 // scalar(vector) cast, and nothing has more slots than `.xyzw`.
45 const char* swizzleHint;
46 switch (type.slotCount()) {
47 case 2: swizzleHint = "; use '.xy' instead"; break;
48 case 3: swizzleHint = "; use '.xyz' instead"; break;
49 default: swizzleHint = ""; SkDEBUGFAIL("unexpected slicing cast"); break;
50 }
51
52 context.fErrors->error(pos, "'" + argument->type().displayName() +
53 "' is not a valid parameter to '" + type.displayName() + "' constructor" +
54 swizzleHint);
55 return nullptr;
56 }
57
58 if (argument->type().isScalar()) {
59 // A constructor containing a single scalar is a splat (for vectors) or diagonal matrix
60 // (for matrices). It's legal regardless of the scalar's type, so synthesize an explicit
61 // conversion to the proper type. (This cast is a no-op if it's unnecessary; it can fail
62 // if we're casting a literal that exceeds the limits of the type.)
63 std::unique_ptr<Expression> typecast = ConstructorScalarCast::Convert(
64 context, pos, type.componentType(), std::move(args));
65 if (!typecast) {
66 return nullptr;
67 }
68
69 // Matrix-from-scalar creates a diagonal matrix; vector-from-scalar creates a splat.
70 return type.isMatrix()
71 ? ConstructorDiagonalMatrix::Make(context, pos, type, std::move(typecast))
72 : ConstructorSplat::Make(context, pos, type, std::move(typecast));
73 } else if (argument->type().isVector()) {
74 // A vector constructor containing a single vector with the same number of columns is a
75 // cast (e.g. float3 -> int3).
76 if (type.isVector() && argument->type().columns() == type.columns()) {
77 return ConstructorCompoundCast::Make(context, pos, type, std::move(argument));
78 }
79 } else if (argument->type().isMatrix()) {
80 // A matrix constructor containing a single matrix can be a resize, typecast, or both.
81 // GLSL lumps these into one category, but internally SkSL keeps them distinct.
82 if (type.isMatrix()) {
83 // First, handle type conversion. If the component types differ, synthesize the
84 // destination type with the argument's rows/columns. (This will be a no-op if it's
85 // already the right type.)
86 const Type& typecastType = type.componentType().toCompound(
87 context,
88 argument->type().columns(),
89 argument->type().rows());
90 argument = ConstructorCompoundCast::Make(context, pos, typecastType,
91 std::move(argument));
92
93 // Casting a matrix type into another matrix type is a resize.
94 return ConstructorMatrixResize::Make(context, pos, type,
95 std::move(argument));
96 }
97
98 // A vector constructor containing a single matrix can be compound construction if the
99 // matrix is 2x2 and the vector is 4-slot.
100 if (type.isVector() && type.columns() == 4 && argument->type().slotCount() == 4) {
101 // Casting a 2x2 matrix to a vector is a form of compound construction.
102 // First, reshape the matrix into a 4-slot vector of the same type.
103 const Type& vectorType = argument->type().componentType().toCompound(context,
104 /*columns=*/4,
105 /*rows=*/1);
106 std::unique_ptr<Expression> vecCtor =
107 ConstructorCompound::Make(context, pos, vectorType, std::move(args));
108
109 // Then, add a typecast to the result expression to ensure the types match.
110 // This will be a no-op if no typecasting is needed.
111 return ConstructorCompoundCast::Make(context, pos, type, std::move(vecCtor));
112 }
113 }
114 }
115
116 // For more complex cases, we walk the argument list and fix up the arguments as needed.
117 int expected = type.rows() * type.columns();
118 int actual = 0;
119 for (std::unique_ptr<Expression>& arg : args) {
120 if (!arg->type().isScalar() && !arg->type().isVector()) {
121 context.fErrors->error(pos, "'" + arg->type().displayName() +
122 "' is not a valid parameter to '" + type.displayName() + "' constructor");
123 return nullptr;
124 }
125
126 // Rely on Constructor::Convert to force this subexpression to the proper type. If it's a
127 // literal, this will make sure it's the right type of literal. If an expression of matching
128 // type, the expression will be returned as-is. If it's an expression of mismatched type,
129 // this adds a cast.
130 const Type& ctorType = type.componentType().toCompound(context, arg->type().columns(),
131 /*rows=*/1);
132 ExpressionArray ctorArg;
133 ctorArg.push_back(std::move(arg));
134 arg = Constructor::Convert(context, pos, ctorType, std::move(ctorArg));
135 if (!arg) {
136 return nullptr;
137 }
138 actual += ctorType.columns();
139 }
140
141 if (actual != expected) {
142 context.fErrors->error(pos, "invalid arguments to '" + type.displayName() +
143 "' constructor (expected " + std::to_string(expected) +
144 " scalars, but found " + std::to_string(actual) + ")");
145 return nullptr;
146 }
147
148 return ConstructorCompound::Make(context, pos, type, std::move(args));
149}
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
static std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap *src, const SkYUVAPixmaps *srcYUVA, const SkColorSpace *srcYUVAColorSpace, const SkJpegEncoder::Options &options)
Definition ref_ptr.h:256

◆ count_returns_at_end_of_control_flow()

static int SkSL::count_returns_at_end_of_control_flow ( const FunctionDefinition funcDef)
static

Definition at line 23 of file SkSLGetReturnComplexity.cpp.

23 {
24 class CountReturnsAtEndOfControlFlow : public ProgramVisitor {
25 public:
26 CountReturnsAtEndOfControlFlow(const FunctionDefinition& funcDef) {
27 this->visitProgramElement(funcDef);
28 }
29
30 bool visitExpression(const Expression& expr) override {
31 // Do not recurse into expressions.
32 return false;
33 }
34
35 bool visitStatement(const Statement& stmt) override {
36 switch (stmt.kind()) {
37 case Statement::Kind::kBlock: {
38 // Check only the last statement of a block.
39 const auto& block = stmt.as<Block>();
40 return block.children().size() &&
41 this->visitStatement(*block.children().back());
42 }
43 case Statement::Kind::kSwitch:
44 case Statement::Kind::kDo:
45 case Statement::Kind::kFor:
46 // Don't introspect switches or loop structures at all.
47 return false;
48
49 case Statement::Kind::kReturn:
50 ++fNumReturns;
51 [[fallthrough]];
52
53 default:
54 return INHERITED::visitStatement(stmt);
55 }
56 }
57
58 int fNumReturns = 0;
59 using INHERITED = ProgramVisitor;
60 };
61
62 return CountReturnsAtEndOfControlFlow{funcDef}.fNumReturns;
63}
#define INHERITED(method,...)
virtual bool visitStatement(typename T::Statement &statement)
virtual bool visitExpression(typename T::Expression &expression)
virtual bool visitProgramElement(typename T::ProgramElement &programElement)

◆ dead_function_predicate()

static bool SkSL::dead_function_predicate ( const ProgramElement element,
ProgramUsage usage 
)
static

Definition at line 25 of file SkSLEliminateDeadFunctions.cpp.

25 {
26 if (!element->is<FunctionDefinition>()) {
27 return false;
28 }
29 const FunctionDefinition& fn = element->as<FunctionDefinition>();
30 if (fn.declaration().isMain() || usage->get(fn.declaration()) > 0) {
31 return false;
32 }
33 // This function is about to be eliminated by remove_if; update ProgramUsage accordingly.
34 usage->remove(*element);
35 return true;
36}

◆ eliminate_dead_local_variables()

static bool SkSL::eliminate_dead_local_variables ( const Context context,
SkSpan< std::unique_ptr< ProgramElement > >  elements,
ProgramUsage usage 
)
static

Definition at line 39 of file SkSLEliminateDeadLocalVariables.cpp.

41 {
42 class DeadLocalVariableEliminator : public ProgramWriter {
43 public:
44 DeadLocalVariableEliminator(const Context& context, ProgramUsage* usage)
45 : fContext(context)
46 , fUsage(usage) {}
47
48 using ProgramWriter::visitProgramElement;
49
50 bool visitExpressionPtr(std::unique_ptr<Expression>& expr) override {
51 if (expr->is<BinaryExpression>()) {
52 // Search for expressions of the form `deadVar = anyExpression`.
53 BinaryExpression& binary = expr->as<BinaryExpression>();
54 if (VariableReference* assignedVar = binary.isAssignmentIntoVariable()) {
55 if (fDeadVariables.contains(assignedVar->variable())) {
56 // Replace `deadVar = anyExpression` with `anyExpression`.
57 fUsage->remove(expr.get());
58 expr = std::move(binary.right());
59 fUsage->add(expr.get());
60
61 // If `anyExpression` is now a lone ExpressionStatement, it's highly likely
62 // that we can eliminate it entirely. This flag will let us know to check.
63 fAssignmentWasEliminated = true;
64
65 // Re-process the newly cleaned-up expression. This lets us fully clean up
66 // gnarly assignments like `a = b = 123;` where both `a` and `b` are dead,
67 // or silly double-assignments like `a = a = 123;`.
68 return this->visitExpressionPtr(expr);
69 }
70 }
71 }
72 if (expr->is<VariableReference>()) {
73 SkASSERT(!fDeadVariables.contains(expr->as<VariableReference>().variable()));
74 }
75 return INHERITED::visitExpressionPtr(expr);
76 }
77
78 bool visitStatementPtr(std::unique_ptr<Statement>& stmt) override {
79 if (stmt->is<VarDeclaration>()) {
80 VarDeclaration& varDecl = stmt->as<VarDeclaration>();
81 const Variable* var = varDecl.var();
82 ProgramUsage::VariableCounts* counts = fUsage->fVariableCounts.find(var);
83 SkASSERT(counts);
84 SkASSERT(counts->fVarExists);
85 if (CanEliminate(var, *counts)) {
86 fDeadVariables.add(var);
87 if (var->initialValue()) {
88 // The variable has an initial-value expression, which might have side
89 // effects. ExpressionStatement::Make will preserve side effects, but
90 // replaces pure expressions with Nop.
91 fUsage->remove(stmt.get());
92 stmt = ExpressionStatement::Make(fContext, std::move(varDecl.value()));
93 fUsage->add(stmt.get());
94 } else {
95 // The variable has no initial-value and can be cleanly eliminated.
96 fUsage->remove(stmt.get());
97 stmt = Nop::Make();
98 }
99 fMadeChanges = true;
100
101 // Re-process the newly cleaned-up statement. This lets us fully clean up
102 // gnarly assignments like `a = b = 123;` where both `a` and `b` are dead,
103 // or silly double-assignments like `a = a = 123;`.
104 return this->visitStatementPtr(stmt);
105 }
106 }
107
108 bool result = INHERITED::visitStatementPtr(stmt);
109
110 // If we eliminated an assignment above, we may have left behind an inert
111 // ExpressionStatement.
112 if (fAssignmentWasEliminated) {
113 fAssignmentWasEliminated = false;
114 if (stmt->is<ExpressionStatement>()) {
115 ExpressionStatement& exprStmt = stmt->as<ExpressionStatement>();
116 if (!Analysis::HasSideEffects(*exprStmt.expression())) {
117 // The expression-statement was inert; eliminate it entirely.
118 fUsage->remove(&exprStmt);
119 stmt = Nop::Make();
120 }
121 }
122 }
123
124 return result;
125 }
126
127 static bool CanEliminate(const Variable* var, const ProgramUsage::VariableCounts& counts) {
128 return counts.fVarExists && !counts.fRead && var->storage() == VariableStorage::kLocal;
129 }
130
131 bool fMadeChanges = false;
132 const Context& fContext;
133 ProgramUsage* fUsage;
134 THashSet<const Variable*> fDeadVariables;
135 bool fAssignmentWasEliminated = false;
136
137 using INHERITED = ProgramWriter;
138 };
139
140 DeadLocalVariableEliminator visitor{context, usage};
141
142 for (auto& [var, counts] : usage->fVariableCounts) {
143 if (DeadLocalVariableEliminator::CanEliminate(var, counts)) {
144 // This program contains at least one dead local variable.
145 // Scan the program for any dead local variables and eliminate them all.
146 for (std::unique_ptr<ProgramElement>& pe : elements) {
147 if (pe->is<FunctionDefinition>()) {
148 visitor.visitProgramElement(*pe);
149 }
150 }
151 break;
152 }
153 }
154
155 return visitor.fMadeChanges;
156}
static std::unique_ptr< Statement > Make(const Context &context, std::unique_ptr< Expression > expr)
static std::unique_ptr< Statement > Make()
Definition SkSLNop.h:26
bool visitExpressionPtr(std::unique_ptr< Expression > &e) override
bool visitStatementPtr(std::unique_ptr< Statement > &s) override
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 counts
Definition switches.h:239

◆ eliminate_empty_statements()

static void SkSL::eliminate_empty_statements ( SkSpan< std::unique_ptr< ProgramElement > >  elements)
static

Definition at line 27 of file SkSLEliminateEmptyStatements.cpp.

27 {
28 class EmptyStatementEliminator : public ProgramWriter {
29 public:
30 bool visitExpressionPtr(std::unique_ptr<Expression>& expr) override {
31 // We don't need to look inside expressions at all.
32 return false;
33 }
34
35 bool visitStatementPtr(std::unique_ptr<Statement>& stmt) override {
36 // Work from the innermost blocks to the outermost.
37 INHERITED::visitStatementPtr(stmt);
38
39 if (stmt->is<Block>()) {
40 StatementArray& children = stmt->as<Block>().children();
41 auto iter = std::remove_if(children.begin(), children.end(),
42 [](std::unique_ptr<Statement>& stmt) {
43 return stmt->isEmpty();
44 });
45 children.resize(std::distance(children.begin(), iter));
46 }
47
48 // We always check the entire program.
49 return false;
50 }
51
52 using INHERITED = ProgramWriter;
53 };
54
55 for (std::unique_ptr<ProgramElement>& pe : elements) {
56 if (pe->is<FunctionDefinition>()) {
57 EmptyStatementEliminator visitor;
58 visitor.visitStatementPtr(pe->as<FunctionDefinition>().body());
59 }
60 }
61}

◆ eliminate_no_op_boolean()

static std::unique_ptr< Expression > SkSL::eliminate_no_op_boolean ( Position  pos,
const Expression left,
Operator  op,
const Expression right 
)
static

Definition at line 52 of file SkSLConstantFolder.cpp.

55 {
56 bool rightVal = right.as<Literal>().boolValue();
57
58 // Detect no-op Boolean expressions and optimize them away.
59 if ((op.kind() == Operator::Kind::LOGICALAND && rightVal) || // (expr && true) -> (expr)
60 (op.kind() == Operator::Kind::LOGICALOR && !rightVal) || // (expr || false) -> (expr)
61 (op.kind() == Operator::Kind::LOGICALXOR && !rightVal) || // (expr ^^ false) -> (expr)
62 (op.kind() == Operator::Kind::EQEQ && rightVal) || // (expr == true) -> (expr)
63 (op.kind() == Operator::Kind::NEQ && !rightVal)) { // (expr != false) -> (expr)
64
65 return left.clone(pos);
66 }
67
68 return nullptr;
69}
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)

◆ eliminate_unnecessary_braces()

static void SkSL::eliminate_unnecessary_braces ( SkSpan< std::unique_ptr< ProgramElement > >  elements)
static

Definition at line 31 of file SkSLEliminateUnnecessaryBraces.cpp.

31 {
32 class UnnecessaryBraceEliminator : public ProgramWriter {
33 public:
34 bool visitExpressionPtr(std::unique_ptr<Expression>& expr) override {
35 // We don't need to look inside expressions at all.
36 return false;
37 }
38
39 bool visitStatementPtr(std::unique_ptr<Statement>& stmt) override {
40 // Work from the innermost blocks to the outermost.
41 INHERITED::visitStatementPtr(stmt);
42
43 switch (stmt->kind()) {
44 case StatementKind::kIf: {
45 IfStatement& ifStmt = stmt->as<IfStatement>();
46 EliminateBracesFrom(ifStmt.ifTrue());
47 EliminateBracesFrom(ifStmt.ifFalse());
48 break;
49 }
51 ForStatement& forStmt = stmt->as<ForStatement>();
52 EliminateBracesFrom(forStmt.statement());
53 break;
54 }
55 case StatementKind::kDo: {
56 DoStatement& doStmt = stmt->as<DoStatement>();
57 EliminateBracesFrom(doStmt.statement());
58 break;
59 }
60 default:
61 break;
62 }
63
64 // We always check the entire program.
65 return false;
66 }
67
68 static void EliminateBracesFrom(std::unique_ptr<Statement>& stmt) {
69 if (!stmt || !stmt->is<Block>()) {
70 return;
71 }
72 Block& block = stmt->as<Block>();
73 std::unique_ptr<Statement>* usefulStmt = nullptr;
74 for (std::unique_ptr<Statement>& childStmt : block.children()) {
75 if (childStmt->isEmpty()) {
76 continue;
77 }
78 if (usefulStmt) {
79 // We found two non-empty statements. We can't eliminate braces from
80 // this block.
81 return;
82 }
83 // We found one non-empty statement.
84 usefulStmt = &childStmt;
85 }
86
87 if (!usefulStmt) {
88 // This block held zero useful statements. Replace the block with a nop.
89 stmt = Nop::Make();
90 } else {
91 // This block held one useful statement. Replace the block with that statement.
92 stmt = std::move(*usefulStmt);
93 }
94 }
95
96 using INHERITED = ProgramWriter;
97 };
98
99 for (std::unique_ptr<ProgramElement>& pe : elements) {
100 if (pe->is<FunctionDefinition>()) {
101 UnnecessaryBraceEliminator visitor;
102 visitor.visitStatementPtr(pe->as<FunctionDefinition>().body());
103 }
104 }
105}

◆ eliminate_unreachable_code()

static void SkSL::eliminate_unreachable_code ( SkSpan< std::unique_ptr< ProgramElement > >  elements,
ProgramUsage usage 
)
static

Definition at line 35 of file SkSLEliminateUnreachableCode.cpp.

36 {
37 class UnreachableCodeEliminator : public ProgramWriter {
38 public:
39 UnreachableCodeEliminator(ProgramUsage* usage) : fUsage(usage) {
40 fFoundFunctionExit.push_back(false);
41 fFoundBlockExit.push_back(false);
42 }
43
44 bool visitExpressionPtr(std::unique_ptr<Expression>& expr) override {
45 // We don't need to look inside expressions at all.
46 return false;
47 }
48
49 bool visitStatementPtr(std::unique_ptr<Statement>& stmt) override {
50 if (fFoundFunctionExit.back() || fFoundBlockExit.back()) {
51 // If we already found an exit in this section, anything beyond it is dead code.
52 if (!stmt->is<Nop>()) {
53 // Eliminate the dead statement by substituting a Nop.
54 fUsage->remove(stmt.get());
55 stmt = Nop::Make();
56 }
57 return false;
58 }
59
60 switch (stmt->kind()) {
61 case Statement::Kind::kReturn:
62 case Statement::Kind::kDiscard:
63 // We found a function exit on this path.
64 fFoundFunctionExit.back() = true;
65 break;
66
67 case Statement::Kind::kBreak:
68 // A `break` statement can either be breaking out of a loop or terminating an
69 // individual switch case. We treat both cases the same way: they only apply
70 // to the statements associated with the parent statement (i.e. enclosing loop
71 // block / preceding case label).
72 case Statement::Kind::kContinue:
73 fFoundBlockExit.back() = true;
74 break;
75
76 case Statement::Kind::kExpression:
77 case Statement::Kind::kNop:
78 case Statement::Kind::kVarDeclaration:
79 // These statements don't affect control flow.
80 break;
81
82 case Statement::Kind::kBlock:
83 // Blocks are on the straight-line path and don't affect control flow.
84 return INHERITED::visitStatementPtr(stmt);
85
86 case Statement::Kind::kDo: {
87 // Function-exits are allowed to propagate outside of a do-loop, because it
88 // always executes its body at least once.
89 fFoundBlockExit.push_back(false);
90 bool result = INHERITED::visitStatementPtr(stmt);
91 fFoundBlockExit.pop_back();
92 return result;
93 }
94 case Statement::Kind::kFor: {
95 // Function-exits are not allowed to propagate out, because a for-loop or while-
96 // loop could potentially run zero times.
97 fFoundFunctionExit.push_back(false);
98 fFoundBlockExit.push_back(false);
99 bool result = INHERITED::visitStatementPtr(stmt);
100 fFoundBlockExit.pop_back();
101 fFoundFunctionExit.pop_back();
102 return result;
103 }
104 case Statement::Kind::kIf: {
105 // This statement is conditional and encloses two inner sections of code.
106 // If both sides contain a function-exit or loop-exit, that exit is allowed to
107 // propagate out.
108 IfStatement& ifStmt = stmt->as<IfStatement>();
109
110 fFoundFunctionExit.push_back(false);
111 fFoundBlockExit.push_back(false);
112 bool result = (ifStmt.ifTrue() && this->visitStatementPtr(ifStmt.ifTrue()));
113 bool foundFunctionExitOnTrue = fFoundFunctionExit.back();
114 bool foundLoopExitOnTrue = fFoundBlockExit.back();
115 fFoundFunctionExit.pop_back();
116 fFoundBlockExit.pop_back();
117
118 fFoundFunctionExit.push_back(false);
119 fFoundBlockExit.push_back(false);
120 result |= (ifStmt.ifFalse() && this->visitStatementPtr(ifStmt.ifFalse()));
121 bool foundFunctionExitOnFalse = fFoundFunctionExit.back();
122 bool foundLoopExitOnFalse = fFoundBlockExit.back();
123 fFoundFunctionExit.pop_back();
124 fFoundBlockExit.pop_back();
125
126 fFoundFunctionExit.back() |= foundFunctionExitOnTrue &&
127 foundFunctionExitOnFalse;
128 fFoundBlockExit.back() |= foundLoopExitOnTrue &&
129 foundLoopExitOnFalse;
130 return result;
131 }
132 case Statement::Kind::kSwitch: {
133 // In switch statements we consider unreachable code on a per-case basis.
134 SwitchStatement& sw = stmt->as<SwitchStatement>();
135 bool result = false;
136
137 // Tracks whether we found at least one case that doesn't lead to a return
138 // statement (potentially via fallthrough).
139 bool foundCaseWithoutReturn = false;
140 bool hasDefault = false;
141 for (std::unique_ptr<Statement>& c : sw.cases()) {
142 // We eliminate unreachable code within the statements of the individual
143 // case. Breaks are not allowed to propagate outside the case statement
144 // itself. Function returns are allowed to propagate out only if all cases
145 // have a return AND one of the cases is default (so that we know at least
146 // one of the branches will be taken). This is similar to how we handle if
147 // statements above.
148 fFoundFunctionExit.push_back(false);
149 fFoundBlockExit.push_back(false);
150
151 SwitchCase& sc = c->as<SwitchCase>();
152 result |= this->visitStatementPtr(sc.statement());
153
154 // When considering whether a case has a return we can propagate, we
155 // assume the following:
156 // 1. The default case is always placed last in a switch statement and
157 // it is the last possible label reachable via fallthrough. Thus if
158 // it does not contain a return statement, then we don't propagate a
159 // function return.
160 // 2. In all other cases we prevent the return from propagating only if
161 // we encounter a break statement. If no return or break is found,
162 // we defer the decision to the fallthrough case. We won't propagate
163 // a return unless we eventually encounter a default label.
164 //
165 // See resources/sksl/shared/SwitchWithEarlyReturn.sksl for test cases that
166 // exercise this.
167 if (sc.isDefault()) {
168 foundCaseWithoutReturn |= !fFoundFunctionExit.back();
169 hasDefault = true;
170 } else {
171 // We can only be sure that a case does not lead to a return if it
172 // doesn't fallthrough.
173 foundCaseWithoutReturn |=
174 (!fFoundFunctionExit.back() && fFoundBlockExit.back());
175 }
176
177 fFoundFunctionExit.pop_back();
178 fFoundBlockExit.pop_back();
179 }
180
181 fFoundFunctionExit.back() |= !foundCaseWithoutReturn && hasDefault;
182 return result;
183 }
184 case Statement::Kind::kSwitchCase:
185 // We should never hit this case as switch cases are handled in the previous
186 // case.
188 }
189
190 return false;
191 }
192
193 ProgramUsage* fUsage;
194 STArray<32, bool> fFoundFunctionExit;
195 STArray<32, bool> fFoundBlockExit;
196
197 using INHERITED = ProgramWriter;
198 };
199
200 for (std::unique_ptr<ProgramElement>& pe : elements) {
201 if (pe->is<FunctionDefinition>()) {
202 UnreachableCodeEliminator visitor{usage};
203 visitor.visitStatementPtr(pe->as<FunctionDefinition>().body());
204 }
205 }
206}

◆ error_on_divide_by_zero()

static bool SkSL::error_on_divide_by_zero ( const Context context,
Position  pos,
Operator  op,
const Expression right 
)
static

Definition at line 423 of file SkSLConstantFolder.cpp.

424 {
425 switch (op.kind()) {
426 case Operator::Kind::SLASH:
427 case Operator::Kind::SLASHEQ:
428 case Operator::Kind::PERCENT:
429 case Operator::Kind::PERCENTEQ:
431 context.fErrors->error(pos, "division by zero");
432 return true;
433 }
434 return false;
435 default:
436 return false;
437 }
438}
static bool contains_constant_zero(const Expression &expr)

◆ evaluate_3_way_intrinsic()

static std::unique_ptr< Expression > SkSL::evaluate_3_way_intrinsic ( const Context context,
const IntrinsicArguments arguments,
const Type returnType,
EvaluateFn  eval 
)
static

Definition at line 319 of file SkSLFunctionCall.cpp.

322 {
323 SkASSERT(arguments[0]);
324 SkASSERT(arguments[1]);
325 SkASSERT(arguments[2]);
326 const Type& type = arguments[0]->type().componentType();
327
328 if (type.isFloat()) {
329 type_check_expression<float>(*arguments[0]);
330 type_check_expression<float>(*arguments[1]);
331 type_check_expression<float>(*arguments[2]);
332 } else if (type.isInteger()) {
333 type_check_expression<SKSL_INT>(*arguments[0]);
334 type_check_expression<SKSL_INT>(*arguments[1]);
335 type_check_expression<SKSL_INT>(*arguments[2]);
336 } else {
337 SkDEBUGFAILF("unsupported type %s", type.description().c_str());
338 return nullptr;
339 }
340
341 return evaluate_n_way_intrinsic(context, arguments[0], arguments[1], arguments[2],
342 returnType, eval);
343}
#define SkDEBUGFAILF(fmt,...)
Definition SkAssert.h:119
static std::unique_ptr< Expression > evaluate_n_way_intrinsic(const Context &context, const Expression *arg0, const Expression *arg1, const Expression *arg2, const Type &returnType, EvaluateFn eval)

◆ evaluate_intrinsic()

template<typename T >
static std::unique_ptr< Expression > SkSL::evaluate_intrinsic ( const Context context,
const IntrinsicArguments arguments,
const Type returnType,
EvaluateFn  eval 
)
static

Definition at line 264 of file SkSLFunctionCall.cpp.

267 {
268 SkASSERT(arguments[0]);
269 SkASSERT(!arguments[1]);
270 type_check_expression<T>(*arguments[0]);
271
272 return evaluate_n_way_intrinsic(context, arguments[0], /*arg1=*/nullptr, /*arg2=*/nullptr,
273 returnType, eval);
274}

◆ evaluate_intrinsic_numeric()

static std::unique_ptr< Expression > SkSL::evaluate_intrinsic_numeric ( const Context context,
const IntrinsicArguments arguments,
const Type returnType,
EvaluateFn  eval 
)
static

Definition at line 276 of file SkSLFunctionCall.cpp.

279 {
280 SkASSERT(arguments[0]);
281 SkASSERT(!arguments[1]);
282 const Type& type = arguments[0]->type().componentType();
283
284 if (type.isFloat()) {
285 return evaluate_intrinsic<float>(context, arguments, returnType, eval);
286 }
287 if (type.isInteger()) {
288 return evaluate_intrinsic<SKSL_INT>(context, arguments, returnType, eval);
289 }
290
291 SkDEBUGFAILF("unsupported type %s", type.description().c_str());
292 return nullptr;
293}

◆ evaluate_n_way_intrinsic()

static std::unique_ptr< Expression > SkSL::evaluate_n_way_intrinsic ( const Context context,
const Expression arg0,
const Expression arg1,
const Expression arg2,
const Type returnType,
EvaluateFn  eval 
)
static

Definition at line 206 of file SkSLFunctionCall.cpp.

211 {
212 // Takes up to three arguments and evaluates all of them, left-to-right, in tandem.
213 // Equivalent to constructing a new compound value containing the results from:
214 // eval(arg0.x, arg1.x, arg2.x),
215 // eval(arg0.y, arg1.y, arg2.y),
216 // eval(arg0.z, arg1.z, arg2.z),
217 // eval(arg0.w, arg1.w, arg2.w)
218 //
219 // If an argument is null, zero is passed to the evaluation function. If the arguments are a mix
220 // of scalars and compounds, scalars are interpreted as a compound containing the same value for
221 // every component.
222
223 double minimumValue = returnType.componentType().minimumValue();
224 double maximumValue = returnType.componentType().maximumValue();
225 int slots = returnType.slotCount();
226 double array[16];
227
228 int arg0Index = 0;
229 int arg1Index = 0;
230 int arg2Index = 0;
231 for (int index = 0; index < slots; ++index) {
232 std::optional<double> arg0Value = arg0->getConstantValue(arg0Index);
233 arg0Index += arg0->type().isScalar() ? 0 : 1;
234 SkASSERT(arg0Value.has_value());
235
236 std::optional<double> arg1Value = 0.0;
237 if (arg1) {
238 arg1Value = arg1->getConstantValue(arg1Index);
239 arg1Index += arg1->type().isScalar() ? 0 : 1;
240 SkASSERT(arg1Value.has_value());
241 }
242
243 std::optional<double> arg2Value = 0.0;
244 if (arg2) {
245 arg2Value = arg2->getConstantValue(arg2Index);
246 arg2Index += arg2->type().isScalar() ? 0 : 1;
247 SkASSERT(arg2Value.has_value());
248 }
249
250 array[index] = eval(*arg0Value, *arg1Value, *arg2Value);
251
252 if (array[index] >= minimumValue && array[index] <= maximumValue) {
253 // This result will fit inside the return type.
254 } else {
255 // The value is outside the float range or is NaN (all if-checks fail); do not optimize.
256 return nullptr;
257 }
258 }
259
260 return ConstructorCompound::MakeFromConstants(context, arg0->fPosition, returnType, array);
261}

◆ evaluate_pairwise_intrinsic()

static std::unique_ptr< Expression > SkSL::evaluate_pairwise_intrinsic ( const Context context,
const IntrinsicArguments arguments,
const Type returnType,
EvaluateFn  eval 
)
static

Definition at line 295 of file SkSLFunctionCall.cpp.

298 {
299 SkASSERT(arguments[0]);
300 SkASSERT(arguments[1]);
301 SkASSERT(!arguments[2]);
302 const Type& type = arguments[0]->type().componentType();
303
304 if (type.isFloat()) {
305 type_check_expression<float>(*arguments[0]);
306 type_check_expression<float>(*arguments[1]);
307 } else if (type.isInteger()) {
308 type_check_expression<SKSL_INT>(*arguments[0]);
309 type_check_expression<SKSL_INT>(*arguments[1]);
310 } else {
311 SkDEBUGFAILF("unsupported type %s", type.description().c_str());
312 return nullptr;
313 }
314
315 return evaluate_n_way_intrinsic(context, arguments[0], arguments[1], /*arg2=*/nullptr,
316 returnType, eval);
317}

◆ extract_field()

static std::unique_ptr< Expression > SkSL::extract_field ( Position  pos,
const ConstructorStruct ctor,
int  fieldIndex 
)
static

Definition at line 65 of file SkSLFieldAccess.cpp.

67 {
68 // Confirm that the fields that are being removed are side-effect free.
69 const ExpressionArray& args = ctor.arguments();
70 int numFields = args.size();
71 for (int index = 0; index < numFields; ++index) {
72 if (fieldIndex == index) {
73 continue;
74 }
75 if (Analysis::HasSideEffects(*args[index])) {
76 return nullptr;
77 }
78 }
79
80 // Return the desired field.
81 return args[fieldIndex]->clone(pos);
82}

◆ extract_matrix()

static void SkSL::extract_matrix ( const Expression expr,
float  mat[16] 
)
static

Definition at line 628 of file SkSLFunctionCall.cpp.

628 {
629 size_t numSlots = expr->type().slotCount();
630 for (size_t index = 0; index < numSlots; ++index) {
631 mat[index] = *expr->getConstantValue(index);
632 }
633}

◆ find_duplicate_case_values()

static std::forward_list< const SwitchCase * > SkSL::find_duplicate_case_values ( const StatementArray cases)
static

Definition at line 41 of file SkSLSwitchStatement.cpp.

42 {
43 std::forward_list<const SwitchCase*> duplicateCases;
44 THashSet<SKSL_INT> intValues;
45 bool foundDefault = false;
46
47 for (const std::unique_ptr<Statement>& stmt : cases) {
48 const SwitchCase* sc = &stmt->as<SwitchCase>();
49 if (sc->isDefault()) {
50 if (foundDefault) {
51 duplicateCases.push_front(sc);
52 continue;
53 }
54 foundDefault = true;
55 } else {
56 SKSL_INT value = sc->value();
57 if (intValues.contains(value)) {
58 duplicateCases.push_front(sc);
59 continue;
60 }
61 intValues.add(value);
62 }
63 }
64
65 return duplicateCases;
66}
int64_t SKSL_INT
Definition SkSLDefines.h:16
SKSL_INT value() const
bool isDefault() const
void add(T item)
Definition SkTHash.h:573
bool contains(const T &item) const
Definition SkTHash.h:576

◆ find_existing_declaration()

static bool SkSL::find_existing_declaration ( const Context context,
Position  pos,
ModifierFlags  modifierFlags,
IntrinsicKind  intrinsicKind,
std::string_view  name,
TArray< std::unique_ptr< Variable > > &  parameters,
Position  returnTypePos,
const Type returnType,
FunctionDeclaration **  outExistingDecl 
)
static

Checks for a previously existing declaration of this function, reporting errors if there is an incompatible symbol. Returns true and sets outExistingDecl to point to the existing declaration (or null if none) on success, returns false on error.

Definition at line 346 of file SkSLFunctionDeclaration.cpp.

354 {
355 auto invalidDeclDescription = [&]() -> std::string {
356 TArray<Variable*> paramPtrs;
357 paramPtrs.reserve_exact(parameters.size());
358 for (std::unique_ptr<Variable>& param : parameters) {
359 paramPtrs.push_back(param.get());
360 }
361 return FunctionDeclaration(context,
362 pos,
363 modifierFlags,
364 name,
365 std::move(paramPtrs),
366 returnType,
367 intrinsicKind)
368 .description();
369 };
370
371 ErrorReporter& errors = *context.fErrors;
372 Symbol* entry = context.fSymbolTable->findMutable(name);
373 *outExistingDecl = nullptr;
374 if (entry) {
375 if (!entry->is<FunctionDeclaration>()) {
376 errors.error(pos, "symbol '" + std::string(name) + "' was already defined");
377 return false;
378 }
379 for (FunctionDeclaration* other = &entry->as<FunctionDeclaration>(); other;
380 other = other->mutableNextOverload()) {
381 SkASSERT(name == other->name());
382 if (!parameters_match(parameters, other->parameters())) {
383 continue;
384 }
385 if (!type_generically_matches(*returnType, other->returnType())) {
386 errors.error(returnTypePos, "functions '" + invalidDeclDescription() + "' and '" +
387 other->description() + "' differ only in return type");
388 return false;
389 }
390 for (int i = 0; i < parameters.size(); i++) {
391 if (parameters[i]->modifierFlags() != other->parameters()[i]->modifierFlags() ||
392 parameters[i]->layout() != other->parameters()[i]->layout()) {
393 errors.error(parameters[i]->fPosition,
394 "modifiers on parameter " + std::to_string(i + 1) +
395 " differ between declaration and definition");
396 return false;
397 }
398 }
399 if (other->definition() || other->isIntrinsic() ||
400 modifierFlags != other->modifierFlags()) {
401 errors.error(pos, "duplicate definition of '" + invalidDeclDescription() + "'");
402 return false;
403 }
404 *outExistingDecl = other;
405 break;
406 }
407 if (!*outExistingDecl && entry->as<FunctionDeclaration>().isMain()) {
408 errors.error(pos, "duplicate definition of 'main'");
409 return false;
410 }
411 }
412 return true;
413}
Symbol * findMutable(std::string_view name) const
const char * name
Definition fuchsia.cc:50
static bool type_generically_matches(const Type &concreteType, const Type &maybeGenericType)
static bool parameters_match(SkSpan< const std::unique_ptr< Variable > > params, SkSpan< Variable *const > otherParams)

◆ find_generic_index()

static int SkSL::find_generic_index ( const Type concreteType,
const Type genericType,
bool  allowNarrowing 
)
static

Given a concrete type (float3) and a generic type ($genType), returns the index of the concrete type within the generic type's typelist. Returns -1 if there is no match.

Definition at line 270 of file SkSLFunctionDeclaration.cpp.

272 {
273 SkSpan<const Type* const> genericTypes = genericType.coercibleTypes();
274 for (size_t index = 0; index < genericTypes.size(); ++index) {
275 if (concreteType.canCoerceTo(*genericTypes[index], allowNarrowing)) {
276 return index;
277 }
278 }
279 return -1;
280}
virtual SkSpan< const Type *const > coercibleTypes() const
Definition SkSLType.h:476
bool canCoerceTo(const Type &other, bool allowNarrowing) const
Definition SkSLType.h:388
constexpr size_t size() const
Definition SkSpan_impl.h:95

◆ find_rt_adjust_index()

static std::optional< int > SkSL::find_rt_adjust_index ( SkSpan< const Field fields)
static

Definition at line 41 of file SkSLInterfaceBlock.cpp.

41 {
42 for (size_t index = 0; index < fields.size(); ++index) {
43 const SkSL::Field& f = fields[index];
44 if (f.fName == SkSL::Compiler::RTADJUST_NAME) {
45 return index;
46 }
47 }
48
49 return std::nullopt;
50}
static constexpr const char RTADJUST_NAME[]

◆ FindIntrinsicKind()

IntrinsicKind SkSL::FindIntrinsicKind ( std::string_view  functionName)

Definition at line 26 of file SkSLIntrinsicList.cpp.

26 {
27 if (skstd::starts_with(functionName, '$')) {
28 functionName.remove_prefix(1);
29 }
30
31 const IntrinsicMap& intrinsicMap = GetIntrinsicMap();
32 IntrinsicKind* kind = intrinsicMap.find(functionName);
33 return kind ? *kind : kNotIntrinsic;
34}
constexpr bool starts_with(std::string_view str, std::string_view prefix)

◆ fold_expression()

static std::unique_ptr< Expression > SkSL::fold_expression ( Position  pos,
double  result,
const Type resultType 
)
static

Definition at line 653 of file SkSLConstantFolder.cpp.

655 {
656 if (resultType->isNumber()) {
657 if (result >= resultType->minimumValue() && result <= resultType->maximumValue()) {
658 // This result will fit inside its type.
659 } else {
660 // The value is outside the range or is NaN (all if-checks fail); do not optimize.
661 return nullptr;
662 }
663 }
664
665 return Literal::Make(pos, result, resultType);
666}
bool isNumber() const
Definition SkSLType.h:304

◆ get_storage_class()

static SpvStorageClass_ SkSL::get_storage_class ( const Expression expr)
static

Definition at line 3000 of file SkSLSPIRVCodeGenerator.cpp.

3000 {
3001 switch (expr.kind()) {
3002 case Expression::Kind::kVariableReference: {
3003 const Variable& var = *expr.as<VariableReference>().variable();
3004 if (var.storage() != Variable::Storage::kGlobal) {
3006 }
3007 return get_storage_class_for_global_variable(var, SpvStorageClassPrivate);
3008 }
3009 case Expression::Kind::kFieldAccess:
3010 return get_storage_class(*expr.as<FieldAccess>().base());
3011 case Expression::Kind::kIndex:
3012 return get_storage_class(*expr.as<IndexExpression>().base());
3013 default:
3015 }
3016}
Kind kind() const
Storage storage() const
static SpvStorageClass_ get_storage_class(const Expression &expr)
@ SpvStorageClassFunction
Definition spirv.h:134
@ SpvStorageClassPrivate
Definition spirv.h:133

◆ get_storage_class_for_global_variable()

static SpvStorageClass_ SkSL::get_storage_class_for_global_variable ( const Variable var,
SpvStorageClass_  fallbackStorageClass 
)
static

Definition at line 2959 of file SkSLSPIRVCodeGenerator.cpp.

2960 {
2961 SkASSERT(var.storage() == Variable::Storage::kGlobal);
2962
2963 if (var.type().typeKind() == Type::TypeKind::kSampler ||
2964 var.type().typeKind() == Type::TypeKind::kSeparateSampler ||
2965 var.type().typeKind() == Type::TypeKind::kTexture) {
2967 }
2968
2969 const Layout& layout = var.layout();
2970 ModifierFlags flags = var.modifierFlags();
2971 if (flags & ModifierFlag::kIn) {
2972 SkASSERT(!(layout.fFlags & LayoutFlag::kPushConstant));
2973 return SpvStorageClassInput;
2974 }
2975 if (flags & ModifierFlag::kOut) {
2976 SkASSERT(!(layout.fFlags & LayoutFlag::kPushConstant));
2977 return SpvStorageClassOutput;
2978 }
2979 if (flags.isUniform()) {
2980 if (layout.fFlags & LayoutFlag::kPushConstant) {
2982 }
2984 }
2985 if (flags.isBuffer()) {
2986 // Note: In SPIR-V 1.3, a storage buffer can be declared with the "StorageBuffer"
2987 // storage class and the "Block" decoration and the <1.3 approach we use here ("Uniform"
2988 // storage class and the "BufferBlock" decoration) is deprecated. Since we target SPIR-V
2989 // 1.0, we have to use the deprecated approach which is well supported in Vulkan and
2990 // addresses SkSL use cases (notably SkSL currently doesn't support pointer features that
2991 // would benefit from SPV_KHR_variable_pointers capabilities).
2993 }
2994 if (flags.isWorkgroup()) {
2996 }
2997 return fallbackStorageClass;
2998}
ModifierFlags modifierFlags() const
FlutterSemanticsFlag flags
@ SpvStorageClassUniformConstant
Definition spirv.h:127
@ SpvStorageClassPushConstant
Definition spirv.h:136
@ SpvStorageClassUniform
Definition spirv.h:129
@ SpvStorageClassInput
Definition spirv.h:128
@ SpvStorageClassWorkgroup
Definition spirv.h:131
@ SpvStorageClassOutput
Definition spirv.h:130

◆ get_struct_definitions_from_module()

static void SkSL::get_struct_definitions_from_module ( Program program,
const Module module,
std::vector< const ProgramElement * > *  addedStructDefs 
)
static

Definition at line 37 of file SkSLFindAndDeclareBuiltinStructs.cpp.

40 {
41 // We want to start at the root module and work our way towards the Program, so that structs
42 // are added to the program in the same order that they appear in the Module hierarchy.
43 if (module.fParent) {
44 get_struct_definitions_from_module(program, *module.fParent, addedStructDefs);
45 }
46
47 // Find StructDefinitions from this Module that are used by the program, and copy them into our
48 // array of shared elements.
49 for (const std::unique_ptr<ProgramElement>& elem : module.fElements) {
50 if (elem->is<StructDefinition>()) {
51 const StructDefinition& structDef = elem->as<StructDefinition>();
52 int* structCount = program.fUsage->fStructCounts.find(&structDef.type());
53 if (structCount && *structCount > 0) {
54 addedStructDefs->push_back(&structDef);
55 }
56 }
57 }
58}
static void get_struct_definitions_from_module(Program &program, const Module &module, std::vector< const ProgramElement * > *addedStructDefs)
const Module * fParent
std::unique_ptr< ProgramUsage > fUsage

◆ get_thread_local_memory_pool()

static MemoryPool * SkSL::get_thread_local_memory_pool ( )
static

Definition at line 18 of file SkSLPool.cpp.

18 {
19 return sMemPool;
20}
static thread_local MemoryPool * sMemPool
Definition SkSLPool.cpp:16

◆ get_top_level_symbol_table()

static SymbolTable * SkSL::get_top_level_symbol_table ( const FunctionDeclaration anyFunc)
static

Definition at line 4878 of file SkSLSPIRVCodeGenerator.cpp.

4878 {
4879 return anyFunc.definition()->body()->as<Block>().symbolTable()->fParent;
4880}
const FunctionDefinition * definition() const
std::unique_ptr< Statement > & body()

◆ get_transition()

static State SkSL::get_transition ( uint8_t  transition,
State  state 
)
static

Definition at line 763 of file SkSLLexer.cpp.

763 {
764 IndexEntry index = kIndices[state];
765 if (index < 0) {
766 return kFull[~index].data[transition];
767 }
768 const CompactEntry& entry = kCompact[index];
769 int v = entry.data[transition >> 2];
770 v >>= 2 * (transition & 3);
771 v &= 3;
772 v *= 9;
773 return (entry.values >> v) & 511;
774}
static const uint16_t kIndices[]
@ kFull
modifies glyph outlines for maximum constrast
AtkStateType state
int16_t IndexEntry
Definition SkSLLexer.cpp:24
uint8_t data[18]
Definition SkSLLexer.cpp:30

◆ GetIntrinsicMap()

const IntrinsicMap & SkSL::GetIntrinsicMap ( )

Definition at line 16 of file SkSLIntrinsicList.cpp.

16 {
17 #define SKSL_INTRINSIC(name) {#name, k_##name##_IntrinsicKind},
18 static const SkNoDestructor<IntrinsicMap> kAllIntrinsics(IntrinsicMap{
20 });
21 #undef SKSL_INTRINSIC
22
23 return *kAllIntrinsics;
24}

◆ has_compile_time_constant_arguments()

static bool SkSL::has_compile_time_constant_arguments ( const ExpressionArray arguments)
static

Definition at line 53 of file SkSLFunctionCall.cpp.

53 {
54 for (const std::unique_ptr<Expression>& arg : arguments) {
55 const Expression* expr = ConstantFolder::GetConstantValueForVariable(*arg);
56 if (!Analysis::IsCompileTimeConstant(*expr)) {
57 return false;
58 }
59 }
60 return true;
61}

◆ hoist_vardecl_symbols_into_outer_scope()

static void SkSL::hoist_vardecl_symbols_into_outer_scope ( const Context context,
const Block initBlock,
SymbolTable innerSymbols,
SymbolTable hoistedSymbols 
)
static

Definition at line 70 of file SkSLForStatement.cpp.

73 {
74 class SymbolHoister : public ProgramVisitor {
75 public:
76 SymbolHoister(const Context& ctx, SymbolTable* innerSym, SymbolTable* hoistSym)
77 : fContext(ctx)
78 , fInnerSymbols(innerSym)
79 , fHoistedSymbols(hoistSym) {}
80
81 bool visitStatement(const Statement& stmt) override {
82 if (stmt.is<VarDeclaration>()) {
83 // Hoist the variable's symbol outside of the initializer block's symbol table, and
84 // into the outer symbol table. If the initializer's symbol table originally had
85 // ownership, transfer it. (If the variable was owned elsewhere, it can keep its
86 // current owner.)
87 Variable* var = stmt.as<VarDeclaration>().var();
88 fInnerSymbols->moveSymbolTo(fHoistedSymbols, var, fContext);
89 return false;
90 }
92 }
93
94 const Context& fContext;
95 SymbolTable* fInnerSymbols;
96 SymbolTable* fHoistedSymbols;
97 };
98
99 SymbolHoister{context, innerSymbols, hoistedSymbols}.visitStatement(initBlock);
100}

◆ index_out_of_range()

static bool SkSL::index_out_of_range ( const Context context,
Position  pos,
SKSL_INT  index,
const Expression base 
)
static

Definition at line 32 of file SkSLIndexExpression.cpp.

33 {
34 if (index >= 0) {
35 if (base.type().columns() == Type::kUnsizedArray) {
36 return false;
37 } else if (index < base.type().columns()) {
38 return false;
39 }
40 }
41 context.fErrors->error(pos, "index " + std::to_string(index) + " out of range for '" +
42 base.type().displayName() + "'");
43 return true;
44}

◆ is_abs()

static bool SkSL::is_abs ( Expression expr)
static

Definition at line 446 of file SkSLGLSLCodeGenerator.cpp.

446 {
447 return expr.is<FunctionCall>() &&
448 expr.as<FunctionCall>().function().intrinsicKind() == k_abs_IntrinsicKind;
449}
const FunctionDeclaration & function() const
IntrinsicKind intrinsicKind() const

◆ is_block_ending_with_return()

static bool SkSL::is_block_ending_with_return ( const Statement stmt)
static

Definition at line 2572 of file SkSLMetalCodeGenerator.cpp.

2572 {
2573 // This function detects (potentially nested) blocks that end in a return statement.
2574 if (!stmt->is<Block>()) {
2575 return false;
2576 }
2577 const StatementArray& block = stmt->as<Block>().children();
2578 for (int index = block.size(); index--; ) {
2579 stmt = block[index].get();
2580 if (stmt->is<ReturnStatement>()) {
2581 return true;
2582 }
2583 if (stmt->is<Block>()) {
2584 return is_block_ending_with_return(stmt);
2585 }
2586 if (!stmt->is<Nop>()) {
2587 break;
2588 }
2589 }
2590 return false;
2591}
static bool is_block_ending_with_return(const Statement *stmt)

◆ is_bool()

static bool SkSL::is_bool ( const Type type)
static

Definition at line 909 of file SkSLSPIRVCodeGenerator.cpp.

909 {
910 return (type.isScalar() || type.isVector()) && type.componentType().isBoolean();
911}

◆ is_buffer()

static bool SkSL::is_buffer ( const InterfaceBlock block)
static

Definition at line 555 of file SkSLMetalCodeGenerator.cpp.

555 {
556 return block.var()->modifierFlags().isBuffer();
557}
Variable * var() const

◆ is_compute_builtin()

static bool SkSL::is_compute_builtin ( const Variable var)
static

Definition at line 1699 of file SkSLMetalCodeGenerator.cpp.

1699 {
1700 switch (var.layout().fBuiltin) {
1706 return true;
1707 default:
1708 break;
1709 }
1710 return false;
1711}
constexpr int SK_WORKGROUPID_BUILTIN
constexpr int SK_GLOBALINVOCATIONID_BUILTIN
constexpr int SK_LOCALINVOCATIONID_BUILTIN
constexpr int SK_NUMWORKGROUPS_BUILTIN
constexpr int SK_LOCALINVOCATIONINDEX_BUILTIN

◆ is_constant_diagonal()

static bool SkSL::is_constant_diagonal ( const Expression expr,
double  value 
)
static

Definition at line 366 of file SkSLConstantFolder.cpp.

366 {
367 SkASSERT(expr.type().isMatrix());
368 int columns = expr.type().columns();
369 int rows = expr.type().rows();
370 if (columns != rows) {
371 return false;
372 }
373 int slotIdx = 0;
374 for (int c = 0; c < columns; ++c) {
375 for (int r = 0; r < rows; ++r) {
376 double expectation = (c == r) ? value : 0;
377 std::optional<double> slotVal = expr.getConstantValue(slotIdx++);
378 if (!slotVal.has_value() || *slotVal != expectation) {
379 return false;
380 }
381 }
382 }
383 return true;
384}
virtual int rows() const
Definition SkSLType.h:438

◆ is_constant_value()

static bool SkSL::is_constant_value ( const Expression expr,
double  value 
)
static

Definition at line 387 of file SkSLConstantFolder.cpp.

387 {
388 return expr.type().isMatrix() ? is_constant_diagonal(expr, value)
389 : ConstantFolder::IsConstantSplat(expr, value);
390}
static bool is_constant_diagonal(const Expression &expr, double value)

◆ is_control_flow_op()

static bool SkSL::is_control_flow_op ( SpvOp_  op)
static

Definition at line 943 of file SkSLSPIRVCodeGenerator.cpp.

943 {
944 switch (op) {
945 case SpvOpReturn:
946 case SpvOpReturnValue:
947 case SpvOpKill:
948 case SpvOpSwitch:
949 case SpvOpBranch:
951 return true;
952 default:
953 return false;
954 }
955}
@ SpvOpBranchConditional
Definition spirv.h:802
@ SpvOpBranch
Definition spirv.h:801
@ SpvOpReturn
Definition spirv.h:805
@ SpvOpSwitch
Definition spirv.h:803
@ SpvOpKill
Definition spirv.h:804
@ SpvOpReturnValue
Definition spirv.h:806

◆ is_dead_variable()

static bool SkSL::is_dead_variable ( const ProgramElement element,
ProgramUsage usage,
bool  onlyPrivateGlobals 
)
static

Definition at line 26 of file SkSLEliminateDeadGlobalVariables.cpp.

28 {
29 if (!element.is<GlobalVarDeclaration>()) {
30 return false;
31 }
32 const GlobalVarDeclaration& global = element.as<GlobalVarDeclaration>();
33 const VarDeclaration& varDecl = global.varDeclaration();
34 if (onlyPrivateGlobals && !skstd::starts_with(varDecl.var()->name(), '$')) {
35 return false;
36 }
37 if (!usage->isDead(*varDecl.var())) {
38 return false;
39 }
40 // This declaration is about to be eliminated by remove_if; update ProgramUsage accordingly.
41 usage->remove(&varDecl);
42 return true;
43}

◆ is_float()

static bool SkSL::is_float ( const Type type)
static

Definition at line 896 of file SkSLSPIRVCodeGenerator.cpp.

896 {
897 return (type.isScalar() || type.isVector() || type.isMatrix()) &&
898 type.componentType().isFloat();
899}

◆ is_globally_reachable_op()

static bool SkSL::is_globally_reachable_op ( SpvOp_  op)
static

Definition at line 957 of file SkSLSPIRVCodeGenerator.cpp.

957 {
958 switch (op) {
959 case SpvOpConstant:
963 case SpvOpTypeVoid:
964 case SpvOpTypeInt:
965 case SpvOpTypeFloat:
966 case SpvOpTypeBool:
967 case SpvOpTypeVector:
968 case SpvOpTypeMatrix:
969 case SpvOpTypeArray:
970 case SpvOpTypePointer:
973 case SpvOpTypeStruct:
974 case SpvOpTypeImage:
976 case SpvOpTypeSampler:
977 case SpvOpVariable:
978 case SpvOpFunction:
980 case SpvOpFunctionEnd:
982 case SpvOpMemoryModel:
983 case SpvOpCapability:
985 case SpvOpEntryPoint:
986 case SpvOpSource:
988 case SpvOpName:
989 case SpvOpMemberName:
990 case SpvOpDecorate:
992 return true;
993 default:
994 return false;
995 }
996}
@ SpvOpCapability
Definition spirv.h:589
@ SpvOpSourceExtension
Definition spirv.h:578
@ SpvOpTypeMatrix
Definition spirv.h:595
@ SpvOpSource
Definition spirv.h:577
@ SpvOpTypeBool
Definition spirv.h:591
@ SpvOpTypeArray
Definition spirv.h:599
@ SpvOpVariable
Definition spirv.h:626
@ SpvOpDecorate
Definition spirv.h:638
@ SpvOpName
Definition spirv.h:579
@ SpvOpTypeSampler
Definition spirv.h:597
@ SpvOpExtInstImport
Definition spirv.h:584
@ SpvOpFunctionParameter
Definition spirv.h:623
@ SpvOpConstantComposite
Definition spirv.h:614
@ SpvOpMemoryModel
Definition spirv.h:586
@ SpvOpTypeImage
Definition spirv.h:596
@ SpvOpTypeSampledImage
Definition spirv.h:598
@ SpvOpTypeVector
Definition spirv.h:594
@ SpvOpFunctionEnd
Definition spirv.h:624
@ SpvOpEntryPoint
Definition spirv.h:587
@ SpvOpTypeInt
Definition spirv.h:592
@ SpvOpMemberName
Definition spirv.h:580
@ SpvOpTypeFloat
Definition spirv.h:593
@ SpvOpFunction
Definition spirv.h:622
@ SpvOpMemberDecorate
Definition spirv.h:639
@ SpvOpConstantFalse
Definition spirv.h:612
@ SpvOpConstantTrue
Definition spirv.h:611
@ SpvOpTypeFunction
Definition spirv.h:604
@ SpvOpTypeStruct
Definition spirv.h:601
@ SpvOpExecutionMode
Definition spirv.h:588
@ SpvOpConstant
Definition spirv.h:613
@ SpvOpTypeVoid
Definition spirv.h:590
@ SpvOpTypeRuntimeArray
Definition spirv.h:600
@ SpvOpTypePointer
Definition spirv.h:603

◆ is_in()

static bool SkSL::is_in ( ModifierFlags  f)
static

Definition at line 935 of file SkSLSPIRVCodeGenerator.cpp.

935 {
936 if (f & ModifierFlag::kIn) {
937 return true; // `in` and `inout` both count
938 }
939 // If neither in/out flag is set, the type is implicitly `in`.
940 return !SkToBool(f & ModifierFlag::kOut);
941}
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35

◆ is_in_globals()

static bool SkSL::is_in_globals ( const Variable var)
static

Definition at line 1745 of file SkSLMetalCodeGenerator.cpp.

1745 {
1746 SkASSERT(var.storage() == VariableStorage::kGlobal);
1747 return !var.modifierFlags().isConst();
1748}

◆ is_input()

static bool SkSL::is_input ( const Variable var)
static

Definition at line 1714 of file SkSLMetalCodeGenerator.cpp.

1714 {
1715 SkASSERT(var.storage() == VariableStorage::kGlobal);
1716 return var.modifierFlags() & ModifierFlag::kIn &&
1717 (var.layout().fBuiltin == -1 || is_compute_builtin(var)) &&
1718 var.type().typeKind() != Type::TypeKind::kTexture;
1719}
static bool is_compute_builtin(const Variable &var)

◆ is_matrix_op_scalar()

static bool SkSL::is_matrix_op_scalar ( const Expression left,
const Expression right 
)
static

Definition at line 476 of file SkSLConstantFolder.cpp.

476 {
478}
static bool is_scalar_op_matrix(const Expression &left, const Expression &right)

◆ is_nontrivial_expression()

static bool SkSL::is_nontrivial_expression ( const Expression expr)
static

Definition at line 2481 of file SkSLWGSLCodeGenerator.cpp.

2481 {
2482 // We consider a "trivial expression" one which we can repeat multiple times in the output
2483 // without being dangerous or spammy. We avoid emitting temporary variables for very trivial
2484 // expressions: literals, unadorned variable references, or constant vectors.
2485 if (expr.is<VariableReference>() || expr.is<Literal>()) {
2486 // Variables and literals are trivial; adding a let-declaration won't simplify anything.
2487 return false;
2488 }
2489 if (expr.type().isVector() && Analysis::IsConstantExpression(expr)) {
2490 // Compile-time constant vectors are also considered trivial; they're short and sweet.
2491 return false;
2492 }
2493 return true;
2494}

◆ is_out()

static bool SkSL::is_out ( ModifierFlags  f)
static

Definition at line 931 of file SkSLSPIRVCodeGenerator.cpp.

931 {
932 return SkToBool(f & ModifierFlag::kOut);
933}

◆ is_output()

static bool SkSL::is_output ( const Variable var)
static

Definition at line 1722 of file SkSLMetalCodeGenerator.cpp.

1722 {
1723 SkASSERT(var.storage() == VariableStorage::kGlobal);
1724 // inout vars get written into the Inputs struct, so we exclude them from Outputs
1725 return (var.modifierFlags() & ModifierFlag::kOut) &&
1726 !(var.modifierFlags() & ModifierFlag::kIn) &&
1727 var.layout().fBuiltin == -1 &&
1728 var.type().typeKind() != Type::TypeKind::kTexture;
1729}

◆ is_readonly()

static bool SkSL::is_readonly ( const InterfaceBlock block)
static

Definition at line 560 of file SkSLMetalCodeGenerator.cpp.

560 {
561 return block.var()->modifierFlags().isReadOnly();
562}

◆ is_safe_to_eliminate()

static bool SkSL::is_safe_to_eliminate ( const Type type,
const Expression arg 
)
static

Definition at line 28 of file SkSLConstructorCompound.cpp.

28 {
29 if (type.isScalar()) {
30 // A scalar "compound type" with a single scalar argument is a no-op and can be eliminated.
31 // (Pedantically, this isn't a compound at all, but it's harmless to allow and simplifies
32 // call sites which need to narrow a vector and may sometimes end up with a scalar.)
33 SkASSERTF(arg.type().matches(type), "Creating type '%s' from '%s'",
34 type.description().c_str(), arg.type().description().c_str());
35 return true;
36 }
37 if (type.isVector() && arg.type().matches(type)) {
38 // A vector compound constructor containing a single argument of matching type can trivially
39 // be eliminated.
40 return true;
41 }
42 // This is a meaningful single-argument compound constructor (e.g. vector-from-matrix,
43 // matrix-from-vector).
44 return false;
45}
#define SkASSERTF(cond, fmt,...)
Definition SkAssert.h:117
std::string description() const override
Definition SkSLType.h:238

◆ is_scalar_op_matrix()

static bool SkSL::is_scalar_op_matrix ( const Expression left,
const Expression right 
)
static

Definition at line 472 of file SkSLConstantFolder.cpp.

472 {
473 return left.type().isScalar() && right.type().isMatrix();
474}

◆ is_signed()

static bool SkSL::is_signed ( const Type type)
static

Definition at line 901 of file SkSLSPIRVCodeGenerator.cpp.

901 {
902 return (type.isScalar() || type.isVector()) && type.componentType().isSigned();
903}

◆ is_simple_initializer()

static bool SkSL::is_simple_initializer ( const Statement stmt)
static

Definition at line 46 of file SkSLForStatement.cpp.

46 {
47 return !stmt || stmt->isEmpty() || stmt->is<SkSL::VarDeclaration>() ||
49}
virtual bool isEmpty() const

◆ is_sk_position()

bool SkSL::is_sk_position ( const Expression expr)

Definition at line 1112 of file SkSLGLSLCodeGenerator.cpp.

1112 {
1113 if (!expr.is<FieldAccess>()) {
1114 return false;
1115 }
1116 const FieldAccess& f = expr.as<FieldAccess>();
1117 return f.base()->type().fields()[f.fieldIndex()].fLayout.fBuiltin == SK_POSITION_BUILTIN;
1118}
constexpr int SK_POSITION_BUILTIN

◆ is_sk_samplemask()

bool SkSL::is_sk_samplemask ( const Expression expr)

Definition at line 1120 of file SkSLGLSLCodeGenerator.cpp.

1120 {
1121 if (!expr.is<VariableReference>()) {
1122 return false;
1123 }
1124 const VariableReference& v = expr.as<VariableReference>();
1125 return v.variable()->layout().fBuiltin == SK_SAMPLEMASK_BUILTIN;
1126}
constexpr int SK_SAMPLEMASK_BUILTIN

◆ is_threadgroup()

static bool SkSL::is_threadgroup ( const Variable var)
static

Definition at line 1739 of file SkSLMetalCodeGenerator.cpp.

1739 {
1740 SkASSERT(var.storage() == VariableStorage::kGlobal);
1741 return var.modifierFlags().isWorkgroup();
1742}

◆ is_uniforms()

static bool SkSL::is_uniforms ( const Variable var)
static

Definition at line 1732 of file SkSLMetalCodeGenerator.cpp.

1732 {
1733 SkASSERT(var.storage() == VariableStorage::kGlobal);
1734 return var.modifierFlags().isUniform() &&
1735 var.type().typeKind() != Type::TypeKind::kSampler;
1736}

◆ is_unsigned()

static bool SkSL::is_unsigned ( const Type type)
static

Definition at line 905 of file SkSLSPIRVCodeGenerator.cpp.

905 {
906 return (type.isScalar() || type.isVector()) && type.componentType().isUnsigned();
907}

◆ is_vardecl_block_initializer()

static bool SkSL::is_vardecl_block_initializer ( const Statement stmt)
static

Definition at line 27 of file SkSLForStatement.cpp.

27 {
28 if (!stmt) {
29 return false;
30 }
31 if (!stmt->is<SkSL::Block>()) {
32 return false;
33 }
34 const SkSL::Block& b = stmt->as<SkSL::Block>();
35 if (b.isScope()) {
36 return false;
37 }
38 for (const auto& child : b.children()) {
39 if (!child->is<SkSL::VarDeclaration>()) {
40 return false;
41 }
42 }
43 return true;
44}

◆ is_vardecl_compile_time_constant()

static bool SkSL::is_vardecl_compile_time_constant ( const VarDeclaration varDecl)
static

Definition at line 4475 of file SkSLSPIRVCodeGenerator.cpp.

4475 {
4476 return varDecl.var()->modifierFlags().isConst() &&
4477 (varDecl.var()->type().isScalar() || varDecl.var()->type().isVector()) &&
4478 (ConstantFolder::GetConstantValueOrNull(*varDecl.value()) ||
4479 Analysis::IsCompileTimeConstant(*varDecl.value()));
4480}
std::unique_ptr< Expression > & value()
Variable * var() const

◆ is_vec_or_mat()

static bool SkSL::is_vec_or_mat ( const Type type)
static

Definition at line 41 of file SkSLConstantFolder.cpp.

41 {
42 switch (type.typeKind()) {
43 case Type::TypeKind::kMatrix:
44 case Type::TypeKind::kVector:
45 return true;
46
47 default:
48 return false;
49 }
50}

◆ is_whitespace()

static bool SkSL::is_whitespace ( Token::Kind  kind)
static

Definition at line 273 of file SkSLParser.cpp.

273 {
274 switch (kind) {
275 case Token::Kind::TK_WHITESPACE:
276 case Token::Kind::TK_LINE_COMMENT:
277 case Token::Kind::TK_BLOCK_COMMENT:
278 return true;
279
280 default:
281 return false;
282 }
283}

◆ layout_flags_to_image_format()

static SpvImageFormat SkSL::layout_flags_to_image_format ( LayoutFlags  flags)
static

Definition at line 1621 of file SkSLSPIRVCodeGenerator.cpp.

1621 {
1622 flags &= LayoutFlag::kAllPixelFormats;
1623 switch (flags.value()) {
1624 case (int)LayoutFlag::kRGBA8:
1625 return SpvImageFormatRgba8;
1626
1627 case (int)LayoutFlag::kRGBA32F:
1628 return SpvImageFormatRgba32f;
1629
1630 case (int)LayoutFlag::kR32F:
1631 return SpvImageFormatR32f;
1632
1633 default:
1634 return SpvImageFormatUnknown;
1635 }
1636
1638}
@ SpvImageFormatUnknown
Definition spirv.h:165
@ SpvImageFormatRgba32f
Definition spirv.h:166
@ SpvImageFormatRgba8
Definition spirv.h:169
@ SpvImageFormatR32f
Definition spirv.h:168

◆ logical_not_operand()

static std::unique_ptr< Expression > SkSL::logical_not_operand ( const Context context,
Position  pos,
std::unique_ptr< Expression operand 
)
static

Definition at line 151 of file SkSLPrefixExpression.cpp.

153 {
154 const Expression* value = ConstantFolder::GetConstantValueForVariable(*operand);
155 switch (value->kind()) {
156 case Expression::Kind::kLiteral: {
157 // Convert !boolLiteral(true) to boolLiteral(false).
158 SkASSERT(value->type().isBoolean());
159 const Literal& b = value->as<Literal>();
160 return Literal::MakeBool(pos, !b.boolValue(), &operand->type());
161 }
162 case Expression::Kind::kPrefix: {
163 // Convert `!(!expression)` into `expression`.
164 PrefixExpression& prefix = operand->as<PrefixExpression>();
165 if (prefix.getOperator().kind() == Operator::Kind::LOGICALNOT) {
166 prefix.operand()->fPosition = pos;
167 return std::move(prefix.operand());
168 }
169 break;
170 }
171 case Expression::Kind::kBinary: {
172 BinaryExpression& binary = operand->as<BinaryExpression>();
173 std::optional<Operator> replacement;
174 switch (binary.getOperator().kind()) {
175 case OperatorKind::EQEQ: replacement = OperatorKind::NEQ; break;
176 case OperatorKind::NEQ: replacement = OperatorKind::EQEQ; break;
177 case OperatorKind::LT: replacement = OperatorKind::GTEQ; break;
178 case OperatorKind::LTEQ: replacement = OperatorKind::GT; break;
179 case OperatorKind::GT: replacement = OperatorKind::LTEQ; break;
180 case OperatorKind::GTEQ: replacement = OperatorKind::LT; break;
181 default: break;
182 }
183 if (replacement.has_value()) {
184 return BinaryExpression::Make(context, pos, std::move(binary.left()),
185 *replacement, std::move(binary.right()),
186 &binary.type());
187 }
188 break;
189 }
190 default:
191 break;
192 }
193
194 // No simplified form; convert expression to Prefix(LOGICALNOT, expression).
195 return std::make_unique<PrefixExpression>(pos, Operator::Kind::LOGICALNOT, std::move(operand));
196}

◆ make_reciprocal_expression()

static std::unique_ptr< Expression > SkSL::make_reciprocal_expression ( const Context context,
const Expression right 
)
static

Definition at line 396 of file SkSLConstantFolder.cpp.

397 {
398 if (right.type().isMatrix() || !right.type().componentType().isFloat()) {
399 return nullptr;
400 }
401 // Verify that each slot contains a finite, non-zero literal, take its reciprocal.
402 double values[4];
403 int nslots = right.type().slotCount();
404 for (int index = 0; index < nslots; ++index) {
405 std::optional<double> value = right.getConstantValue(index);
406 if (!value) {
407 return nullptr;
408 }
409 *value = sk_ieee_double_divide(1.0, *value);
410 if (*value >= -FLT_MAX && *value <= FLT_MAX && *value != 0.0) {
411 // The reciprocal can be represented safely as a finite 32-bit float.
412 values[index] = *value;
413 } else {
414 // The value is outside the 32-bit float range, or is NaN; do not optimize.
415 return nullptr;
416 }
417 }
418 // Turn the expression array into a compound constructor. (If this is a single-slot expression,
419 // this will return the literal as-is.)
420 return ConstructorCompound::MakeFromConstants(context, right.fPosition, right.type(), values);
421}

◆ make_splat_from_arguments()

static const Expression * SkSL::make_splat_from_arguments ( const Type type,
const ExpressionArray args 
)
static

Definition at line 47 of file SkSLConstructorCompound.cpp.

47 {
48 // Splats cannot represent a matrix.
49 if (type.isMatrix()) {
50 return nullptr;
51 }
52 const Expression* splatExpression = nullptr;
53 for (int index = 0; index < args.size(); ++index) {
54 // Arguments must only be scalars or a splat constructors (which can only contain scalars).
55 const Expression* expr;
56 if (args[index]->type().isScalar()) {
57 expr = args[index].get();
58 } else if (args[index]->is<ConstructorSplat>()) {
59 expr = args[index]->as<ConstructorSplat>().argument().get();
60 } else {
61 return nullptr;
62 }
63 // On the first iteration, just remember the expression we encountered.
64 if (index == 0) {
65 splatExpression = expr;
66 continue;
67 }
68 // On subsequent iterations, ensure that the expression we found matches the first one.
69 // (Note that IsSameExpressionTree will always reject an Expression with side effects.)
70 if (!Analysis::IsSameExpressionTree(*expr, *splatExpression)) {
71 return nullptr;
72 }
73 }
74
75 return splatExpression;
76}

◆ MakeRasterPipelineProgram()

std::unique_ptr< RP::Program > SkSL::MakeRasterPipelineProgram ( const SkSL::Program program,
const FunctionDefinition function,
DebugTracePriv debugTrace,
bool  writeTraceOps 
)

Definition at line 4070 of file SkSLRasterPipelineCodeGenerator.cpp.

4073 {
4074 RP::Generator generator(program, debugTrace, writeTraceOps);
4075 if (!generator.writeProgram(function)) {
4076 return nullptr;
4077 }
4078 return generator.finish();
4079}

◆ mask_char()

static char SkSL::mask_char ( int8_t  component)
static

Definition at line 87 of file SkSLSwizzle.cpp.

87 {
88 switch (component) {
89 case SwizzleComponent::X: return 'x';
90 case SwizzleComponent::Y: return 'y';
91 case SwizzleComponent::Z: return 'z';
92 case SwizzleComponent::W: return 'w';
93 case SwizzleComponent::R: return 'r';
94 case SwizzleComponent::G: return 'g';
95 case SwizzleComponent::B: return 'b';
96 case SwizzleComponent::A: return 'a';
97 case SwizzleComponent::S: return 's';
98 case SwizzleComponent::T: return 't';
99 case SwizzleComponent::P: return 'p';
100 case SwizzleComponent::Q: return 'q';
101 case SwizzleComponent::UL: return 'L';
102 case SwizzleComponent::UT: return 'T';
103 case SwizzleComponent::UR: return 'R';
104 case SwizzleComponent::UB: return 'B';
105 case SwizzleComponent::ZERO: return '0';
106 case SwizzleComponent::ONE: return '1';
107 default: SkUNREACHABLE;
108 }
109}

◆ needs_address_space()

static bool SkSL::needs_address_space ( const Type type,
ModifierFlags  modifiers 
)
static

Definition at line 550 of file SkSLMetalCodeGenerator.cpp.

550 {
551 return type.isUnsizedArray() || pass_by_reference(type, modifiers);
552}
static bool pass_by_reference(const Type &type, ModifierFlags flags)

◆ negate_expression()

static std::unique_ptr< Expression > SkSL::negate_expression ( const Context context,
Position  pos,
const Expression expr,
const Type type 
)
static

Definition at line 316 of file SkSLConstantFolder.cpp.

319 {
320 std::unique_ptr<Expression> ctor = cast_expression(context, pos, expr, type);
321 return ctor ? PrefixExpression::Make(context, pos, Operator::Kind::MINUS, std::move(ctor))
322 : nullptr;
323}
static std::unique_ptr< Expression > cast_expression(const Context &context, Position pos, const Expression &expr, const Type &type)

◆ negate_operand()

static std::unique_ptr< Expression > SkSL::negate_operand ( const Context context,
Position  pos,
std::unique_ptr< Expression value 
)
static

Definition at line 139 of file SkSLPrefixExpression.cpp.

141 {
142 // Attempt to simplify this negation (e.g. eliminate double negation, literal values)
143 if (std::unique_ptr<Expression> simplified = simplify_negation(context, pos, *value)) {
144 return simplified;
145 }
146
147 // No simplified form; convert expression to Prefix(MINUS, expression).
148 return std::make_unique<PrefixExpression>(pos, Operator::Kind::MINUS, std::move(value));
149}
static std::unique_ptr< Expression > simplify_negation(const Context &context, Position pos, const Expression &originalExpr)

◆ negate_operands()

static ExpressionArray SkSL::negate_operands ( const Context context,
Position  pos,
const ExpressionArray operands 
)
static

Definition at line 122 of file SkSLPrefixExpression.cpp.

124 {
125 ExpressionArray replacement;
126 replacement.reserve_exact(array.size());
127 for (const std::unique_ptr<Expression>& expr : array) {
128 // The logic below is very similar to `negate_operand`, but with different ownership rules.
129 if (std::unique_ptr<Expression> simplified = simplify_negation(context, pos, *expr)) {
130 replacement.push_back(std::move(simplified));
131 } else {
132 replacement.push_back(std::make_unique<PrefixExpression>(pos, Operator::Kind::MINUS,
133 expr->clone()));
134 }
135 }
136 return replacement;
137}

◆ negate_value()

static double SkSL::negate_value ( double  value)
static

Definition at line 35 of file SkSLPrefixExpression.cpp.

35 {
36 return -value;
37}

◆ one_over_scalar()

static std::unique_ptr< Expression > SkSL::one_over_scalar ( const Context context,
const Expression right 
)
static

Definition at line 615 of file SkSLConstantFolder.cpp.

616 {
617 SkASSERT(right.type().isScalar());
618 Position pos = right.fPosition;
619 return BinaryExpression::Make(context, pos,
620 Literal::Make(pos, 1.0, &right.type()),
621 Operator::Kind::SLASH,
622 right.clone());
623}

◆ operator_name()

static const char * SkSL::operator_name ( Operator  op)
static

Definition at line 368 of file SkSLMetalCodeGenerator.cpp.

368 {
369 switch (op.kind()) {
370 case Operator::Kind::LOGICALXOR: return " != ";
371 default: return op.operatorName();
372 }
373}
const char * operatorName() const

◆ optimize_comparison()

static std::unique_ptr< Expression > SkSL::optimize_comparison ( const Context context,
const IntrinsicArguments arguments,
CompareFn  compare 
)
static

Definition at line 176 of file SkSLFunctionCall.cpp.

178 {
179 const Expression* left = arguments[0];
180 const Expression* right = arguments[1];
181 SkASSERT(left);
183 SkASSERT(!arguments[2]);
184
185 const Type& type = left->type();
186 SkASSERT(type.isVector());
187 SkASSERT(type.componentType().isScalar());
188 SkASSERT(type.matches(right->type()));
189
190 double array[4];
191
192 for (int index = 0; index < type.columns(); ++index) {
193 std::optional<double> leftValue = left->getConstantValue(index);
194 std::optional<double> rightValue = right->getConstantValue(index);
195 SkASSERT(leftValue.has_value());
196 SkASSERT(rightValue.has_value());
197 array[index] = compare(*leftValue, *rightValue) ? 1.0 : 0.0;
198 }
199
200 const Type& bvecType = context.fTypes.fBool->toCompound(context, type.columns(), /*rows=*/1);
201 return ConstructorCompound::MakeFromConstants(context, left->fPosition, bvecType, array);
202}
static bool compare(const SkBitmap &ref, const SkIRect &iref, const SkBitmap &test, const SkIRect &itest)
Definition BlurTest.cpp:100
const std::unique_ptr< Type > fBool

◆ optimize_constructor_swizzle()

static std::unique_ptr< Expression > SkSL::optimize_constructor_swizzle ( const Context context,
Position  pos,
const ConstructorCompound base,
ComponentArray  components 
)
static

Definition at line 119 of file SkSLSwizzle.cpp.

122 {
123 auto baseArguments = base.argumentSpan();
124 std::unique_ptr<Expression> replacement;
125 const Type& exprType = base.type();
126 const Type& componentType = exprType.componentType();
127 int swizzleSize = components.size();
128
129 // Swizzles can duplicate some elements and discard others, e.g.
130 // `half4(1, 2, 3, 4).xxz` --> `half3(1, 1, 3)`. However, there are constraints:
131 // - Expressions with side effects need to occur exactly once, even if they would otherwise be
132 // swizzle-eliminated
133 // - Non-trivial expressions should not be repeated, but elimination is OK.
134 //
135 // Look up the argument for the constructor at each index. This is typically simple but for
136 // weird cases like `half4(bar.yz, half2(foo))`, it can be harder than it seems. This example
137 // would result in:
138 // argMap[0] = {.fArgIndex = 0, .fComponent = 0} (bar.yz .x)
139 // argMap[1] = {.fArgIndex = 0, .fComponent = 1} (bar.yz .y)
140 // argMap[2] = {.fArgIndex = 1, .fComponent = 0} (half2(foo) .x)
141 // argMap[3] = {.fArgIndex = 1, .fComponent = 1} (half2(foo) .y)
142 struct ConstructorArgMap {
143 int8_t fArgIndex;
144 int8_t fComponent;
145 };
146
147 int numConstructorArgs = base.type().columns();
148 ConstructorArgMap argMap[4] = {};
149 int writeIdx = 0;
150 for (int argIdx = 0; argIdx < (int)baseArguments.size(); ++argIdx) {
151 const Expression& arg = *baseArguments[argIdx];
152 const Type& argType = arg.type();
153
154 if (!argType.isScalar() && !argType.isVector()) {
155 return nullptr;
156 }
157
158 int argSlots = argType.slotCount();
159 for (int componentIdx = 0; componentIdx < argSlots; ++componentIdx) {
160 argMap[writeIdx].fArgIndex = argIdx;
161 argMap[writeIdx].fComponent = componentIdx;
162 ++writeIdx;
163 }
164 }
165 SkASSERT(writeIdx == numConstructorArgs);
166
167 // Count up the number of times each constructor argument is used by the swizzle.
168 // `half4(bar.yz, half2(foo)).xwxy` -> { 3, 1 }
169 // - bar.yz is referenced 3 times, by `.x_xy`
170 // - half(foo) is referenced 1 time, by `._w__`
171 int8_t exprUsed[4] = {};
172 for (int8_t c : components) {
173 exprUsed[argMap[c].fArgIndex]++;
174 }
175
176 for (int index = 0; index < numConstructorArgs; ++index) {
177 int8_t constructorArgIndex = argMap[index].fArgIndex;
178 const Expression& baseArg = *baseArguments[constructorArgIndex];
179
180 // Check that non-trivial expressions are not swizzled in more than once.
181 if (exprUsed[constructorArgIndex] > 1 && !Analysis::IsTrivialExpression(baseArg)) {
182 return nullptr;
183 }
184 // Check that side-effect-bearing expressions are swizzled in exactly once.
185 if (exprUsed[constructorArgIndex] != 1 && Analysis::HasSideEffects(baseArg)) {
186 return nullptr;
187 }
188 }
189
190 struct ReorderedArgument {
191 int8_t fArgIndex;
192 ComponentArray fComponents;
193 };
194 STArray<4, ReorderedArgument> reorderedArgs;
195 for (int8_t c : components) {
196 const ConstructorArgMap& argument = argMap[c];
197 const Expression& baseArg = *baseArguments[argument.fArgIndex];
198
199 if (baseArg.type().isScalar()) {
200 // This argument is a scalar; add it to the list as-is.
201 SkASSERT(argument.fComponent == 0);
202 reorderedArgs.push_back({argument.fArgIndex,
203 ComponentArray{}});
204 } else {
205 // This argument is a component from a vector.
206 SkASSERT(baseArg.type().isVector());
207 SkASSERT(argument.fComponent < baseArg.type().columns());
208 if (reorderedArgs.empty() ||
209 reorderedArgs.back().fArgIndex != argument.fArgIndex) {
210 // This can't be combined with the previous argument. Add a new one.
211 reorderedArgs.push_back({argument.fArgIndex,
212 ComponentArray{argument.fComponent}});
213 } else {
214 // Since we know this argument uses components, it should already have at least one
215 // component set.
216 SkASSERT(!reorderedArgs.back().fComponents.empty());
217 // Build up the current argument with one more component.
218 reorderedArgs.back().fComponents.push_back(argument.fComponent);
219 }
220 }
221 }
222
223 // Convert our reordered argument list to an actual array of expressions, with the new order and
224 // any new inner swizzles that need to be applied.
225 ExpressionArray newArgs;
226 newArgs.reserve_exact(swizzleSize);
227 for (const ReorderedArgument& reorderedArg : reorderedArgs) {
228 std::unique_ptr<Expression> newArg = baseArguments[reorderedArg.fArgIndex]->clone();
229
230 if (reorderedArg.fComponents.empty()) {
231 newArgs.push_back(std::move(newArg));
232 } else {
233 newArgs.push_back(Swizzle::Make(context, pos, std::move(newArg),
234 reorderedArg.fComponents));
235 }
236 }
237
238 // Wrap the new argument list in a compound constructor.
239 return ConstructorCompound::Make(context,
240 pos,
241 componentType.toCompound(context, swizzleSize, /*rows=*/1),
242 std::move(newArgs));
243}
const Type & toCompound(const Context &context, int columns, int rows) const
bool empty() const
Definition SkTArray.h:194
skia_private::STArray< 4, int8_t > ComponentArray
Definition SkSLDefines.h:24

◆ optimize_intrinsic_call()

static std::unique_ptr< Expression > SkSL::optimize_intrinsic_call ( const Context context,
Position  pos,
IntrinsicKind  intrinsic,
const ExpressionArray argArray,
const Type returnType 
)
static

Definition at line 635 of file SkSLFunctionCall.cpp.

639 {
640 // Replace constant variables with their literal values.
641 IntrinsicArguments arguments = {};
642 SkASSERT(SkToSizeT(argArray.size()) <= arguments.size());
643 for (int index = 0; index < argArray.size(); ++index) {
644 arguments[index] = ConstantFolder::GetConstantValueForVariable(*argArray[index]);
645 }
646
647 auto Get = [&](int idx, int col) -> float {
648 return *arguments[idx]->getConstantValue(col);
649 };
650
651 switch (intrinsic) {
652 // 8.1 : Angle and Trigonometry Functions
653 case k_radians_IntrinsicKind:
654 return evaluate_intrinsic<float>(context, arguments, returnType,
655 Intrinsics::evaluate_radians);
656 case k_degrees_IntrinsicKind:
657 return evaluate_intrinsic<float>(context, arguments, returnType,
658 Intrinsics::evaluate_degrees);
659 case k_sin_IntrinsicKind:
660 return evaluate_intrinsic<float>(context, arguments, returnType,
661 Intrinsics::evaluate_sin);
662 case k_cos_IntrinsicKind:
663 return evaluate_intrinsic<float>(context, arguments, returnType,
664 Intrinsics::evaluate_cos);
665 case k_tan_IntrinsicKind:
666 return evaluate_intrinsic<float>(context, arguments, returnType,
667 Intrinsics::evaluate_tan);
668 case k_sinh_IntrinsicKind:
669 return evaluate_intrinsic<float>(context, arguments, returnType,
670 Intrinsics::evaluate_sinh);
671 case k_cosh_IntrinsicKind:
672 return evaluate_intrinsic<float>(context, arguments, returnType,
673 Intrinsics::evaluate_cosh);
674 case k_tanh_IntrinsicKind:
675 return evaluate_intrinsic<float>(context, arguments, returnType,
676 Intrinsics::evaluate_tanh);
677 case k_asin_IntrinsicKind:
678 return evaluate_intrinsic<float>(context, arguments, returnType,
679 Intrinsics::evaluate_asin);
680 case k_acos_IntrinsicKind:
681 return evaluate_intrinsic<float>(context, arguments, returnType,
682 Intrinsics::evaluate_acos);
683 case k_atan_IntrinsicKind:
684 if (argArray.size() == 1) {
685 return evaluate_intrinsic<float>(context, arguments, returnType,
686 Intrinsics::evaluate_atan);
687 } else {
688 return evaluate_pairwise_intrinsic(context, arguments, returnType,
689 Intrinsics::evaluate_atan2);
690 }
691 case k_asinh_IntrinsicKind:
692 return evaluate_intrinsic<float>(context, arguments, returnType,
693 Intrinsics::evaluate_asinh);
694
695 case k_acosh_IntrinsicKind:
696 return evaluate_intrinsic<float>(context, arguments, returnType,
697 Intrinsics::evaluate_acosh);
698 case k_atanh_IntrinsicKind:
699 return evaluate_intrinsic<float>(context, arguments, returnType,
700 Intrinsics::evaluate_atanh);
701 // 8.2 : Exponential Functions
702 case k_pow_IntrinsicKind:
703 return evaluate_pairwise_intrinsic(context, arguments, returnType,
704 Intrinsics::evaluate_pow);
705 case k_exp_IntrinsicKind:
706 return evaluate_intrinsic<float>(context, arguments, returnType,
707 Intrinsics::evaluate_exp);
708 case k_log_IntrinsicKind:
709 return evaluate_intrinsic<float>(context, arguments, returnType,
710 Intrinsics::evaluate_log);
711 case k_exp2_IntrinsicKind:
712 return evaluate_intrinsic<float>(context, arguments, returnType,
713 Intrinsics::evaluate_exp2);
714 case k_log2_IntrinsicKind:
715 return evaluate_intrinsic<float>(context, arguments, returnType,
716 Intrinsics::evaluate_log2);
717 case k_sqrt_IntrinsicKind:
718 return evaluate_intrinsic<float>(context, arguments, returnType,
719 Intrinsics::evaluate_sqrt);
720 case k_inversesqrt_IntrinsicKind:
721 return evaluate_intrinsic<float>(context, arguments, returnType,
722 Intrinsics::evaluate_inversesqrt);
723 // 8.3 : Common Functions
724 case k_abs_IntrinsicKind:
725 return evaluate_intrinsic_numeric(context, arguments, returnType,
726 Intrinsics::evaluate_abs);
727 case k_sign_IntrinsicKind:
728 return Intrinsics::evaluate_sign(context, arguments);
729
730 case k_floor_IntrinsicKind:
731 return evaluate_intrinsic<float>(context, arguments, returnType,
732 Intrinsics::evaluate_floor);
733 case k_ceil_IntrinsicKind:
734 return evaluate_intrinsic<float>(context, arguments, returnType,
735 Intrinsics::evaluate_ceil);
736 case k_fract_IntrinsicKind:
737 return evaluate_intrinsic<float>(context, arguments, returnType,
738 Intrinsics::evaluate_fract);
739 case k_mod_IntrinsicKind:
740 return evaluate_pairwise_intrinsic(context, arguments, returnType,
741 Intrinsics::evaluate_mod);
742 case k_min_IntrinsicKind:
743 return evaluate_pairwise_intrinsic(context, arguments, returnType,
744 Intrinsics::evaluate_min);
745 case k_max_IntrinsicKind:
746 return evaluate_pairwise_intrinsic(context, arguments, returnType,
747 Intrinsics::evaluate_max);
748 case k_clamp_IntrinsicKind:
749 return evaluate_3_way_intrinsic(context, arguments, returnType,
750 Intrinsics::evaluate_clamp);
751 case k_fma_IntrinsicKind:
752 return evaluate_3_way_intrinsic(context, arguments, returnType,
753 Intrinsics::evaluate_fma);
754 case k_saturate_IntrinsicKind:
755 return evaluate_intrinsic<float>(context, arguments, returnType,
756 Intrinsics::evaluate_saturate);
757 case k_mix_IntrinsicKind:
758 if (arguments[2]->type().componentType().isBoolean()) {
759 const SkSL::Type& numericType = arguments[0]->type().componentType();
760
761 if (numericType.isFloat()) {
762 type_check_expression<float>(*arguments[0]);
763 type_check_expression<float>(*arguments[1]);
764 } else if (numericType.isInteger()) {
765 type_check_expression<SKSL_INT>(*arguments[0]);
766 type_check_expression<SKSL_INT>(*arguments[1]);
767 } else if (numericType.isBoolean()) {
768 type_check_expression<bool>(*arguments[0]);
769 type_check_expression<bool>(*arguments[1]);
770 } else {
771 SkDEBUGFAILF("unsupported type %s", numericType.description().c_str());
772 return nullptr;
773 }
774 return evaluate_n_way_intrinsic(context, arguments[0], arguments[1], arguments[2],
775 returnType, Intrinsics::evaluate_mix);
776 } else {
777 return evaluate_3_way_intrinsic(context, arguments, returnType,
778 Intrinsics::evaluate_mix);
779 }
780 case k_step_IntrinsicKind:
781 return evaluate_pairwise_intrinsic(context, arguments, returnType,
782 Intrinsics::evaluate_step);
783 case k_smoothstep_IntrinsicKind:
784 return evaluate_3_way_intrinsic(context, arguments, returnType,
785 Intrinsics::evaluate_smoothstep);
786 case k_trunc_IntrinsicKind:
787 return evaluate_intrinsic<float>(context, arguments, returnType,
788 Intrinsics::evaluate_trunc);
789 case k_round_IntrinsicKind: // GLSL `round` documents its rounding mode as unspecified
790 case k_roundEven_IntrinsicKind: // and is allowed to behave identically to `roundEven`.
791 return evaluate_intrinsic<float>(context, arguments, returnType,
792 Intrinsics::evaluate_round);
793 case k_floatBitsToInt_IntrinsicKind:
794 return evaluate_intrinsic<float>(context, arguments, returnType,
795 Intrinsics::evaluate_floatBitsToInt);
796 case k_floatBitsToUint_IntrinsicKind:
797 return evaluate_intrinsic<float>(context, arguments, returnType,
798 Intrinsics::evaluate_floatBitsToUint);
799 case k_intBitsToFloat_IntrinsicKind:
800 return evaluate_intrinsic<SKSL_INT>(context, arguments, returnType,
801 Intrinsics::evaluate_intBitsToFloat);
802 case k_uintBitsToFloat_IntrinsicKind:
803 return evaluate_intrinsic<SKSL_INT>(context, arguments, returnType,
804 Intrinsics::evaluate_uintBitsToFloat);
805 // 8.4 : Floating-Point Pack and Unpack Functions
806 case k_packUnorm2x16_IntrinsicKind: {
807 auto Pack = [&](int n) -> unsigned int {
808 float x = Get(0, n);
809 return (int)std::round(Intrinsics::evaluate_clamp(x, 0.0, 1.0) * 65535.0);
810 };
811 const double packed = ((Pack(0) << 0) & 0x0000FFFF) |
812 ((Pack(1) << 16) & 0xFFFF0000);
813 return ConstructorCompound::MakeFromConstants(context, arguments[0]->fPosition,
814 *context.fTypes.fUInt, &packed);
815 }
816 case k_packSnorm2x16_IntrinsicKind: {
817 auto Pack = [&](int n) -> unsigned int {
818 float x = Get(0, n);
819 return (int)std::round(Intrinsics::evaluate_clamp(x, -1.0, 1.0) * 32767.0);
820 };
821 const double packed = ((Pack(0) << 0) & 0x0000FFFF) |
822 ((Pack(1) << 16) & 0xFFFF0000);
823 return ConstructorCompound::MakeFromConstants(context, arguments[0]->fPosition,
824 *context.fTypes.fUInt, &packed);
825 }
826 case k_packHalf2x16_IntrinsicKind: {
827 auto Pack = [&](int n) -> unsigned int {
828 return SkFloatToHalf(Get(0, n));
829 };
830 const double packed = ((Pack(0) << 0) & 0x0000FFFF) |
831 ((Pack(1) << 16) & 0xFFFF0000);
832 return ConstructorCompound::MakeFromConstants(context, arguments[0]->fPosition,
833 *context.fTypes.fUInt, &packed);
834 }
835 case k_unpackUnorm2x16_IntrinsicKind: {
836 SKSL_INT x = *arguments[0]->getConstantValue(0);
837 uint16_t a = ((x >> 0) & 0x0000FFFF);
838 uint16_t b = ((x >> 16) & 0x0000FFFF);
839 const double unpacked[2] = {double(a) / 65535.0,
840 double(b) / 65535.0};
841 return ConstructorCompound::MakeFromConstants(context, arguments[0]->fPosition,
842 *context.fTypes.fFloat2, unpacked);
843 }
844 case k_unpackSnorm2x16_IntrinsicKind: {
845 SKSL_INT x = *arguments[0]->getConstantValue(0);
846 int16_t a = ((x >> 0) & 0x0000FFFF);
847 int16_t b = ((x >> 16) & 0x0000FFFF);
848 const double unpacked[2] = {Intrinsics::evaluate_clamp(double(a) / 32767.0, -1.0, 1.0),
849 Intrinsics::evaluate_clamp(double(b) / 32767.0, -1.0, 1.0)};
850 return ConstructorCompound::MakeFromConstants(context, arguments[0]->fPosition,
851 *context.fTypes.fFloat2, unpacked);
852 }
853 case k_unpackHalf2x16_IntrinsicKind: {
854 SKSL_INT x = *arguments[0]->getConstantValue(0);
855 uint16_t a = ((x >> 0) & 0x0000FFFF);
856 uint16_t b = ((x >> 16) & 0x0000FFFF);
857 const double unpacked[2] = {SkHalfToFloat(a),
859 return ConstructorCompound::MakeFromConstants(context, arguments[0]->fPosition,
860 *context.fTypes.fFloat2, unpacked);
861 }
862 // 8.5 : Geometric Functions
863 case k_length_IntrinsicKind:
864 return Intrinsics::evaluate_length(arguments);
865
866 case k_distance_IntrinsicKind:
867 return Intrinsics::evaluate_distance(arguments);
868
869 case k_dot_IntrinsicKind:
870 return Intrinsics::evaluate_dot(arguments);
871
872 case k_cross_IntrinsicKind: {
873 auto X = [&](int n) -> float { return Get(0, n); };
874 auto Y = [&](int n) -> float { return Get(1, n); };
875 SkASSERT(arguments[0]->type().columns() == 3); // the vec2 form is not a real intrinsic
876
877 double vec[3] = {X(1) * Y(2) - Y(1) * X(2),
878 X(2) * Y(0) - Y(2) * X(0),
879 X(0) * Y(1) - Y(0) * X(1)};
880 return ConstructorCompound::MakeFromConstants(context, arguments[0]->fPosition,
881 returnType, vec);
882 }
883 case k_normalize_IntrinsicKind:
884 return Intrinsics::evaluate_normalize(context, arguments);
885
886 case k_faceforward_IntrinsicKind:
887 return Intrinsics::evaluate_faceforward(context, arguments);
888
889 case k_reflect_IntrinsicKind:
890 return Intrinsics::evaluate_reflect(context, arguments);
891
892 case k_refract_IntrinsicKind:
893 return Intrinsics::evaluate_refract(context, arguments);
894
895 // 8.6 : Matrix Functions
896 case k_matrixCompMult_IntrinsicKind:
897 return evaluate_pairwise_intrinsic(context, arguments, returnType,
898 Intrinsics::evaluate_matrixCompMult);
899 case k_transpose_IntrinsicKind: {
900 double mat[16];
901 int index = 0;
902 for (int c = 0; c < returnType.columns(); ++c) {
903 for (int r = 0; r < returnType.rows(); ++r) {
904 mat[index++] = Get(0, (returnType.columns() * r) + c);
905 }
906 }
907 return ConstructorCompound::MakeFromConstants(context, arguments[0]->fPosition,
908 returnType, mat);
909 }
910 case k_outerProduct_IntrinsicKind: {
911 double mat[16];
912 int index = 0;
913 for (int c = 0; c < returnType.columns(); ++c) {
914 for (int r = 0; r < returnType.rows(); ++r) {
915 mat[index++] = Get(0, r) * Get(1, c);
916 }
917 }
918 return ConstructorCompound::MakeFromConstants(context, arguments[0]->fPosition,
919 returnType, mat);
920 }
921 case k_determinant_IntrinsicKind: {
922 float mat[16];
923 extract_matrix(arguments[0], mat);
924 float determinant;
925 switch (arguments[0]->type().slotCount()) {
926 case 4:
927 determinant = SkInvert2x2Matrix(mat, /*outMatrix=*/nullptr);
928 break;
929 case 9:
930 determinant = SkInvert3x3Matrix(mat, /*outMatrix=*/nullptr);
931 break;
932 case 16:
933 determinant = SkInvert4x4Matrix(mat, /*outMatrix=*/nullptr);
934 break;
935 default:
936 SkDEBUGFAILF("unsupported type %s", arguments[0]->type().description().c_str());
937 return nullptr;
938 }
939 return Literal::MakeFloat(arguments[0]->fPosition, determinant, &returnType);
940 }
941 case k_inverse_IntrinsicKind: {
942 float mat[16] = {};
943 extract_matrix(arguments[0], mat);
944 switch (arguments[0]->type().slotCount()) {
945 case 4:
946 if (SkInvert2x2Matrix(mat, mat) == 0.0f) {
947 return nullptr;
948 }
949 break;
950 case 9:
951 if (SkInvert3x3Matrix(mat, mat) == 0.0f) {
952 return nullptr;
953 }
954 break;
955 case 16:
956 if (SkInvert4x4Matrix(mat, mat) == 0.0f) {
957 return nullptr;
958 }
959 break;
960 default:
961 SkDEBUGFAILF("unsupported type %s", arguments[0]->type().description().c_str());
962 return nullptr;
963 }
964
965 double dmat[16];
966 std::copy(mat, mat + std::size(mat), dmat);
967 return ConstructorCompound::MakeFromConstants(context, arguments[0]->fPosition,
968 returnType, dmat);
969 }
970 // 8.7 : Vector Relational Functions
971 case k_lessThan_IntrinsicKind:
972 return optimize_comparison(context, arguments, Intrinsics::compare_lessThan);
973
974 case k_lessThanEqual_IntrinsicKind:
975 return optimize_comparison(context, arguments, Intrinsics::compare_lessThanEqual);
976
977 case k_greaterThan_IntrinsicKind:
978 return optimize_comparison(context, arguments, Intrinsics::compare_greaterThan);
979
980 case k_greaterThanEqual_IntrinsicKind:
981 return optimize_comparison(context, arguments, Intrinsics::compare_greaterThanEqual);
982
983 case k_equal_IntrinsicKind:
984 return optimize_comparison(context, arguments, Intrinsics::compare_equal);
985
986 case k_notEqual_IntrinsicKind:
987 return optimize_comparison(context, arguments, Intrinsics::compare_notEqual);
988
989 case k_any_IntrinsicKind:
990 return coalesce_vector<bool>(arguments, /*startingState=*/false, returnType,
991 Intrinsics::coalesce_any,
992 /*finalize=*/nullptr);
993 case k_all_IntrinsicKind:
994 return coalesce_vector<bool>(arguments, /*startingState=*/true, returnType,
995 Intrinsics::coalesce_all,
996 /*finalize=*/nullptr);
997 case k_not_IntrinsicKind:
998 return evaluate_intrinsic<bool>(context, arguments, returnType,
999 Intrinsics::evaluate_not);
1000 default:
1001 return nullptr;
1002 }
1003}
float SkHalfToFloat(SkHalf h)
Definition SkHalf.cpp:24
SkHalf SkFloatToHalf(float f)
Definition SkHalf.cpp:16
SkScalar SkInvert2x2Matrix(const SkScalar inMatrix[4], SkScalar outMatrix[4])
SkScalar SkInvert3x3Matrix(const SkScalar inMatrix[9], SkScalar outMatrix[9])
SkScalar SkInvert4x4Matrix(const SkScalar inMatrix[16], SkScalar outMatrix[16])
static const SkScalar Y
static const SkScalar X
const std::unique_ptr< Type > fUInt
bool isBoolean() const
Definition SkSLType.h:297
bool isFloat() const
Definition SkSLType.h:318
bool isInteger() const
Definition SkSLType.h:339
double x
const GrXPFactory * Get(SkBlendMode mode)
static std::unique_ptr< Expression > optimize_comparison(const Context &context, const IntrinsicArguments &arguments, CompareFn compare)
std::array< const Expression *, 3 > IntrinsicArguments
static std::unique_ptr< Expression > evaluate_3_way_intrinsic(const Context &context, const IntrinsicArguments &arguments, const Type &returnType, EvaluateFn eval)
static std::unique_ptr< Expression > evaluate_pairwise_intrinsic(const Context &context, const IntrinsicArguments &arguments, const Type &returnType, EvaluateFn eval)
static std::unique_ptr< Expression > evaluate_intrinsic_numeric(const Context &context, const IntrinsicArguments &arguments, const Type &returnType, EvaluateFn eval)
static void extract_matrix(const Expression *expr, float mat[16])

◆ parameters_match()

static bool SkSL::parameters_match ( SkSpan< const std::unique_ptr< Variable > >  params,
SkSpan< Variable *const >  otherParams 
)
static

Checks a parameter list (params) against the parameters of a function that was declared earlier (otherParams). Returns true if they match, even if the parameters in otherParams contain generic types.

Definition at line 294 of file SkSLFunctionDeclaration.cpp.

295 {
296 // If the param lists are different lengths, they're definitely not a match.
297 if (params.size() != otherParams.size()) {
298 return false;
299 }
300
301 // Figure out a consistent generic index (or bail if we find a contradiction).
302 int genericIndex = -1;
303 for (size_t i = 0; i < params.size(); ++i) {
304 const Type* paramType = &params[i]->type();
305 const Type* otherParamType = &otherParams[i]->type();
306
307 if (otherParamType->isGeneric()) {
308 int genericIndexForThisParam = find_generic_index(*paramType, *otherParamType,
309 /*allowNarrowing=*/false);
310 if (genericIndexForThisParam == -1) {
311 // The type wasn't a match for this generic at all; these params can't be a match.
312 return false;
313 }
314 if (genericIndex != -1 && genericIndex != genericIndexForThisParam) {
315 // The generic index mismatches from what we determined on a previous parameter.
316 return false;
317 }
318 genericIndex = genericIndexForThisParam;
319 }
320 }
321
322 // Now that we've determined a generic index (if we needed one), do a parameter check.
323 for (size_t i = 0; i < params.size(); i++) {
324 const Type* paramType = &params[i]->type();
325 const Type* otherParamType = &otherParams[i]->type();
326
327 // Make generic types concrete.
328 if (otherParamType->isGeneric()) {
329 SkASSERT(genericIndex != -1);
330 SkASSERT(genericIndex < (int)otherParamType->coercibleTypes().size());
331 otherParamType = otherParamType->coercibleTypes()[genericIndex];
332 }
333 // Detect type mismatches.
334 if (!paramType->matches(*otherParamType)) {
335 return false;
336 }
337 }
338 return true;
339}

◆ parse_modifier_token()

static ModifierFlags SkSL::parse_modifier_token ( Token::Kind  token)
static

Definition at line 77 of file SkSLParser.cpp.

77 {
78 switch (token) {
79 case Token::Kind::TK_UNIFORM: return ModifierFlag::kUniform;
80 case Token::Kind::TK_CONST: return ModifierFlag::kConst;
81 case Token::Kind::TK_IN: return ModifierFlag::kIn;
82 case Token::Kind::TK_OUT: return ModifierFlag::kOut;
83 case Token::Kind::TK_INOUT: return ModifierFlag::kIn | ModifierFlag::kOut;
84 case Token::Kind::TK_FLAT: return ModifierFlag::kFlat;
85 case Token::Kind::TK_NOPERSPECTIVE: return ModifierFlag::kNoPerspective;
86 case Token::Kind::TK_PURE: return ModifierFlag::kPure;
87 case Token::Kind::TK_INLINE: return ModifierFlag::kInline;
88 case Token::Kind::TK_NOINLINE: return ModifierFlag::kNoInline;
89 case Token::Kind::TK_HIGHP: return ModifierFlag::kHighp;
90 case Token::Kind::TK_MEDIUMP: return ModifierFlag::kMediump;
91 case Token::Kind::TK_LOWP: return ModifierFlag::kLowp;
92 case Token::Kind::TK_EXPORT: return ModifierFlag::kExport;
93 case Token::Kind::TK_ES3: return ModifierFlag::kES3;
94 case Token::Kind::TK_WORKGROUP: return ModifierFlag::kWorkgroup;
95 case Token::Kind::TK_READONLY: return ModifierFlag::kReadOnly;
96 case Token::Kind::TK_WRITEONLY: return ModifierFlag::kWriteOnly;
97 case Token::Kind::TK_BUFFER: return ModifierFlag::kBuffer;
98 case Token::Kind::TK_PIXELLOCAL: return ModifierFlag::kPixelLocal;
99 default: return ModifierFlag::kNone;
100 }
101}

◆ pass_by_reference()

static bool SkSL::pass_by_reference ( const Type type,
ModifierFlags  flags 
)
static

Definition at line 545 of file SkSLMetalCodeGenerator.cpp.

545 {
546 return (flags & ModifierFlag::kOut) && !type.isUnsizedArray();
547}

◆ pick_by_type()

template<typename T >
static T SkSL::pick_by_type ( const Type type,
T  ifFloat,
T  ifInt,
T  ifUInt,
T  ifBool 
)
static

Definition at line 914 of file SkSLSPIRVCodeGenerator.cpp.

914 {
915 if (is_float(type)) {
916 return ifFloat;
917 }
918 if (is_signed(type)) {
919 return ifInt;
920 }
921 if (is_unsigned(type)) {
922 return ifUInt;
923 }
924 if (is_bool(type)) {
925 return ifBool;
926 }
927 SkDEBUGFAIL("unrecognized type");
928 return ifFloat;
929}
static bool is_bool(const Type &type)
static bool is_float(const Type &type)
static bool is_unsigned(const Type &type)

◆ pun_value()

template<typename T1 , typename T2 >
static double SkSL::pun_value ( double  val)
static

Definition at line 346 of file SkSLFunctionCall.cpp.

346 {
347 // Interpret `val` as a value of type T1.
348 static_assert(sizeof(T1) == sizeof(T2));
349 T1 inputValue = (T1)val;
350 // Reinterpret those bits as a value of type T2.
351 T2 outputValue;
352 memcpy(&outputValue, &inputValue, sizeof(T2));
353 // Return the value-of-type-T2 as a double. (Non-finite values will prohibit optimization.)
354 return (double)outputValue;
355}

◆ range_of_at_least_one_char()

static Position SkSL::range_of_at_least_one_char ( int  start,
int  end 
)
static

Definition at line 1580 of file SkSLParser.cpp.

1580 {
1581 return Position::Range(start, std::max(end, start + 1));
1582}

◆ remove_break_statements()

static void SkSL::remove_break_statements ( std::unique_ptr< Statement > &  stmt)
static

Definition at line 68 of file SkSLSwitchStatement.cpp.

68 {
69 class RemoveBreaksWriter : public ProgramWriter {
70 public:
71 bool visitStatementPtr(std::unique_ptr<Statement>& stmt) override {
72 if (stmt->is<BreakStatement>()) {
73 stmt = Nop::Make();
74 return false;
75 }
77 }
78
79 bool visitExpressionPtr(std::unique_ptr<Expression>& expr) override {
80 return false;
81 }
82 };
83 RemoveBreaksWriter{}.visitStatementPtr(stmt);
84}

◆ replace_empty_with_nop()

static std::unique_ptr< Statement > SkSL::replace_empty_with_nop ( std::unique_ptr< Statement stmt,
bool  isEmpty 
)
static

Definition at line 51 of file SkSLIfStatement.cpp.

52 {
53 return (stmt && (!isEmpty || stmt->is<Nop>())) ? std::move(stmt)
54 : Nop::Make();
55}

◆ set_thread_local_memory_pool()

static void SkSL::set_thread_local_memory_pool ( MemoryPool memPool)
static

Definition at line 22 of file SkSLPool.cpp.

22 {
23 sMemPool = memPool;
24}

◆ short_circuit_boolean()

static std::unique_ptr< Expression > SkSL::short_circuit_boolean ( Position  pos,
const Expression left,
Operator  op,
const Expression right 
)
static

Definition at line 71 of file SkSLConstantFolder.cpp.

74 {
75 bool leftVal = left.as<Literal>().boolValue();
76
77 // When the literal is on the left, we can sometimes eliminate the other expression entirely.
78 if ((op.kind() == Operator::Kind::LOGICALAND && !leftVal) || // (false && expr) -> (false)
79 (op.kind() == Operator::Kind::LOGICALOR && leftVal)) { // (true || expr) -> (true)
80
81 return left.clone(pos);
82 }
83
84 // We can't eliminate the right-side expression via short-circuit, but we might still be able to
85 // simplify away a no-op expression.
86 return eliminate_no_op_boolean(pos, right, op, left);
87}

◆ simplify_arithmetic()

static std::unique_ptr< Expression > SkSL::simplify_arithmetic ( const Context context,
Position  pos,
const Expression left,
Operator  op,
const Expression right,
const Type resultType 
)
static

Definition at line 480 of file SkSLConstantFolder.cpp.

485 {
486 switch (op.kind()) {
487 case Operator::Kind::PLUS:
489 ConstantFolder::IsConstantSplat(right, 0.0)) { // x + 0
490 if (std::unique_ptr<Expression> expr = cast_expression(context, pos, left,
491 resultType)) {
492 return expr;
493 }
494 }
496 ConstantFolder::IsConstantSplat(left, 0.0)) { // 0 + x
497 if (std::unique_ptr<Expression> expr = cast_expression(context, pos, right,
498 resultType)) {
499 return expr;
500 }
501 }
502 break;
503
504 case Operator::Kind::STAR:
505 if (is_constant_value(right, 1.0)) { // x * 1
506 if (std::unique_ptr<Expression> expr = cast_expression(context, pos, left,
507 resultType)) {
508 return expr;
509 }
510 }
511 if (is_constant_value(left, 1.0)) { // 1 * x
512 if (std::unique_ptr<Expression> expr = cast_expression(context, pos, right,
513 resultType)) {
514 return expr;
515 }
516 }
517 if (is_constant_value(right, 0.0) && !Analysis::HasSideEffects(left)) { // x * 0
518 return zero_expression(context, pos, resultType);
519 }
520 if (is_constant_value(left, 0.0) && !Analysis::HasSideEffects(right)) { // 0 * x
521 return zero_expression(context, pos, resultType);
522 }
523 if (is_constant_value(right, -1.0)) { // x * -1 (to `-x`)
524 if (std::unique_ptr<Expression> expr = negate_expression(context, pos, left,
525 resultType)) {
526 return expr;
527 }
528 }
529 if (is_constant_value(left, -1.0)) { // -1 * x (to `-x`)
530 if (std::unique_ptr<Expression> expr = negate_expression(context, pos, right,
531 resultType)) {
532 return expr;
533 }
534 }
535 break;
536
537 case Operator::Kind::MINUS:
539 ConstantFolder::IsConstantSplat(right, 0.0)) { // x - 0
540 if (std::unique_ptr<Expression> expr = cast_expression(context, pos, left,
541 resultType)) {
542 return expr;
543 }
544 }
546 ConstantFolder::IsConstantSplat(left, 0.0)) { // 0 - x
547 if (std::unique_ptr<Expression> expr = negate_expression(context, pos, right,
548 resultType)) {
549 return expr;
550 }
551 }
552 break;
553
554 case Operator::Kind::SLASH:
556 ConstantFolder::IsConstantSplat(right, 1.0)) { // x / 1
557 if (std::unique_ptr<Expression> expr = cast_expression(context, pos, left,
558 resultType)) {
559 return expr;
560 }
561 }
562 if (!left.type().isMatrix()) { // convert `x / 2` into `x * 0.5`
563 if (std::unique_ptr<Expression> expr = make_reciprocal_expression(context, right)) {
564 return BinaryExpression::Make(context, pos, left.clone(), Operator::Kind::STAR,
565 std::move(expr));
566 }
567 }
568 break;
569
570 case Operator::Kind::PLUSEQ:
571 case Operator::Kind::MINUSEQ:
572 if (ConstantFolder::IsConstantSplat(right, 0.0)) { // x += 0, x -= 0
573 if (std::unique_ptr<Expression> var = cast_expression(context, pos, left,
574 resultType)) {
575 Analysis::UpdateVariableRefKind(var.get(), VariableRefKind::kRead);
576 return var;
577 }
578 }
579 break;
580
581 case Operator::Kind::STAREQ:
582 if (is_constant_value(right, 1.0)) { // x *= 1
583 if (std::unique_ptr<Expression> var = cast_expression(context, pos, left,
584 resultType)) {
585 Analysis::UpdateVariableRefKind(var.get(), VariableRefKind::kRead);
586 return var;
587 }
588 }
589 break;
590
591 case Operator::Kind::SLASHEQ:
592 if (ConstantFolder::IsConstantSplat(right, 1.0)) { // x /= 1
593 if (std::unique_ptr<Expression> var = cast_expression(context, pos, left,
594 resultType)) {
595 Analysis::UpdateVariableRefKind(var.get(), VariableRefKind::kRead);
596 return var;
597 }
598 }
599 if (std::unique_ptr<Expression> expr = make_reciprocal_expression(context, right)) {
600 return BinaryExpression::Make(context, pos, left.clone(), Operator::Kind::STAREQ,
601 std::move(expr));
602 }
603 break;
604
605 default:
606 break;
607 }
608
609 return nullptr;
610}
static std::unique_ptr< Expression > negate_expression(const Context &context, Position pos, const Expression &expr, const Type &type)
static bool is_matrix_op_scalar(const Expression &left, const Expression &right)
static bool is_constant_value(const Expression &expr, double value)
static std::unique_ptr< Expression > make_reciprocal_expression(const Context &context, const Expression &right)
static std::unique_ptr< Expression > zero_expression(const Context &context, Position pos, const Type &type)

◆ simplify_componentwise()

static std::unique_ptr< Expression > SkSL::simplify_componentwise ( const Context context,
Position  pos,
const Expression left,
Operator  op,
const Expression right 
)
static

Definition at line 215 of file SkSLConstantFolder.cpp.

219 {
220 SkASSERT(is_vec_or_mat(left.type()));
221 SkASSERT(left.type().matches(right.type()));
222 const Type& type = left.type();
223
224 // Handle equality operations: == !=
225 if (std::unique_ptr<Expression> result = simplify_constant_equality(context, pos, left, op,
226 right)) {
227 return result;
228 }
229
230 // Handle floating-point arithmetic: + - * /
231 using FoldFn = double (*)(double, double);
232 FoldFn foldFn;
233 switch (op.kind()) {
234 case Operator::Kind::PLUS: foldFn = +[](double a, double b) { return a + b; }; break;
235 case Operator::Kind::MINUS: foldFn = +[](double a, double b) { return a - b; }; break;
236 case Operator::Kind::STAR: foldFn = +[](double a, double b) { return a * b; }; break;
237 case Operator::Kind::SLASH: foldFn = +[](double a, double b) { return a / b; }; break;
238 default:
239 return nullptr;
240 }
241
242 const Type& componentType = type.componentType();
243 SkASSERT(componentType.isNumber());
244
245 double minimumValue = componentType.minimumValue();
246 double maximumValue = componentType.maximumValue();
247
248 double args[16];
249 int numSlots = type.slotCount();
250 for (int i = 0; i < numSlots; i++) {
251 double value = foldFn(*left.getConstantValue(i), *right.getConstantValue(i));
252 if (value < minimumValue || value > maximumValue) {
253 return nullptr;
254 }
255 args[i] = value;
256 }
257 return ConstructorCompound::MakeFromConstants(context, pos, type, args);
258}
static bool is_vec_or_mat(const Type &type)
static std::unique_ptr< Expression > simplify_constant_equality(const Context &context, Position pos, const Expression &left, Operator op, const Expression &right)

◆ simplify_constant_equality()

static std::unique_ptr< Expression > SkSL::simplify_constant_equality ( const Context context,
Position  pos,
const Expression left,
Operator  op,
const Expression right 
)
static

Definition at line 89 of file SkSLConstantFolder.cpp.

93 {
94 if (op.kind() == Operator::Kind::EQEQ || op.kind() == Operator::Kind::NEQ) {
95 bool equality = (op.kind() == Operator::Kind::EQEQ);
96
97 switch (left.compareConstant(right)) {
98 case Expression::ComparisonResult::kNotEqual:
99 equality = !equality;
100 [[fallthrough]];
101
102 case Expression::ComparisonResult::kEqual:
103 return Literal::MakeBool(context, pos, equality);
104
105 case Expression::ComparisonResult::kUnknown:
106 break;
107 }
108 }
109 return nullptr;
110}

◆ simplify_matrix_division()

static std::unique_ptr< Expression > SkSL::simplify_matrix_division ( const Context context,
Position  pos,
const Expression left,
Operator  op,
const Expression right,
const Type resultType 
)
static

Definition at line 625 of file SkSLConstantFolder.cpp.

630 {
631 // Convert matrix-over-scalar `x /= y` into `x *= (1.0 / y)`. This generates better
632 // code in SPIR-V and Metal, and should be roughly equivalent elsewhere.
633 switch (op.kind()) {
634 case OperatorKind::SLASH:
635 case OperatorKind::SLASHEQ:
636 if (left.type().isMatrix() && right.type().isScalar()) {
637 Operator multiplyOp = op.isAssignment() ? OperatorKind::STAREQ
638 : OperatorKind::STAR;
639 return BinaryExpression::Make(context, pos,
640 left.clone(),
641 multiplyOp,
642 one_over_scalar(context, right));
643 }
644 break;
645
646 default:
647 break;
648 }
649
650 return nullptr;
651}
bool isAssignment() const
static std::unique_ptr< Expression > one_over_scalar(const Context &context, const Expression &right)

◆ simplify_matrix_multiplication()

static std::unique_ptr< Expression > SkSL::simplify_matrix_multiplication ( const Context context,
Position  pos,
const Expression left,
const Expression right,
int  leftColumns,
int  leftRows,
int  rightColumns,
int  rightRows 
)
static

Definition at line 112 of file SkSLConstantFolder.cpp.

119 {
120 const Type& componentType = left.type().componentType();
121 SkASSERT(componentType.matches(right.type().componentType()));
122
123 // Fetch the left matrix.
124 double leftVals[4][4];
125 for (int c = 0; c < leftColumns; ++c) {
126 for (int r = 0; r < leftRows; ++r) {
127 leftVals[c][r] = *left.getConstantValue((c * leftRows) + r);
128 }
129 }
130 // Fetch the right matrix.
131 double rightVals[4][4];
132 for (int c = 0; c < rightColumns; ++c) {
133 for (int r = 0; r < rightRows; ++r) {
134 rightVals[c][r] = *right.getConstantValue((c * rightRows) + r);
135 }
136 }
137
138 SkASSERT(leftColumns == rightRows);
139 int outColumns = rightColumns,
140 outRows = leftRows;
141
142 double args[16];
143 int argIndex = 0;
144 for (int c = 0; c < outColumns; ++c) {
145 for (int r = 0; r < outRows; ++r) {
146 // Compute a dot product for this position.
147 double val = 0;
148 for (int dotIdx = 0; dotIdx < leftColumns; ++dotIdx) {
149 val += leftVals[dotIdx][r] * rightVals[c][dotIdx];
150 }
151
152 if (val >= -FLT_MAX && val <= FLT_MAX) {
153 args[argIndex++] = val;
154 } else {
155 // The value is outside the 32-bit float range, or is NaN; do not optimize.
156 return nullptr;
157 }
158 }
159 }
160
161 if (outColumns == 1) {
162 // Matrix-times-vector conceptually makes a 1-column N-row matrix, but we return vecN.
163 std::swap(outColumns, outRows);
164 }
165
166 const Type& resultType = componentType.toCompound(context, outColumns, outRows);
167 return ConstructorCompound::MakeFromConstants(context, pos, resultType, args);
168}

◆ simplify_matrix_times_matrix()

static std::unique_ptr< Expression > SkSL::simplify_matrix_times_matrix ( const Context context,
Position  pos,
const Expression left,
const Expression right 
)
static

Definition at line 170 of file SkSLConstantFolder.cpp.

173 {
174 const Type& leftType = left.type();
175 const Type& rightType = right.type();
176
177 SkASSERT(leftType.isMatrix());
178 SkASSERT(rightType.isMatrix());
179
181 leftType.columns(), leftType.rows(),
182 rightType.columns(), rightType.rows());
183}
static std::unique_ptr< Expression > simplify_matrix_multiplication(const Context &context, Position pos, const Expression &left, const Expression &right, int leftColumns, int leftRows, int rightColumns, int rightRows)

◆ simplify_matrix_times_vector()

static std::unique_ptr< Expression > SkSL::simplify_matrix_times_vector ( const Context context,
Position  pos,
const Expression left,
const Expression right 
)
static

Definition at line 200 of file SkSLConstantFolder.cpp.

203 {
204 const Type& leftType = left.type();
205 const Type& rightType = right.type();
206
207 SkASSERT(leftType.isMatrix());
208 SkASSERT(rightType.isVector());
209
211 leftType.columns(), leftType.rows(),
212 /*rightColumns=*/1, /*rightRows=*/rightType.columns());
213}

◆ simplify_negation()

static std::unique_ptr< Expression > SkSL::simplify_negation ( const Context context,
Position  pos,
const Expression originalExpr 
)
static

Definition at line 71 of file SkSLPrefixExpression.cpp.

73 {
74 const Expression* value = ConstantFolder::GetConstantValueForVariable(originalExpr);
75 switch (value->kind()) {
76 case Expression::Kind::kLiteral:
77 case Expression::Kind::kConstructorSplat:
78 case Expression::Kind::kConstructorCompound: {
79 // Convert `-vecN(literal, ...)` into `vecN(-literal, ...)`.
80 if (std::unique_ptr<Expression> expr = apply_to_elements(context, pos, *value,
81 negate_value)) {
82 return expr;
83 }
84 break;
85 }
86 case Expression::Kind::kPrefix: {
87 // Convert `-(-expression)` into `expression`.
88 const PrefixExpression& prefix = value->as<PrefixExpression>();
89 if (prefix.getOperator().kind() == Operator::Kind::MINUS) {
90 return prefix.operand()->clone(pos);
91 }
92 break;
93 }
94 case Expression::Kind::kConstructorArray:
95 // Convert `-array[N](literal, ...)` into `array[N](-literal, ...)`.
96 if (Analysis::IsCompileTimeConstant(*value)) {
97 const ConstructorArray& ctor = value->as<ConstructorArray>();
98 return ConstructorArray::Make(context, pos, ctor.type(),
99 negate_operands(context, pos, ctor.arguments()));
100 }
101 break;
102
103 case Expression::Kind::kConstructorDiagonalMatrix:
104 // Convert `-matrix(literal)` into `matrix(-literal)`.
105 if (Analysis::IsCompileTimeConstant(*value)) {
106 const ConstructorDiagonalMatrix& ctor = value->as<ConstructorDiagonalMatrix>();
107 if (std::unique_ptr<Expression> simplified = simplify_negation(context,
108 pos,
109 *ctor.argument())) {
110 return ConstructorDiagonalMatrix::Make(context, pos, ctor.type(),
111 std::move(simplified));
112 }
113 }
114 break;
115
116 default:
117 break;
118 }
119 return nullptr;
120}
static ExpressionArray negate_operands(const Context &context, Position pos, const ExpressionArray &operands)

◆ simplify_vector_times_matrix()

static std::unique_ptr< Expression > SkSL::simplify_vector_times_matrix ( const Context context,
Position  pos,
const Expression left,
const Expression right 
)
static

Definition at line 185 of file SkSLConstantFolder.cpp.

188 {
189 const Type& leftType = left.type();
190 const Type& rightType = right.type();
191
192 SkASSERT(leftType.isVector());
193 SkASSERT(rightType.isMatrix());
194
196 /*leftColumns=*/leftType.columns(), /*leftRows=*/1,
197 rightType.columns(), rightType.rows());
198}

◆ SPIRVtoHLSL()

bool SkSL::SPIRVtoHLSL ( const std::string &  ,
std::string *   
)

Definition at line 47 of file SkSLSPIRVtoHLSL.cpp.

47{ bool SPIRVtoHLSL(const std::string&, std::string*) { return false; } }
bool SPIRVtoHLSL(const std::string &, std::string *)

◆ splat_scalar()

static std::unique_ptr< Expression > SkSL::splat_scalar ( const Context context,
const Expression scalar,
const Type type 
)
static

Definition at line 260 of file SkSLConstantFolder.cpp.

262 {
263 if (type.isVector()) {
264 return ConstructorSplat::Make(context, scalar.fPosition, type, scalar.clone());
265 }
266 if (type.isMatrix()) {
267 int numSlots = type.slotCount();
268 ExpressionArray splatMatrix;
269 splatMatrix.reserve_exact(numSlots);
270 for (int index = 0; index < numSlots; ++index) {
271 splatMatrix.push_back(scalar.clone());
272 }
273 return ConstructorCompound::Make(context, scalar.fPosition, type, std::move(splatMatrix));
274 }
275 SkDEBUGFAILF("unsupported type %s", type.description().c_str());
276 return nullptr;
277}

◆ stod()

bool SkSL::stod ( std::string_view  s,
SKSL_FLOAT value 
)

Definition at line 58 of file SkSLString.cpp.

58 {
59 std::string str(s.data(), s.size());
60 std::stringstream buffer(str);
61 buffer.imbue(std::locale::classic());
62 buffer >> *value;
63 return !buffer.fail() && std::isfinite(*value);
64}
struct MyStruct s
static const uint8_t buffer[]

◆ stoi()

bool SkSL::stoi ( std::string_view  s,
SKSL_INT value 
)

Definition at line 66 of file SkSLString.cpp.

66 {
67 if (s.empty()) {
68 return false;
69 }
70 char suffix = s.back();
71 if (suffix == 'u' || suffix == 'U') {
72 s.remove_suffix(1);
73 }
74 std::string str(s); // s is not null-terminated
75 const char* strEnd = str.data() + str.length();
76 char* p;
77 errno = 0;
78 unsigned long long result = strtoull(str.data(), &p, /*base=*/0);
79 *value = static_cast<SKSL_INT>(result);
80 return p == strEnd && errno == 0 && result <= 0xFFFFFFFF;
81}

◆ strip_export_flag()

static void SkSL::strip_export_flag ( Context context,
const FunctionDeclaration funcDecl,
SymbolTable symbols 
)
static

Definition at line 42 of file SkSLRenamePrivateSymbols.cpp.

44 {
45 // Remove `$export` from every overload of this function.
46 Symbol* mutableSym = symbols->findMutable(funcDecl->name());
47 while (mutableSym) {
48 FunctionDeclaration* mutableDecl = &mutableSym->as<FunctionDeclaration>();
49
50 ModifierFlags flags = mutableDecl->modifierFlags();
51 flags &= ~ModifierFlag::kExport;
52 mutableDecl->setModifierFlags(flags);
53
54 mutableSym = mutableDecl->mutableNextOverload();
55 }
56}
FunctionDeclaration * mutableNextOverload() const
ModifierFlags modifierFlags() const
void setModifierFlags(ModifierFlags m)
std::string_view name() const
Definition SkSLSymbol.h:51

◆ ToGLSL() [1/2]

bool SkSL::ToGLSL ( Program program,
const ShaderCaps caps,
OutputStream out 
)

Converts a Program into GLSL code.

Definition at line 2023 of file SkSLGLSLCodeGenerator.cpp.

2023 {
2024 TRACE_EVENT0("skia.shaders", "SkSL::ToGLSL");
2025 SkASSERT(caps != nullptr);
2026
2027 program.fContext->fErrors->setSource(*program.fSource);
2028 GLSLCodeGenerator cg(program.fContext.get(), caps, &program, &out);
2029 bool result = cg.generateCode();
2030 program.fContext->fErrors->setSource(std::string_view());
2031
2032 return result;
2033}
std::shared_ptr< Context > fContext
std::unique_ptr< std::string > fSource
#define TRACE_EVENT0(category_group, name)

◆ ToGLSL() [2/2]

bool SkSL::ToGLSL ( Program program,
const ShaderCaps caps,
std::string *  out 
)

Definition at line 2035 of file SkSLGLSLCodeGenerator.cpp.

2035 {
2037 if (!ToGLSL(program, caps, buffer)) {
2038 return false;
2039 }
2040 *out = buffer.str();
2041 return true;
2042}
bool ToGLSL(Program &program, const ShaderCaps *caps, OutputStream &out)

◆ ToHLSL() [1/2]

bool SkSL::ToHLSL ( Program program,
const ShaderCaps caps,
OutputStream out 
)

Converts a Program into HLSL code. (SPIRV-Cross must be enabled.)

Definition at line 26 of file SkSLHLSLCodeGenerator.cpp.

26 {
27 TRACE_EVENT0("skia.shaders", "SkSL::ToHLSL");
28 std::string hlsl;
29 if (!ToHLSL(program, caps, &hlsl)) {
30 return false;
31 }
32 out.writeString(hlsl);
33 return true;
34}
bool ToHLSL(Program &program, const ShaderCaps *caps, OutputStream &out)

◆ ToHLSL() [2/2]

bool SkSL::ToHLSL ( Program program,
const ShaderCaps caps,
std::string *  out 
)

Definition at line 36 of file SkSLHLSLCodeGenerator.cpp.

36 {
37 std::string spirv;
38 if (!ToSPIRV(program, caps, &spirv)) {
39 return false;
40 }
41 if (!SPIRVtoHLSL(spirv, out)) {
42 program.fContext->fErrors->error(Position(), "HLSL cross-compilation not enabled");
43 return false;
44 }
45 return true;
46}
bool ToSPIRV(Program &program, const ShaderCaps *caps, OutputStream &out)

◆ ToMetal() [1/2]

bool SkSL::ToMetal ( Program program,
const ShaderCaps caps,
OutputStream out 
)

Converts a Program into Metal code.

Definition at line 3580 of file SkSLMetalCodeGenerator.cpp.

3580 {
3581 TRACE_EVENT0("skia.shaders", "SkSL::ToMetal");
3582 SkASSERT(caps != nullptr);
3583
3584 program.fContext->fErrors->setSource(*program.fSource);
3585 MetalCodeGenerator cg(program.fContext.get(), caps, &program, &out);
3586 bool result = cg.generateCode();
3587 program.fContext->fErrors->setSource(std::string_view());
3588
3589 return result;
3590}

◆ ToMetal() [2/2]

bool SkSL::ToMetal ( Program program,
const ShaderCaps caps,
std::string *  out 
)

Definition at line 3592 of file SkSLMetalCodeGenerator.cpp.

3592 {
3594 if (!ToMetal(program, caps, buffer)) {
3595 return false;
3596 }
3597 *out = buffer.str();
3598 return true;
3599}
bool ToMetal(Program &program, const ShaderCaps *caps, OutputStream &out)

◆ ToSPIRV() [1/2]

bool SkSL::ToSPIRV ( Program program,
const ShaderCaps caps,
OutputStream out 
)

Converts a Program into a SPIR-V binary.

Definition at line 5346 of file SkSLSPIRVCodeGenerator.cpp.

5346 {
5347 TRACE_EVENT0("skia.shaders", "SkSL::ToSPIRV");
5348 SkASSERT(caps != nullptr);
5349
5350 program.fContext->fErrors->setSource(*program.fSource);
5351#ifdef SK_ENABLE_SPIRV_VALIDATION
5353 SPIRVCodeGenerator cg(program.fContext.get(), caps, &program, &buffer);
5354 bool result = cg.generateCode();
5355
5356 if (result && program.fConfig->fSettings.fValidateSPIRV) {
5357 std::string_view binary = buffer.str();
5358 result = validate_spirv(*program.fContext->fErrors, binary);
5359 out.write(binary.data(), binary.size());
5360 }
5361#else
5362 SPIRVCodeGenerator cg(program.fContext.get(), caps, &program, &out);
5363 bool result = cg.generateCode();
5364#endif
5365 program.fContext->fErrors->setSource(std::string_view());
5366
5367 return result;
5368}
std::unique_ptr< ProgramConfig > fConfig

◆ ToSPIRV() [2/2]

bool SkSL::ToSPIRV ( Program program,
const ShaderCaps caps,
std::string *  out 
)

Definition at line 5370 of file SkSLSPIRVCodeGenerator.cpp.

5370 {
5372 if (!ToSPIRV(program, caps, buffer)) {
5373 return false;
5374 }
5375 *out = buffer.str();
5376 return true;
5377}

◆ ToWGSL() [1/2]

bool SkSL::ToWGSL ( Program program,
const ShaderCaps caps,
OutputStream out 
)

Convert a Program into WGSL code.

Definition at line 4546 of file SkSLWGSLCodeGenerator.cpp.

4546 {
4547 TRACE_EVENT0("skia.shaders", "SkSL::ToWGSL");
4548 SkASSERT(caps != nullptr);
4549
4550 program.fContext->fErrors->setSource(*program.fSource);
4551#ifdef SK_ENABLE_WGSL_VALIDATION
4552 StringStream wgsl;
4553 WGSLCodeGenerator cg(program.fContext.get(), caps, &program, &wgsl);
4554 bool result = cg.generateCode();
4555 if (result) {
4556 std::string wgslString = wgsl.str();
4557 std::string warnings;
4558 result = validate_wgsl(*program.fContext->fErrors, wgslString, &warnings);
4559 if (!warnings.empty()) {
4560 out.writeText("/* Tint reported warnings. */\n\n");
4561 }
4562 out.writeString(wgslString);
4563 }
4564#else
4565 WGSLCodeGenerator cg(program.fContext.get(), caps, &program, &out);
4566 bool result = cg.generateCode();
4567#endif
4568 program.fContext->fErrors->setSource(std::string_view());
4569
4570 return result;
4571}
const std::string & str() const

◆ ToWGSL() [2/2]

bool SkSL::ToWGSL ( Program program,
const ShaderCaps caps,
std::string *  out 
)

Definition at line 4573 of file SkSLWGSLCodeGenerator.cpp.

4573 {
4575 if (!ToWGSL(program, caps, buffer)) {
4576 return false;
4577 }
4578 *out = buffer.str();
4579 return true;
4580}
bool ToWGSL(Program &program, const ShaderCaps *caps, OutputStream &out)

◆ type_check_expression()

template<typename T >
static void SkSL::type_check_expression ( const Expression expr)
static

◆ type_check_expression< bool >()

template<>
void SkSL::type_check_expression< bool > ( const Expression expr)

Definition at line 77 of file SkSLFunctionCall.cpp.

77 {
79}

◆ type_check_expression< float >()

template<>
void SkSL::type_check_expression< float > ( const Expression expr)

Definition at line 67 of file SkSLFunctionCall.cpp.

67 {
69}

◆ type_check_expression< SKSL_INT >()

template<>
void SkSL::type_check_expression< SKSL_INT > ( const Expression expr)

Definition at line 72 of file SkSLFunctionCall.cpp.

72 {
74}

◆ type_generically_matches()

static bool SkSL::type_generically_matches ( const Type concreteType,
const Type maybeGenericType 
)
static

Returns true if the types match, or if concreteType can be found in maybeGenericType.

Definition at line 283 of file SkSLFunctionDeclaration.cpp.

283 {
284 return maybeGenericType.isGeneric()
285 ? find_generic_index(concreteType, maybeGenericType, /*allowNarrowing=*/false) != -1
286 : concreteType.matches(maybeGenericType);
287}
bool isGeneric() const
Definition SkSLType.h:500
static int find_generic_index(const Type &concreteType, const Type &genericType, bool allowNarrowing)

◆ type_is_valid_for_color()

static bool SkSL::type_is_valid_for_color ( const Type type)
static

Definition at line 123 of file SkSLFunctionDeclaration.cpp.

123 {
124 return type.isVector() && type.columns() == 4 && type.componentType().isFloat();
125}

◆ type_is_valid_for_coords()

static bool SkSL::type_is_valid_for_coords ( const Type type)
static

Definition at line 127 of file SkSLFunctionDeclaration.cpp.

127 {
128 return type.isVector() && type.highPrecision() && type.columns() == 2 &&
129 type.componentType().isFloat();
130}

◆ type_to_sksltype()

bool SkSL::type_to_sksltype ( const Context context,
const Type type,
SkSLType outType 
)

Definition at line 45 of file SkSLUtil.cpp.

45 {
46 // If a new GrSL type is added, this function will need to be updated.
47 static_assert(kSkSLTypeCount == 41);
48
49 if (type.matches(*context.fTypes.fVoid )) { *outType = SkSLType::kVoid; return true; }
50 if (type.matches(*context.fTypes.fBool )) { *outType = SkSLType::kBool; return true; }
51 if (type.matches(*context.fTypes.fBool2 )) { *outType = SkSLType::kBool2; return true; }
52 if (type.matches(*context.fTypes.fBool3 )) { *outType = SkSLType::kBool3; return true; }
53 if (type.matches(*context.fTypes.fBool4 )) { *outType = SkSLType::kBool4; return true; }
54 if (type.matches(*context.fTypes.fShort )) { *outType = SkSLType::kShort; return true; }
55 if (type.matches(*context.fTypes.fShort2 )) { *outType = SkSLType::kShort2; return true; }
56 if (type.matches(*context.fTypes.fShort3 )) { *outType = SkSLType::kShort3; return true; }
57 if (type.matches(*context.fTypes.fShort4 )) { *outType = SkSLType::kShort4; return true; }
58 if (type.matches(*context.fTypes.fUShort )) { *outType = SkSLType::kUShort; return true; }
59 if (type.matches(*context.fTypes.fUShort2 )) { *outType = SkSLType::kUShort2; return true; }
60 if (type.matches(*context.fTypes.fUShort3 )) { *outType = SkSLType::kUShort3; return true; }
61 if (type.matches(*context.fTypes.fUShort4 )) { *outType = SkSLType::kUShort4; return true; }
62 if (type.matches(*context.fTypes.fFloat )) { *outType = SkSLType::kFloat; return true; }
63 if (type.matches(*context.fTypes.fFloat2 )) { *outType = SkSLType::kFloat2; return true; }
64 if (type.matches(*context.fTypes.fFloat3 )) { *outType = SkSLType::kFloat3; return true; }
65 if (type.matches(*context.fTypes.fFloat4 )) { *outType = SkSLType::kFloat4; return true; }
66 if (type.matches(*context.fTypes.fFloat2x2)) { *outType = SkSLType::kFloat2x2; return true; }
67 if (type.matches(*context.fTypes.fFloat3x3)) { *outType = SkSLType::kFloat3x3; return true; }
68 if (type.matches(*context.fTypes.fFloat4x4)) { *outType = SkSLType::kFloat4x4; return true; }
69 if (type.matches(*context.fTypes.fHalf )) { *outType = SkSLType::kHalf; return true; }
70 if (type.matches(*context.fTypes.fHalf2 )) { *outType = SkSLType::kHalf2; return true; }
71 if (type.matches(*context.fTypes.fHalf3 )) { *outType = SkSLType::kHalf3; return true; }
72 if (type.matches(*context.fTypes.fHalf4 )) { *outType = SkSLType::kHalf4; return true; }
73 if (type.matches(*context.fTypes.fHalf2x2 )) { *outType = SkSLType::kHalf2x2; return true; }
74 if (type.matches(*context.fTypes.fHalf3x3 )) { *outType = SkSLType::kHalf3x3; return true; }
75 if (type.matches(*context.fTypes.fHalf4x4 )) { *outType = SkSLType::kHalf4x4; return true; }
76 if (type.matches(*context.fTypes.fInt )) { *outType = SkSLType::kInt; return true; }
77 if (type.matches(*context.fTypes.fInt2 )) { *outType = SkSLType::kInt2; return true; }
78 if (type.matches(*context.fTypes.fInt3 )) { *outType = SkSLType::kInt3; return true; }
79 if (type.matches(*context.fTypes.fInt4 )) { *outType = SkSLType::kInt4; return true; }
80 if (type.matches(*context.fTypes.fUInt )) { *outType = SkSLType::kUInt; return true; }
81 if (type.matches(*context.fTypes.fUInt2 )) { *outType = SkSLType::kUInt2; return true; }
82 if (type.matches(*context.fTypes.fUInt3 )) { *outType = SkSLType::kUInt3; return true; }
83 if (type.matches(*context.fTypes.fUInt4 )) { *outType = SkSLType::kUInt4; return true; }
84 return false;
85}
static const int kSkSLTypeCount
const std::unique_ptr< Type > fInt4
const std::unique_ptr< Type > fHalf2x2
const std::unique_ptr< Type > fUInt2
const std::unique_ptr< Type > fShort3
const std::unique_ptr< Type > fInt2
const std::unique_ptr< Type > fUShort
const std::unique_ptr< Type > fInt
const std::unique_ptr< Type > fFloat2x2
const std::unique_ptr< Type > fFloat4x4
const std::unique_ptr< Type > fShort2
const std::unique_ptr< Type > fShort
const std::unique_ptr< Type > fInt3
const std::unique_ptr< Type > fUInt3
const std::unique_ptr< Type > fUShort4
const std::unique_ptr< Type > fFloat4
const std::unique_ptr< Type > fHalf2
const std::unique_ptr< Type > fUInt4
const std::unique_ptr< Type > fHalf3x3
const std::unique_ptr< Type > fShort4
const std::unique_ptr< Type > fBool2
const std::unique_ptr< Type > fFloat3x3
const std::unique_ptr< Type > fUShort2
const std::unique_ptr< Type > fBool3
const std::unique_ptr< Type > fUShort3
const std::unique_ptr< Type > fHalf3
const std::unique_ptr< Type > fFloat
const std::unique_ptr< Type > fFloat3
const std::unique_ptr< Type > fHalf
const std::unique_ptr< Type > fHalf4x4
const std::unique_ptr< Type > fBool4

◆ types_match()

static bool SkSL::types_match ( const Type a,
const Type b 
)
static

Definition at line 3640 of file SkSLSPIRVCodeGenerator.cpp.

3640 {
3641 if (a.matches(b)) {
3642 return true;
3643 }
3644 return (a.typeKind() == b.typeKind()) &&
3645 (a.isScalar() || a.isVector() || a.isMatrix()) &&
3646 (a.columns() == b.columns() && a.rows() == b.rows()) &&
3647 a.componentType().numberKind() == b.componentType().numberKind();
3648}

◆ validate_swizzle_domain()

static bool SkSL::validate_swizzle_domain ( const ComponentArray fields)
static

Definition at line 33 of file SkSLSwizzle.cpp.

33 {
34 enum SwizzleDomain {
35 kCoordinate,
36 kColor,
37 kUV,
39 };
40
41 std::optional<SwizzleDomain> domain;
42
43 for (int8_t field : fields) {
44 SwizzleDomain fieldDomain;
45 switch (field) {
46 case SwizzleComponent::X:
47 case SwizzleComponent::Y:
48 case SwizzleComponent::Z:
49 case SwizzleComponent::W:
50 fieldDomain = kCoordinate;
51 break;
52 case SwizzleComponent::R:
53 case SwizzleComponent::G:
54 case SwizzleComponent::B:
55 case SwizzleComponent::A:
56 fieldDomain = kColor;
57 break;
58 case SwizzleComponent::S:
59 case SwizzleComponent::T:
60 case SwizzleComponent::P:
61 case SwizzleComponent::Q:
62 fieldDomain = kUV;
63 break;
64 case SwizzleComponent::UL:
65 case SwizzleComponent::UT:
66 case SwizzleComponent::UR:
67 case SwizzleComponent::UB:
68 fieldDomain = kRectangle;
69 break;
70 case SwizzleComponent::ZERO:
71 case SwizzleComponent::ONE:
72 continue;
73 default:
74 return false;
75 }
76
77 if (!domain.has_value()) {
78 domain = fieldDomain;
79 } else if (domain != fieldDomain) {
80 return false;
81 }
82 }
83
84 return true;
85}

◆ write_stringstream()

void SkSL::write_stringstream ( const StringStream s,
OutputStream out 
)

Definition at line 41 of file SkSLUtil.cpp.

41 {
42 out.write(s.str().c_str(), s.str().size());
43}

◆ zero_expression()

static std::unique_ptr< Expression > SkSL::zero_expression ( const Context context,
Position  pos,
const Type type 
)
static

Definition at line 299 of file SkSLConstantFolder.cpp.

301 {
302 std::unique_ptr<Expression> zero = Literal::Make(pos, 0.0, &type.componentType());
303 if (type.isScalar()) {
304 return zero;
305 }
306 if (type.isVector()) {
307 return ConstructorSplat::Make(context, pos, type, std::move(zero));
308 }
309 if (type.isMatrix()) {
310 return ConstructorDiagonalMatrix::Make(context, pos, type, std::move(zero));
311 }
312 SkDEBUGFAILF("unsupported type %s", type.description().c_str());
313 return nullptr;
314}

Variable Documentation

◆ kAccepts

const uint8_t SkSL::kAccepts[427]
static
Initial value:
= {
255, 255, 89, 89, 92, 68, 73, 92, 43, 41, 41, 41, 41, 36, 41, 41, 41, 41, 37, 41,
41, 41, 27, 58, 82, 63, 67, 87, 44, 45, 56, 80, 54, 52, 78, 51, 55, 53, 79, 50,
1, 255, 255, 1, 57, 255, 255, 91, 90, 81, 2, 1, 1, 255, 255, 1, 255, 255, 1, 2,
3, 255, 255, 1, 3, 2, 2, 255, 2, 2, 2, 70, 88, 75, 59, 83, 77, 71, 72, 74,
76, 60, 84, 69, 42, 42, 48, 49, 62, 86, 66, 42, 42, 40, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 14, 42, 42, 42, 42, 30, 42, 42, 42, 12, 42, 42,
42, 42, 42, 42, 22, 42, 42, 42, 42, 15, 42, 42, 42, 42, 42, 42, 13, 42, 42, 42,
42, 42, 16, 10, 42, 42, 42, 42, 42, 42, 42, 42, 42, 7, 42, 42, 42, 42, 42, 42,
40, 42, 42, 42, 42, 42, 5, 42, 42, 42, 42, 42, 23, 42, 8, 42, 42, 42, 42, 42,
40, 42, 42, 42, 42, 42, 42, 33, 42, 42, 42, 42, 6, 18, 42, 42, 42, 25, 42, 42,
20, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
32, 42, 42, 42, 35, 42, 42, 42, 42, 42, 42, 34, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 26, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 24, 42, 42,
19, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 39, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 28, 42, 42, 42,
17, 42, 42, 42, 42, 42, 42, 42, 42, 40, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 40, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 31, 42, 42, 42, 42, 42, 42, 42, 42, 11, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 4, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 21, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 9, 42, 42, 42, 42, 42, 42, 42, 38, 42, 42, 42, 42, 42, 42, 42,
29, 46, 61, 85, 65, 47, 64,
}

Definition at line 775 of file SkSLLexer.cpp.

775 {
776 255, 255, 89, 89, 92, 68, 73, 92, 43, 41, 41, 41, 41, 36, 41, 41, 41, 41, 37, 41,
777 41, 41, 27, 58, 82, 63, 67, 87, 44, 45, 56, 80, 54, 52, 78, 51, 55, 53, 79, 50,
778 1, 255, 255, 1, 57, 255, 255, 91, 90, 81, 2, 1, 1, 255, 255, 1, 255, 255, 1, 2,
779 3, 255, 255, 1, 3, 2, 2, 255, 2, 2, 2, 70, 88, 75, 59, 83, 77, 71, 72, 74,
780 76, 60, 84, 69, 42, 42, 48, 49, 62, 86, 66, 42, 42, 40, 42, 42, 42, 42, 42, 42,
781 42, 42, 42, 42, 42, 42, 42, 42, 14, 42, 42, 42, 42, 30, 42, 42, 42, 12, 42, 42,
782 42, 42, 42, 42, 22, 42, 42, 42, 42, 15, 42, 42, 42, 42, 42, 42, 13, 42, 42, 42,
783 42, 42, 16, 10, 42, 42, 42, 42, 42, 42, 42, 42, 42, 7, 42, 42, 42, 42, 42, 42,
784 40, 42, 42, 42, 42, 42, 5, 42, 42, 42, 42, 42, 23, 42, 8, 42, 42, 42, 42, 42,
785 40, 42, 42, 42, 42, 42, 42, 33, 42, 42, 42, 42, 6, 18, 42, 42, 42, 25, 42, 42,
786 20, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
787 32, 42, 42, 42, 35, 42, 42, 42, 42, 42, 42, 34, 42, 42, 42, 42, 42, 42, 42, 42,
788 42, 42, 42, 42, 42, 42, 26, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 24, 42, 42,
789 19, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 39, 42, 42,
790 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 28, 42, 42, 42,
791 17, 42, 42, 42, 42, 42, 42, 42, 42, 40, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
792 42, 42, 42, 42, 42, 42, 42, 40, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
793 42, 42, 42, 42, 42, 31, 42, 42, 42, 42, 42, 42, 42, 42, 11, 42, 42, 42, 42, 42,
794 42, 42, 42, 42, 42, 42, 4, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 21, 42,
795 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
796 42, 42, 42, 42, 9, 42, 42, 42, 42, 42, 42, 42, 38, 42, 42, 42, 42, 42, 42, 42,
797 29, 46, 61, 85, 65, 47, 64,
798};

◆ kCompact

constexpr CompactEntry SkSL::kCompact[]
staticconstexpr

Definition at line 121 of file SkSLLexer.cpp.

121 {
122 {0,
123 {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
124 {3,
125 {195, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
126 {6,
127 {255, 255, 255, 255, 255, 255, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
128 {8, {255, 255, 255, 255, 255, 255, 255, 15, 0, 192, 15, 0, 0, 0, 0, 0, 192, 63}},
129 {8, {255, 255, 255, 255, 3, 0, 255, 15, 0, 192, 15, 0, 0, 0, 0, 0, 192, 63}},
130 {19 | (11 << 9) | (10 << 18),
131 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 106, 170, 170, 162, 170, 234, 63}},
132 {10, {255, 255, 255, 255, 3, 0, 255, 15, 0, 192, 15, 0, 0, 0, 0, 0, 192, 63}},
133 {14 | (12 << 9) | (10 << 18),
134 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 170, 170, 106, 170, 232, 63}},
135 {13 | (10 << 9),
136 {255, 255, 255, 255, 87, 84, 255, 95, 85, 213, 95, 85, 85, 85, 85, 85, 213, 63}},
137 {15 | (10 << 9),
138 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
139 {16 | (10 << 9),
140 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 84, 85, 213, 63}},
141 {17 | (10 << 9),
142 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
143 {18 | (10 << 9),
144 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
145 {20 | (10 << 9),
146 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
147 {21 | (10 << 9),
148 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
149 {22 | (10 << 9),
150 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
151 {24,
152 {255, 255, 255, 255, 255, 255, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
153 {27 | (26 << 9),
154 {255, 255, 253, 255, 255, 255, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
155 {31,
156 {255, 255, 255, 255, 255, 255, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
157 {34 | (33 << 9),
158 {255, 255, 255, 253, 255, 255, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
159 {38 | (37 << 9),
160 {255, 255, 255, 223, 255, 255, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
161 {40, {255, 255, 255, 255, 3, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
162 {41 | (40 << 9),
163 {255, 255, 255, 255, 87, 85, 255, 255, 243, 255, 255, 63, 255, 255, 255, 255, 255, 63}},
164 {43 | (42 << 9),
165 {255, 255, 255, 221, 3, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
166 {43, {255, 255, 255, 255, 3, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
167 {49 | (48 << 9) | (45 << 18),
168 {255, 255, 191, 255, 253, 255, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
169 {46 | (45 << 9), {87, 85, 21, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 21}},
170 {47 | (45 << 9), {87, 85, 85, 85, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 21}},
171 {48, {51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
172 {56 | (52 << 9),
173 {255, 255, 255, 255, 87, 85, 255, 255, 243, 255, 255, 63, 255, 255, 255, 255, 255, 63}},
174 {53 | (52 << 9),
175 {255, 255, 255, 255, 87, 85, 255, 255, 243, 255, 255, 63, 255, 255, 255, 255, 255, 63}},
176 {55 | (54 << 9),
177 {255, 255, 255, 221, 3, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
178 {55, {255, 255, 255, 255, 3, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
179 {58 | (57 << 9),
180 {255, 255, 255, 221, 3, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
181 {58, {255, 255, 255, 255, 3, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
182 {63 | (62 << 9),
183 {255, 255, 255, 221, 3, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
184 {63, {255, 255, 255, 255, 3, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
185 {68, {255, 255, 255, 255, 3, 0, 255, 15, 240, 255, 63, 0, 252, 255, 255, 255, 255, 63}},
186 {68 | (66 << 9),
187 {255, 255, 255, 255, 3, 0, 255, 15, 240, 247, 63, 0, 252, 255, 255, 247, 255, 63}},
188 {76 | (74 << 9),
189 {255, 255, 255, 255, 255, 255, 31, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
190 {75,
191 {255, 255, 255, 255, 255, 255, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
192 {78,
193 {255, 255, 255, 255, 255, 255, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
194 {81 | (80 << 9),
195 {255, 255, 255, 255, 255, 255, 127, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
196 {82,
197 {255, 255, 255, 255, 255, 255, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63}},
198 {85, {255, 255, 255, 255, 3, 0, 255, 15, 0, 192, 15, 0, 0, 0, 0, 0, 192, 63}},
199 {90 | (89 << 9),
200 {255, 255, 255, 255, 255, 255, 127, 255, 255, 255, 243, 255, 255, 255, 255, 255, 255, 63}},
201 {94 | (92 << 9) | (85 << 18),
202 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 170, 170, 106, 168, 234, 63}},
203 {93 | (85 << 9),
204 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 69, 85, 85, 213, 63}},
205 {98 | (95 << 9) | (85 << 18),
206 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 170, 170, 169, 168, 234, 63}},
207 {96 | (85 << 9),
208 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 69, 85, 85, 213, 63}},
209 {97 | (85 << 9),
210 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
211 {93 | (85 << 9),
212 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
213 {99 | (85 << 9),
214 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
215 {100 | (85 << 9),
216 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
217 {101 | (85 << 9),
218 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 84, 85, 85, 85, 85, 213, 63}},
219 {102 | (85 << 9),
220 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
221 {103 | (85 << 9),
222 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
223 {93 | (85 << 9),
224 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
225 {109 | (105 << 9) | (85 << 18),
226 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 170, 170, 154, 162, 234, 63}},
227 {106 | (85 << 9),
228 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
229 {107 | (85 << 9),
230 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
231 {108 | (85 << 9),
232 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 84, 85, 85, 213, 63}},
233 {110 | (85 << 9),
234 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 84, 85, 85, 85, 213, 63}},
235 {111 | (85 << 9),
236 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 84, 85, 85, 85, 213, 63}},
237 {112 | (85 << 9),
238 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
239 {113 | (85 << 9),
240 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
241 {116 | (85 << 9),
242 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 21, 85, 213, 63}},
243 {117 | (93 << 9) | (85 << 18),
244 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 42, 170, 170, 170, 169, 234, 63}},
245 {119 | (85 << 9),
246 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
247 {120 | (85 << 9),
248 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 21, 85, 213, 63}},
249 {93 | (85 << 9),
250 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 21, 85, 213, 63}},
251 {122 | (85 << 9),
252 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
253 {125 | (123 << 9) | (85 << 18),
254 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 170, 170, 106, 168, 234, 63}},
255 {124 | (85 << 9),
256 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
257 {126 | (85 << 9),
258 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
259 {127 | (85 << 9),
260 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
261 {128 | (85 << 9),
262 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
263 {129 | (85 << 9),
264 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
265 {132 | (85 << 9),
266 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 84, 85, 85, 85, 213, 63}},
267 {133 | (85 << 9),
268 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
269 {134 | (85 << 9),
270 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
271 {135 | (85 << 9),
272 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
273 {136 | (85 << 9),
274 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
275 {138 | (85 << 9),
276 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 21, 85, 213, 63}},
277 {139 | (85 << 9),
278 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
279 {140 | (85 << 9),
280 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
281 {141 | (85 << 9),
282 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
283 {142 | (85 << 9),
284 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 69, 85, 85, 85, 85, 213, 63}},
285 {144 | (85 << 9),
286 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
287 {145 | (85 << 9),
288 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 84, 85, 85, 85, 85, 213, 63}},
289 {146 | (85 << 9),
290 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
291 {148 | (85 << 9),
292 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
293 {149 | (85 << 9),
294 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
295 {93 | (85 << 9),
296 {255, 255, 255, 255, 23, 80, 255, 95, 85, 213, 95, 85, 85, 85, 85, 85, 213, 63}},
297 {152 | (85 << 9),
298 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 21, 85, 213, 63}},
299 {153 | (85 << 9),
300 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
301 {155 | (85 << 9),
302 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
303 {157 | (85 << 9),
304 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
305 {158 | (85 << 9),
306 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
307 {159 | (85 << 9),
308 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
309 {160 | (85 << 9),
310 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
311 {161 | (85 << 9),
312 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
313 {93 | (85 << 9),
314 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
315 {164 | (85 << 9),
316 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
317 {165 | (85 << 9),
318 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 21, 85, 213, 63}},
319 {166 | (85 << 9),
320 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
321 {168 | (85 << 9),
322 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 85, 212, 63}},
323 {169 | (85 << 9),
324 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
325 {93 | (85 << 9),
326 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 69, 85, 85, 85, 85, 213, 63}},
327 {171 | (85 << 9),
328 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
329 {172 | (85 << 9),
330 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
331 {174 | (85 << 9),
332 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
333 {176 | (85 << 9),
334 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
335 {177 | (85 << 9),
336 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
337 {181 | (179 << 9) | (85 << 18),
338 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 170, 166, 168, 170, 234, 63}},
339 {180 | (85 << 9),
340 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 79, 85, 85, 85, 85, 85, 213, 63}},
341 {180, {255, 255, 255, 255, 3, 0, 255, 15, 0, 192, 15, 0, 0, 0, 0, 0, 192, 63}},
342 {182 | (85 << 9),
343 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
344 {93 | (85 << 9),
345 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 84, 85, 213, 63}},
346 {188 | (184 << 9) | (85 << 18),
347 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 106, 170, 170, 138, 234, 63}},
348 {185 | (85 << 9),
349 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 81, 85, 85, 85, 213, 63}},
350 {186 | (85 << 9),
351 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 69, 85, 85, 85, 213, 63}},
352 {187 | (85 << 9),
353 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
354 {189 | (85 << 9),
355 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
356 {190 | (85 << 9),
357 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
358 {193 | (192 << 9) | (85 << 18),
359 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 169, 42, 170, 170, 234, 63}},
360 {195 | (85 << 9),
361 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
362 {196 | (85 << 9),
363 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
364 {197 | (85 << 9),
365 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
366 {199 | (85 << 9),
367 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
368 {200 | (85 << 9),
369 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
370 {202 | (85 << 9),
371 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
372 {93 | (85 << 9),
373 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
374 {204 | (85 << 9),
375 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
376 {205 | (85 << 9),
377 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
378 {206 | (85 << 9),
379 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 84, 85, 85, 85, 213, 63}},
380 {207 | (85 << 9),
381 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
382 {208 | (85 << 9),
383 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
384 {210 | (85 << 9),
385 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
386 {211 | (85 << 9),
387 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
388 {212 | (85 << 9),
389 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
390 {213 | (85 << 9),
391 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
392 {214 | (85 << 9),
393 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
394 {221 | (216 << 9) | (85 << 18),
395 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 111, 170, 170, 170, 168, 170, 234, 63}},
396 {217 | (85 << 9),
397 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 85, 209, 63}},
398 {218 | (85 << 9),
399 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 84, 85, 213, 63}},
400 {219 | (85 << 9),
401 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
402 {220 | (85 << 9),
403 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
404 {223 | (222 << 9) | (85 << 18),
405 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 170, 106, 170, 42, 234, 63}},
406 {93 | (85 << 9),
407 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 81, 85, 85, 85, 213, 63}},
408 {224 | (85 << 9),
409 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
410 {226 | (85 << 9),
411 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
412 {227 | (85 << 9),
413 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 69, 85, 85, 85, 85, 213, 63}},
414 {228 | (85 << 9),
415 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
416 {229 | (85 << 9),
417 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
418 {230 | (85 << 9),
419 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 69, 85, 85, 213, 63}},
420 {231 | (85 << 9),
421 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
422 {240 | (233 << 9) | (85 << 18),
423 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 111, 170, 170, 170, 168, 170, 234, 63}},
424 {234 | (85 << 9),
425 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 69, 85, 85, 213, 63}},
426 {235 | (85 << 9),
427 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
428 {236 | (85 << 9),
429 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 21, 85, 213, 63}},
430 {237 | (85 << 9),
431 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
432 {238 | (85 << 9),
433 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
434 {239 | (85 << 9),
435 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
436 {247 | (241 << 9) | (85 << 18),
437 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 106, 170, 162, 170, 234, 63}},
438 {242 | (85 << 9),
439 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
440 {243 | (85 << 9),
441 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
442 {244 | (85 << 9),
443 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
444 {245 | (85 << 9),
445 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
446 {246 | (85 << 9),
447 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
448 {248 | (85 << 9),
449 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
450 {249 | (85 << 9),
451 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
452 {250 | (85 << 9),
453 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 21, 85, 213, 63}},
454 {251 | (85 << 9),
455 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
456 {252 | (85 << 9),
457 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
458 {253 | (85 << 9),
459 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
460 {254 | (85 << 9),
461 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
462 {255 | (85 << 9),
463 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
464 {256 | (85 << 9),
465 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 69, 213, 63}},
466 {257 | (85 << 9),
467 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
468 {259 | (85 << 9),
469 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
470 {260 | (85 << 9),
471 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
472 {261 | (85 << 9),
473 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
474 {262 | (85 << 9),
475 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
476 {265 | (85 << 9),
477 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
478 {266 | (85 << 9),
479 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 84, 85, 85, 213, 63}},
480 {267 | (85 << 9),
481 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
482 {269 | (85 << 9),
483 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 85, 212, 63}},
484 {270 | (85 << 9),
485 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
486 {271 | (85 << 9),
487 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
488 {272 | (85 << 9),
489 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 79, 85, 85, 85, 85, 85, 213, 63}},
490 {273 | (85 << 9),
491 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
492 {274 | (85 << 9),
493 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 84, 85, 213, 63}},
494 {275 | (85 << 9),
495 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
496 {276 | (85 << 9),
497 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
498 {277 | (85 << 9),
499 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
500 {279 | (85 << 9),
501 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
502 {280 | (85 << 9),
503 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
504 {281 | (85 << 9),
505 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
506 {282 | (85 << 9),
507 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 21, 85, 213, 63}},
508 {283 | (85 << 9),
509 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
510 {284 | (85 << 9),
511 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 84, 85, 213, 63}},
512 {93 | (85 << 9),
513 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
514 {286 | (85 << 9),
515 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 84, 85, 85, 85, 85, 213, 63}},
516 {287 | (85 << 9),
517 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
518 {288 | (85 << 9),
519 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
520 {290 | (85 << 9),
521 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
522 {297 | (291 << 9) | (85 << 18),
523 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 111, 170, 170, 170, 170, 168, 234, 63}},
524 {292 | (85 << 9),
525 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 69, 85, 85, 85, 85, 213, 63}},
526 {293 | (85 << 9),
527 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 84, 85, 213, 63}},
528 {294 | (85 << 9),
529 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
530 {295 | (85 << 9),
531 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
532 {296 | (85 << 9),
533 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 85, 209, 63}},
534 {298 | (85 << 9),
535 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
536 {299 | (85 << 9),
537 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
538 {300 | (85 << 9),
539 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
540 {303 | (85 << 9),
541 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 69, 85, 85, 213, 63}},
542 {304 | (85 << 9),
543 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
544 {305 | (85 << 9),
545 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
546 {306 | (85 << 9),
547 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
548 {307 | (85 << 9),
549 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
550 {309 | (85 << 9),
551 {255, 255, 255, 255, 87, 85, 255, 95, 84, 213, 95, 85, 85, 85, 85, 85, 213, 63}},
552 {310 | (85 << 9),
553 {255, 255, 255, 255, 87, 85, 255, 95, 85, 212, 95, 85, 85, 85, 85, 85, 213, 63}},
554 {311 | (85 << 9),
555 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 69, 85, 85, 85, 213, 63}},
556 {312 | (85 << 9),
557 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
558 {313 | (85 << 9),
559 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 69, 85, 85, 85, 85, 213, 63}},
560 {314 | (85 << 9),
561 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 84, 85, 213, 63}},
562 {93 | (85 << 9),
563 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 21, 213, 63}},
564 {316 | (85 << 9),
565 {255, 255, 255, 255, 87, 85, 255, 95, 84, 213, 95, 85, 85, 85, 85, 85, 213, 63}},
566 {317 | (310 << 9) | (85 << 18),
567 {255, 255, 255, 255, 171, 170, 255, 175, 42, 233, 175, 170, 170, 170, 170, 170, 234, 63}},
568 {318 | (85 << 9),
569 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
570 {319 | (85 << 9),
571 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
572 {320 | (85 << 9),
573 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
574 {321 | (85 << 9),
575 {255, 255, 255, 255, 87, 85, 255, 95, 85, 212, 95, 85, 85, 85, 85, 85, 213, 63}},
576 {322 | (85 << 9),
577 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 69, 85, 85, 85, 213, 63}},
578 {323 | (85 << 9),
579 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
580 {324 | (85 << 9),
581 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 69, 85, 85, 85, 85, 213, 63}},
582 {325 | (85 << 9),
583 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 84, 85, 213, 63}},
584 {327 | (85 << 9),
585 {255, 255, 255, 255, 87, 85, 255, 95, 84, 213, 95, 85, 85, 85, 85, 85, 213, 63}},
586 {328 | (85 << 9),
587 {255, 255, 255, 255, 87, 85, 255, 95, 21, 213, 95, 85, 85, 85, 85, 85, 213, 63}},
588 {329 | (85 << 9),
589 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
590 {330 | (85 << 9),
591 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
592 {332 | (85 << 9),
593 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
594 {333 | (85 << 9),
595 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 84, 85, 85, 85, 85, 213, 63}},
596 {335 | (85 << 9),
597 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 85, 197, 63}},
598 {336 | (85 << 9),
599 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
600 {337 | (85 << 9),
601 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 84, 85, 213, 63}},
602 {93 | (85 << 9),
603 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 84, 85, 85, 85, 213, 63}},
604 {342 | (339 << 9) | (85 << 18),
605 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 111, 170, 170, 170, 138, 170, 234, 63}},
606 {340 | (85 << 9),
607 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
608 {341 | (85 << 9),
609 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
610 {343 | (85 << 9),
611 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
612 {344 | (85 << 9),
613 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
614 {345 | (85 << 9),
615 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
616 {347 | (85 << 9),
617 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
618 {348 | (85 << 9),
619 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
620 {349 | (85 << 9),
621 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
622 {93 | (85 << 9),
623 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
624 {351 | (85 << 9),
625 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
626 {352 | (85 << 9),
627 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
628 {353 | (85 << 9),
629 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 81, 85, 85, 85, 85, 213, 63}},
630 {354 | (85 << 9),
631 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 69, 85, 85, 85, 213, 63}},
632 {357 | (85 << 9),
633 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 69, 85, 85, 213, 63}},
634 {358 | (85 << 9),
635 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
636 {359 | (85 << 9),
637 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
638 {360 | (85 << 9),
639 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
640 {361 | (85 << 9),
641 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
642 {363 | (85 << 9),
643 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
644 {365 | (85 << 9),
645 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
646 {366 | (85 << 9),
647 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
648 {368 | (85 << 9),
649 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
650 {369 | (85 << 9),
651 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
652 {370 | (85 << 9),
653 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 69, 85, 85, 85, 85, 213, 63}},
654 {371 | (85 << 9),
655 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
656 {385 | (373 << 9) | (85 << 18),
657 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 170, 106, 42, 170, 234, 63}},
658 {380 | (374 << 9) | (85 << 18),
659 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 106, 170, 42, 170, 234, 63}},
660 {379 | (375 << 9) | (85 << 18),
661 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 175, 170, 169, 170, 168, 170, 234, 63}},
662 {376 | (85 << 9),
663 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 84, 85, 213, 63}},
664 {377 | (85 << 9),
665 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
666 {378 | (85 << 9),
667 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 69, 85, 85, 213, 63}},
668 {381 | (85 << 9),
669 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
670 {382 | (85 << 9),
671 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 81, 85, 85, 85, 213, 63}},
672 {383 | (85 << 9),
673 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
674 {384 | (85 << 9),
675 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
676 {386 | (85 << 9),
677 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
678 {387 | (85 << 9),
679 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
680 {394 | (389 << 9) | (85 << 18),
681 {255, 255, 255, 255, 171, 170, 255, 175, 170, 234, 111, 170, 170, 170, 168, 170, 234, 63}},
682 {390 | (85 << 9),
683 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
684 {391 | (85 << 9),
685 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 85, 209, 63}},
686 {392 | (85 << 9),
687 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
688 {393 | (85 << 9),
689 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
690 {395 | (85 << 9),
691 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
692 {396 | (85 << 9),
693 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 31, 85, 85, 85, 85, 85, 213, 63}},
694 {397 | (85 << 9),
695 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
696 {398 | (85 << 9),
697 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
698 {399 | (85 << 9),
699 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
700 {402 | (85 << 9),
701 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
702 {403 | (85 << 9),
703 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
704 {404 | (85 << 9),
705 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
706 {406 | (85 << 9),
707 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
708 {407 | (85 << 9),
709 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 84, 85, 85, 213, 63}},
710 {408 | (85 << 9),
711 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 81, 85, 85, 85, 213, 63}},
712 {409 | (85 << 9),
713 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 69, 85, 213, 63}},
714 {410 | (85 << 9),
715 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 84, 85, 213, 63}},
716 {411 | (85 << 9),
717 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 81, 213, 63}},
718 {412 | (85 << 9),
719 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 81, 85, 213, 63}},
720 {414 | (85 << 9),
721 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 21, 85, 85, 85, 213, 63}},
722 {415 | (85 << 9),
723 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 84, 213, 63}},
724 {416 | (85 << 9),
725 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 21, 85, 85, 85, 85, 213, 63}},
726 {417 | (85 << 9),
727 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 84, 85, 213, 63}},
728 {418 | (85 << 9),
729 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 21, 85, 85, 213, 63}},
730 {419 | (85 << 9),
731 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 81, 85, 85, 213, 63}},
732 {420 | (85 << 9),
733 {255, 255, 255, 255, 87, 85, 255, 95, 85, 213, 95, 85, 85, 85, 85, 85, 209, 63}},
734 {424 | (423 << 9),
735 {255, 255, 255, 255, 255, 255, 127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 60}},
736};

◆ kDefaultInlineThreshold

constexpr int SkSL::kDefaultInlineThreshold = 50
staticconstexpr

Definition at line 40 of file SkSLDefines.h.

◆ kDefaultLayout

constexpr Layout SkSL::kDefaultLayout
staticconstexpr

Definition at line 29 of file SkSLVariable.cpp.

◆ kDeterminant2

constexpr char SkSL::kDeterminant2[]
staticconstexpr
Initial value:
= R"(
float _determinant2(mat2 m) {
return m[0].x*m[1].y - m[0].y*m[1].x;
}
)"

Definition at line 474 of file SkSLGLSLCodeGenerator.cpp.

◆ kDeterminant3

constexpr char SkSL::kDeterminant3[]
staticconstexpr
Initial value:
= R"(
float _determinant3(mat3 m) {
float
a00 = m[0].x, a01 = m[0].y, a02 = m[0].z,
a10 = m[1].x, a11 = m[1].y, a12 = m[1].z,
a20 = m[2].x, a21 = m[2].y, a22 = m[2].z,
b01 = a22*a11 - a12*a21,
b11 =-a22*a10 + a12*a20,
b21 = a21*a10 - a11*a20;
return a00*b01 + a01*b11 + a02*b21;
}
)"

Definition at line 480 of file SkSLGLSLCodeGenerator.cpp.

◆ kDeterminant4

constexpr char SkSL::kDeterminant4[]
staticconstexpr
Initial value:
= R"(
mat4 _determinant4(mat4 m) {
float
a00 = m[0].x, a01 = m[0].y, a02 = m[0].z, a03 = m[0].w,
a10 = m[1].x, a11 = m[1].y, a12 = m[1].z, a13 = m[1].w,
a20 = m[2].x, a21 = m[2].y, a22 = m[2].z, a23 = m[2].w,
a30 = m[3].x, a31 = m[3].y, a32 = m[3].z, a33 = m[3].w,
b00 = a00*a11 - a01*a10,
b01 = a00*a12 - a02*a10,
b02 = a00*a13 - a03*a10,
b03 = a01*a12 - a02*a11,
b04 = a01*a13 - a03*a11,
b05 = a02*a13 - a03*a12,
b06 = a20*a31 - a21*a30,
b07 = a20*a32 - a22*a30,
b08 = a20*a33 - a23*a30,
b09 = a21*a32 - a22*a31,
b10 = a21*a33 - a23*a31,
b11 = a22*a33 - a23*a32;
return b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06;
}
)"

Definition at line 493 of file SkSLGLSLCodeGenerator.cpp.

◆ kFull

constexpr FullEntry SkSL::kFull[]
staticconstexpr

Definition at line 32 of file SkSLLexer.cpp.

32 {
33 {
34 0, 2, 3, 4, 5, 7, 9, 23, 25, 28, 29, 30, 32, 35, 36,
35 39, 44, 50, 69, 69, 69, 69, 69, 69, 71, 72, 73, 77, 79, 83,
36 84, 84, 84, 84, 84, 84, 84, 84, 84, 86, 87, 88, 84, 91, 104,
37 114, 130, 150, 162, 178, 183, 191, 84, 215, 225, 232, 258, 263, 289, 301,
38 355, 372, 388, 400, 84, 84, 84, 421, 422, 425, 426,
39 },
40 {
41 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 59, 59, 59, 59, 59, 59, 60,
42 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 66, 67, 0, 0, 0, 0, 0, 0, 0, 0, 61,
43 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 67, 0, 0, 0, 0, 0, 0,
44 },
45 {
46 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 59, 59, 59, 59, 59, 59, 60,
47 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61,
48 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49 },
50 {
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 60, 60, 60, 60, 60, 60, 60,
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61,
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 },
55 {
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 70, 70, 70, 70, 70, 70, 70,
57 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61,
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 },
60 {
61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,
62 85, 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 85, 85,
63 85, 85, 85, 0, 0, 0, 85, 115, 85, 85, 85, 85, 85, 85, 85, 85, 85, 118,
64 85, 85, 121, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 0, 0, 0, 0,
65 },
66 {
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,
68 85, 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 85, 85,
69 85, 85, 85, 0, 0, 0, 85, 85, 85, 85, 85, 131, 85, 85, 85, 137, 85, 85,
70 85, 85, 143, 85, 85, 85, 85, 85, 147, 85, 85, 85, 85, 0, 0, 0, 0,
71 },
72 {
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,
74 85, 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 85, 85,
75 85, 85, 85, 0, 0, 0, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 151,
76 85, 154, 85, 85, 85, 85, 85, 85, 85, 85, 156, 85, 85, 0, 0, 0, 0,
77 },
78 {
79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,
80 85, 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 85, 85,
81 85, 85, 85, 0, 0, 0, 85, 163, 85, 85, 85, 85, 85, 85, 85, 167, 85, 170,
82 85, 85, 173, 85, 85, 85, 85, 85, 175, 85, 85, 85, 85, 0, 0, 0, 0,
83 },
84 {
85 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,
86 85, 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 85, 85,
87 85, 85, 85, 0, 0, 0, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 194,
88 85, 85, 198, 201, 85, 85, 203, 85, 209, 85, 85, 85, 85, 0, 0, 0, 0,
89 },
90 {
91 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,
92 85, 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 85, 85,
93 85, 85, 85, 0, 0, 0, 85, 264, 85, 85, 85, 85, 85, 85, 85, 268, 85, 85,
94 85, 85, 85, 85, 278, 85, 85, 285, 85, 85, 85, 85, 85, 0, 0, 0, 0,
95 },
96 {
97 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,
98 85, 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 85, 85,
99 85, 85, 85, 0, 0, 0, 85, 302, 85, 85, 85, 85, 85, 85, 85, 334, 85, 85,
100 85, 85, 85, 85, 85, 85, 338, 346, 85, 350, 85, 85, 85, 0, 0, 0, 0,
101 },
102 {
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,
104 308, 315, 326, 85, 85, 85, 0, 0, 0, 0, 0, 0, 85, 331, 85, 85, 85, 85,
105 85, 85, 85, 0, 0, 0, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
106 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 0, 0, 0, 0,
107 },
108 {
109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,
110 85, 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 85, 85,
111 85, 85, 85, 0, 0, 0, 85, 85, 85, 85, 85, 356, 85, 85, 362, 85, 85, 85,
112 85, 85, 85, 85, 364, 85, 85, 85, 85, 85, 85, 367, 85, 0, 0, 0, 0,
113 },
114 {
115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,
116 85, 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 85, 85,
117 85, 85, 85, 0, 0, 0, 85, 85, 85, 85, 85, 85, 85, 85, 401, 85, 85, 85,
118 85, 85, 405, 85, 413, 85, 85, 85, 85, 85, 85, 85, 85, 0, 0, 0, 0,
119 },
120};

◆ kIndices

constexpr IndexEntry SkSL::kIndices[]
staticconstexpr
Initial value:
= {
0, -1, 1, 1, 0, 2, 0, 3, 4, 5, 6, 7, 8, 6, 9, 10, 11, 12,
6, 13, 14, 15, 6, 16, 0, 17, 0, 0, 0, 0, 18, 0, 19, 0, 0, 0,
20, 0, 0, 21, 22, 23, 24, 24, 25, 26, 27, 0, 28, 0, -2, 29, 30, 31,
32, 32, 33, 34, 34, -3, -4, 35, 36, 36, 0, 0, 0, 37, 38, -5, -5, 0,
0, 39, 40, 0, 0, 41, 0, 42, 0, 43, 0, 0, 44, 44, 0, 0, 45, 0,
0, 46, 47, 44, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
44, 62, 63, 64, 65, 44, -6, 66, 67, 44, 68, 69, 70, 71, 72, 73, 44, 74,
75, 76, 77, 44, -7, 78, 79, 80, 81, 82, 44, 83, 84, 85, 86, 87, 44, 88,
89, 90, 57, 91, 92, 93, -8, 94, 95, 44, 96, 47, 97, 98, 99, 100, 101, 102,
-9, 103, 104, 105, 44, 106, 107, 108, 109, 110, 44, 111, 44, 112, 113, 93, 114, 115,
116, 117, 118, 119, 120, 121, 122, 44, 123, 124, 93, 125, 44, -10, 126, 127, 128, 44,
129, 130, 44, 131, 132, 133, 134, 135, 136, 137, 57, 138, 139, 140, 141, 142, 132, 143,
144, 145, 146, 147, 44, 148, 149, 150, 44, 151, 152, 153, 154, 155, 156, 44, 157, 158,
159, 160, 161, 162, 163, 57, 164, 165, 166, 167, 168, 169, 44, 170, 171, 172, 173, 174,
175, 176, 177, 178, 179, 44, 180, 181, 182, 183, 132, -11, 184, 185, 186, 108, 187, 188,
189, 190, 191, 192, 193, 194, 195, 44, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
51, 206, 207, 208, 209, 210, 211, 212, 44, 213, 214, 215, 44, -12, 216, 217, 218, 219,
220, -13, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
237, 227, 238, 239, 240, 241, 132, 242, 243, 57, 244, 245, 246, 247, 248, 249, 250, 51,
251, 252, 253, 44, 254, 255, 256, 257, 258, 259, 260, 261, 44, -14, 262, 263, 264, 265,
266, 57, 267, 70, 268, 269, 44, 270, 271, 272, 273, 247, 274, 275, 276, 277, 278, 279,
44, 202, 280, 281, 282, 283, 108, 284, 285, 149, 286, 287, 288, 289, 290, 149, 291, 292,
293, 294, 295, 57, -15, 296, 297, 298, 44, 299, 300, 301, 302, 303, 304, 305, 44, 306,
307, 308, 309, 310, 311, 312, 44, 0, 313, 0, 0, 0, 0,
}

Definition at line 737 of file SkSLLexer.cpp.

737 {
738 0, -1, 1, 1, 0, 2, 0, 3, 4, 5, 6, 7, 8, 6, 9, 10, 11, 12,
739 6, 13, 14, 15, 6, 16, 0, 17, 0, 0, 0, 0, 18, 0, 19, 0, 0, 0,
740 20, 0, 0, 21, 22, 23, 24, 24, 25, 26, 27, 0, 28, 0, -2, 29, 30, 31,
741 32, 32, 33, 34, 34, -3, -4, 35, 36, 36, 0, 0, 0, 37, 38, -5, -5, 0,
742 0, 39, 40, 0, 0, 41, 0, 42, 0, 43, 0, 0, 44, 44, 0, 0, 45, 0,
743 0, 46, 47, 44, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
744 44, 62, 63, 64, 65, 44, -6, 66, 67, 44, 68, 69, 70, 71, 72, 73, 44, 74,
745 75, 76, 77, 44, -7, 78, 79, 80, 81, 82, 44, 83, 84, 85, 86, 87, 44, 88,
746 89, 90, 57, 91, 92, 93, -8, 94, 95, 44, 96, 47, 97, 98, 99, 100, 101, 102,
747 -9, 103, 104, 105, 44, 106, 107, 108, 109, 110, 44, 111, 44, 112, 113, 93, 114, 115,
748 116, 117, 118, 119, 120, 121, 122, 44, 123, 124, 93, 125, 44, -10, 126, 127, 128, 44,
749 129, 130, 44, 131, 132, 133, 134, 135, 136, 137, 57, 138, 139, 140, 141, 142, 132, 143,
750 144, 145, 146, 147, 44, 148, 149, 150, 44, 151, 152, 153, 154, 155, 156, 44, 157, 158,
751 159, 160, 161, 162, 163, 57, 164, 165, 166, 167, 168, 169, 44, 170, 171, 172, 173, 174,
752 175, 176, 177, 178, 179, 44, 180, 181, 182, 183, 132, -11, 184, 185, 186, 108, 187, 188,
753 189, 190, 191, 192, 193, 194, 195, 44, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
754 51, 206, 207, 208, 209, 210, 211, 212, 44, 213, 214, 215, 44, -12, 216, 217, 218, 219,
755 220, -13, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
756 237, 227, 238, 239, 240, 241, 132, 242, 243, 57, 244, 245, 246, 247, 248, 249, 250, 51,
757 251, 252, 253, 44, 254, 255, 256, 257, 258, 259, 260, 261, 44, -14, 262, 263, 264, 265,
758 266, 57, 267, 70, 268, 269, 44, 270, 271, 272, 273, 247, 274, 275, 276, 277, 278, 279,
759 44, 202, 280, 281, 282, 283, 108, 284, 285, 149, 286, 287, 288, 289, 290, 149, 291, 292,
760 293, 294, 295, 57, -15, 296, 297, 298, 44, 299, 300, 301, 302, 303, 304, 305, 44, 306,
761 307, 308, 309, 310, 311, 312, 44, 0, 313, 0, 0, 0, 0,
762};

◆ kInvalidChar

constexpr uint8_t SkSL::kInvalidChar = 18
staticconstexpr

Definition at line 15 of file SkSLLexer.cpp.

◆ kInverse2

constexpr char SkSL::kInverse2[]
staticconstexpr
Initial value:
= R"(
mat2 _inverse2(mat2 m) {
return mat2(m[1].y, -m[0].y, -m[1].x, m[0].x) / (m[0].x * m[1].y - m[0].y * m[1].x);
}
)"

Definition at line 547 of file SkSLGLSLCodeGenerator.cpp.

◆ kInverse2x2 [1/2]

constexpr char SkSL::kInverse2x2[]
staticconstexpr
Initial value:
= R"(
template <typename T>
matrix<T, 2, 2> mat2_inverse(matrix<T, 2, 2> m) {
return matrix<T, 2, 2>(m[1].y, -m[0].y, -m[1].x, m[0].x) * (1/determinant(m));
}
)"

Definition at line 727 of file SkSLMetalCodeGenerator.cpp.

◆ kInverse2x2 [2/2]

constexpr char SkSL::kInverse2x2[]
staticconstexpr
Initial value:
=
"fn mat2_inverse(m: mat2x2<f32>) -> mat2x2<f32> {"
"\n" "return mat2x2<f32>(m[1].y, -m[0].y, -m[1].x, m[0].x) * (1/determinant(m));"
"\n" "}"
"\n"

Definition at line 3292 of file SkSLWGSLCodeGenerator.cpp.

◆ kInverse3

constexpr char SkSL::kInverse3[]
staticconstexpr
Initial value:
= R"(
mat3 _inverse3(mat3 m) {
float
a00 = m[0].x, a01 = m[0].y, a02 = m[0].z,
a10 = m[1].x, a11 = m[1].y, a12 = m[1].z,
a20 = m[2].x, a21 = m[2].y, a22 = m[2].z,
b01 = a22*a11 - a12*a21,
b11 =-a22*a10 + a12*a20,
b21 = a21*a10 - a11*a20,
det = a00*b01 + a01*b11 + a02*b21;
return mat3(
b01, (-a22*a01 + a02*a21), ( a12*a01 - a02*a11),
b11, ( a22*a00 - a02*a20), (-a12*a00 + a02*a10),
b21, (-a21*a00 + a01*a20), ( a11*a00 - a01*a10)) / det;
}
)"

Definition at line 553 of file SkSLGLSLCodeGenerator.cpp.

◆ kInverse3x3 [1/2]

constexpr char SkSL::kInverse3x3[]
staticconstexpr
Initial value:
= R"(
template <typename T>
matrix<T, 3, 3> mat3_inverse(matrix<T, 3, 3> m) {
T
a00 = m[0].x, a01 = m[0].y, a02 = m[0].z,
a10 = m[1].x, a11 = m[1].y, a12 = m[1].z,
a20 = m[2].x, a21 = m[2].y, a22 = m[2].z,
b01 = a22*a11 - a12*a21,
b11 = -a22*a10 + a12*a20,
b21 = a21*a10 - a11*a20,
det = a00*b01 + a01*b11 + a02*b21;
return matrix<T, 3, 3>(
b01, (-a22*a01 + a02*a21), ( a12*a01 - a02*a11),
b11, ( a22*a00 - a02*a20), (-a12*a00 + a02*a10),
b21, (-a21*a00 + a01*a20), ( a11*a00 - a01*a10)) * (1/det);
}
)"

Definition at line 734 of file SkSLMetalCodeGenerator.cpp.

◆ kInverse3x3 [2/2]

constexpr char SkSL::kInverse3x3[]
staticconstexpr
Initial value:
=
"fn mat3_inverse(m: mat3x3<f32>) -> mat3x3<f32> {"
"\n" "let a00 = m[0].x; let a01 = m[0].y; let a02 = m[0].z;"
"\n" "let a10 = m[1].x; let a11 = m[1].y; let a12 = m[1].z;"
"\n" "let a20 = m[2].x; let a21 = m[2].y; let a22 = m[2].z;"
"\n" "let b01 = a22*a11 - a12*a21;"
"\n" "let b11 = -a22*a10 + a12*a20;"
"\n" "let b21 = a21*a10 - a11*a20;"
"\n" "let det = a00*b01 + a01*b11 + a02*b21;"
"\n" "return mat3x3<f32>(b01, (-a22*a01 + a02*a21), ( a12*a01 - a02*a11),"
"\n" "b11, ( a22*a00 - a02*a20), (-a12*a00 + a02*a10),"
"\n" "b21, (-a21*a00 + a01*a20), ( a11*a00 - a01*a10)) * (1/det);"
"\n" "}"
"\n"

Definition at line 3298 of file SkSLWGSLCodeGenerator.cpp.

◆ kInverse4

constexpr char SkSL::kInverse4[]
staticconstexpr

Definition at line 570 of file SkSLGLSLCodeGenerator.cpp.

◆ kInverse4x4 [1/2]

constexpr char SkSL::kInverse4x4[]
staticconstexpr

Definition at line 752 of file SkSLMetalCodeGenerator.cpp.

◆ kInverse4x4 [2/2]

constexpr char SkSL::kInverse4x4[]
staticconstexpr

Definition at line 3313 of file SkSLWGSLCodeGenerator.cpp.

◆ kLoopTerminationLimit

constexpr int SkSL::kLoopTerminationLimit = 100000
staticconstexpr

Definition at line 36 of file SkSLGetLoopUnrollInfo.cpp.

◆ kMappings

constexpr uint8_t SkSL::kMappings[118]
staticconstexpr
Initial value:
= {
1, 2, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 1, 4, 3, 5, 6, 7, 8, 3, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 22, 22, 23, 23, 24, 25, 26, 27, 28, 29, 3, 30, 30, 31, 32,
33, 30, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 36, 34, 37, 34, 34, 38,
34, 34, 39, 3, 40, 41, 42, 3, 43, 44, 45, 46, 47, 48, 49, 50, 51, 34, 52, 53,
54, 55, 56, 57, 34, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
}

Definition at line 16 of file SkSLLexer.cpp.

16 {
17 1, 2, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
18 3, 3, 3, 1, 4, 3, 5, 6, 7, 8, 3, 9, 10, 11, 12, 13, 14, 15, 16, 17,
19 18, 19, 20, 21, 22, 22, 22, 23, 23, 24, 25, 26, 27, 28, 29, 3, 30, 30, 31, 32,
20 33, 30, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 36, 34, 37, 34, 34, 38,
21 34, 34, 39, 3, 40, 41, 42, 3, 43, 44, 45, 46, 47, 48, 49, 50, 51, 34, 52, 53,
22 54, 55, 56, 57, 34, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
23};

◆ kMaxParseDepth

constexpr int SkSL::kMaxParseDepth = 50
staticconstexpr

Definition at line 75 of file SkSLParser.cpp.

◆ kMaxStructDepth

constexpr int SkSL::kMaxStructDepth = 8
staticconstexpr

Definition at line 40 of file SkSLType.cpp.

◆ kPrivateTypes

constexpr BuiltinTypePtr SkSL::kPrivateTypes[]
staticconstexpr
Initial value:
= {
TYPE(Sampler2D), TYPE(SamplerExternalOES), TYPE(Sampler2DRect),
TYPE(SubpassInput), TYPE(SubpassInputMS),
TYPE(Sampler),
TYPE(Texture2D_sample),
TYPE(Texture2D), TYPE(ReadOnlyTexture2D), TYPE(WriteOnlyTexture2D),
TYPE(GenTexture2D), TYPE(ReadableTexture2D), TYPE(WritableTexture2D),
TYPE(AtomicUInt),
}
#define TYPE(t)

Definition at line 133 of file SkSLModuleLoader.cpp.

133 {
134 TYPE(Sampler2D), TYPE(SamplerExternalOES), TYPE(Sampler2DRect),
135
136 TYPE(SubpassInput), TYPE(SubpassInputMS),
137
138 TYPE(Sampler),
139 TYPE(Texture2D_sample),
140 TYPE(Texture2D), TYPE(ReadOnlyTexture2D), TYPE(WriteOnlyTexture2D),
141 TYPE(GenTexture2D), TYPE(ReadableTexture2D), TYPE(WritableTexture2D),
142
143 TYPE(AtomicUInt),
144};

◆ kRootTypes

constexpr BuiltinTypePtr SkSL::kRootTypes[]
staticconstexpr

Definition at line 95 of file SkSLModuleLoader.cpp.

95 {
96 TYPE(Void),
97
98 TYPE( Float), TYPE( Float2), TYPE( Float3), TYPE( Float4),
99 TYPE( Half), TYPE( Half2), TYPE( Half3), TYPE( Half4),
100 TYPE( Int), TYPE( Int2), TYPE( Int3), TYPE( Int4),
101 TYPE( UInt), TYPE( UInt2), TYPE( UInt3), TYPE( UInt4),
102 TYPE( Short), TYPE( Short2), TYPE( Short3), TYPE( Short4),
103 TYPE(UShort), TYPE(UShort2), TYPE(UShort3), TYPE(UShort4),
104 TYPE( Bool), TYPE( Bool2), TYPE( Bool3), TYPE( Bool4),
105
106 TYPE(Float2x2), TYPE(Float2x3), TYPE(Float2x4),
107 TYPE(Float3x2), TYPE(Float3x3), TYPE(Float3x4),
108 TYPE(Float4x2), TYPE(Float4x3), TYPE(Float4x4),
109
110 TYPE(Half2x2), TYPE(Half2x3), TYPE(Half2x4),
111 TYPE(Half3x2), TYPE(Half3x3), TYPE(Half3x4),
112 TYPE(Half4x2), TYPE(Half4x3), TYPE(Half4x4),
113
114 TYPE(SquareMat), TYPE(SquareHMat),
115 TYPE(Mat), TYPE(HMat),
116
117 // TODO(skia:12349): generic short/ushort
118 TYPE(GenType), TYPE(GenIType), TYPE(GenUType),
119 TYPE(GenHType), /* (GenSType) (GenUSType) */
120 TYPE(GenBType),
121 TYPE(IntLiteral),
122 TYPE(FloatLiteral),
123
124 TYPE(Vec), TYPE(IVec), TYPE(UVec),
125 TYPE(HVec), TYPE(SVec), TYPE(USVec),
126 TYPE(BVec),
127
128 TYPE(ColorFilter),
129 TYPE(Shader),
130 TYPE(Blender),
131};

◆ kVariableSlotLimit

constexpr int SkSL::kVariableSlotLimit = 100000
staticconstexpr

Definition at line 45 of file SkSLDefines.h.

◆ SKSL_MAGIC

const int32_t SkSL::SKSL_MAGIC = 0x001F0000
static

Definition at line 729 of file SkSLSPIRVCodeGenerator.cpp.

◆ sMemPool

thread_local MemoryPool* SkSL::sMemPool = nullptr
static

Definition at line 16 of file SkSLPool.cpp.