blob: 0e07fac6f52e06c60a56954c208b40f861a67ada [file] [log] [blame]
/*
* 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<VariableReference>().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<FunctionCall>().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