1 /* 2 * Copyright 2023 Google LLC 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "include/core/SkTypes.h" 9 #include "src/sksl/SkSLAnalysis.h" 10 #include "src/sksl/analysis/SkSLProgramVisitor.h" 11 #include "src/sksl/ir/SkSLExpression.h" 12 #include "src/sksl/ir/SkSLFunctionCall.h" 13 #include "src/sksl/ir/SkSLFunctionDeclaration.h" 14 #include "src/sksl/ir/SkSLIRNode.h" 15 #include "src/sksl/ir/SkSLModifierFlags.h" 16 #include "src/sksl/ir/SkSLVariable.h" 17 #include "src/sksl/ir/SkSLVariableReference.h" 18 19 namespace SkSL { 20 IsDynamicallyUniformExpression(const Expression & expr)21bool Analysis::IsDynamicallyUniformExpression(const Expression& expr) { 22 class IsDynamicallyUniformExpressionVisitor : public ProgramVisitor { 23 public: 24 bool visitExpression(const Expression& expr) override { 25 switch (expr.kind()) { 26 case Expression::Kind::kBinary: 27 case Expression::Kind::kConstructorArray: 28 case Expression::Kind::kConstructorArrayCast: 29 case Expression::Kind::kConstructorCompound: 30 case Expression::Kind::kConstructorCompoundCast: 31 case Expression::Kind::kConstructorDiagonalMatrix: 32 case Expression::Kind::kConstructorMatrixResize: 33 case Expression::Kind::kConstructorScalarCast: 34 case Expression::Kind::kConstructorSplat: 35 case Expression::Kind::kConstructorStruct: 36 case Expression::Kind::kFieldAccess: 37 case Expression::Kind::kIndex: 38 case Expression::Kind::kPostfix: 39 case Expression::Kind::kPrefix: 40 case Expression::Kind::kSwizzle: 41 case Expression::Kind::kTernary: 42 // These expressions might be dynamically uniform, if they are composed entirely 43 // of constants and uniforms. 44 break; 45 46 case Expression::Kind::kVariableReference: { 47 // Verify that variable references are const or uniform. 48 const Variable* var = expr.as<VariableReference>().variable(); 49 if (var && (var->modifierFlags().isConst() || 50 var->modifierFlags().isUniform())) { 51 break; 52 } 53 fIsDynamicallyUniform = false; 54 return true; 55 } 56 case Expression::Kind::kFunctionCall: { 57 // Verify that function calls are pure. 58 const FunctionDeclaration& decl = expr.as<FunctionCall>().function(); 59 if (decl.modifierFlags().isPure()) { 60 break; 61 } 62 fIsDynamicallyUniform = false; 63 return true; 64 } 65 case Expression::Kind::kLiteral: 66 // Literals are compile-time constants. 67 return false; 68 69 default: 70 // This expression isn't dynamically uniform. 71 fIsDynamicallyUniform = false; 72 return true; 73 } 74 return INHERITED::visitExpression(expr); 75 } 76 77 bool fIsDynamicallyUniform = true; 78 using INHERITED = ProgramVisitor; 79 }; 80 81 IsDynamicallyUniformExpressionVisitor visitor; 82 visitor.visitExpression(expr); 83 return visitor.fIsDynamicallyUniform; 84 } 85 86 } // namespace SkSL 87