/* * Copyright 2023 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "include/core/SkTypes.h" #include "include/private/SkSLIRNode.h" #include "include/private/SkSLModifiers.h" #include "src/sksl/SkSLAnalysis.h" #include "src/sksl/analysis/SkSLProgramVisitor.h" #include "src/sksl/ir/SkSLExpression.h" #include "src/sksl/ir/SkSLFunctionCall.h" #include "src/sksl/ir/SkSLFunctionDeclaration.h" #include "src/sksl/ir/SkSLVariable.h" #include "src/sksl/ir/SkSLVariableReference.h" namespace SkSL { bool Analysis::IsDynamicallyUniformExpression(const Expression& expr) { class IsDynamicallyUniformExpressionVisitor : public ProgramVisitor { public: bool visitExpression(const Expression& expr) override { switch (expr.kind()) { case Expression::Kind::kBinary: case Expression::Kind::kConstructorArray: case Expression::Kind::kConstructorArrayCast: case Expression::Kind::kConstructorCompound: case Expression::Kind::kConstructorCompoundCast: case Expression::Kind::kConstructorDiagonalMatrix: case Expression::Kind::kConstructorMatrixResize: case Expression::Kind::kConstructorScalarCast: case Expression::Kind::kConstructorSplat: case Expression::Kind::kConstructorStruct: case Expression::Kind::kFieldAccess: case Expression::Kind::kIndex: case Expression::Kind::kPostfix: case Expression::Kind::kPrefix: case Expression::Kind::kSwizzle: case Expression::Kind::kTernary: // These expressions might be dynamically uniform, if they are composed entirely // of constants and uniforms. break; case Expression::Kind::kVariableReference: { // Verify that variable references are const or uniform. const Variable* var = expr.as().variable(); if (!var || !(var->modifiers().fFlags & (Modifiers::Flag::kConst_Flag | Modifiers::Flag::kUniform_Flag))) { fIsDynamicallyUniform = false; return true; } break; } case Expression::Kind::kFunctionCall: { // Verify that function calls are pure. const FunctionDeclaration& decl = expr.as().function(); if (!(decl.modifiers().fFlags & Modifiers::Flag::kPure_Flag)) { fIsDynamicallyUniform = false; return true; } break; } case Expression::Kind::kLiteral: // Literals are compile-time constants. return false; default: // This expression isn't dynamically uniform. fIsDynamicallyUniform = false; return true; } return INHERITED::visitExpression(expr); } bool fIsDynamicallyUniform = true; using INHERITED = ProgramVisitor; }; IsDynamicallyUniformExpressionVisitor visitor; visitor.visitExpression(expr); return visitor.fIsDynamicallyUniform; } } // namespace SkSL