72 MergeSampleUsageVisitor(
const Context& context,
74 bool writesToSampleCoords)
75 :
fContext(context), fChild(child), fWritesToSampleCoords(writesToSampleCoords) {}
83 int elidedSampleCoordCount()
const {
return fElidedSampleCoordCount; }
88 const Variable* fMainCoordsParam =
nullptr;
89 const bool fWritesToSampleCoords;
91 int fElidedSampleCoordCount = 0;
100 bool visitExpression(
const Expression&
e)
override {
107 const Expression* maybeCoords = arguments[0].get();
115 ++fElidedSampleCoordCount;
134 SampleOutsideMainVisitor() {}
136 bool visitExpression(
const Expression&
e)
override {
154 ReturnsNonOpaqueColorVisitor() {}
156 bool visitStatement(
const Statement&
s)
override {
159 bool knownOpaque =
e &&
e->type().slotCount() == 4 &&
168 bool visitExpression(
const Expression&
e)
override {
180 NodeCountVisitor(
int limit) : fLimit(limit) {}
183 this->visitStatement(
s);
187 bool visitExpression(
const Expression&
e)
override {
197 bool visitStatement(
const Statement&
s)
override {
211 VariableWriteVisitor(
const Variable* var)
215 return this->visitStatement(
s);
218 bool visitExpression(
const Expression&
e)
override {
224 ref.
refKind() == VariableReference::RefKind::kPointer)) {
240class IsAssignableVisitor {
245 int oldErrorCount = fErrors->errorCount();
246 this->visitExpression(expr);
248 info->fAssignedVar = fAssignedVar;
250 return fErrors->errorCount() == oldErrorCount;
254 switch (expr.
kind()) {
255 case Expression::Kind::kVariableReference: {
258 auto fieldName = [&] {
260 : std::string(var->name());
262 if (var->modifierFlags().isConst() || var->modifierFlags().isUniform()) {
264 "cannot modify immutable variable '" + fieldName() +
"'");
268 "cannot modify pipeline input variable '" + fieldName() +
"'");
271 fAssignedVar = &varRef;
275 case Expression::Kind::kFieldAccess: {
277 this->visitExpression(*
f.base(), &
f);
280 case Expression::Kind::kSwizzle: {
282 this->checkSwizzleWrite(swizzle);
283 this->visitExpression(*swizzle.
base(), fieldAccess);
290 case Expression::Kind::kPoison:
294 fErrors->error(expr.
fPosition,
"cannot assign to this expression");
300 void checkSwizzleWrite(
const Swizzle& swizzle) {
307 "cannot write to the same swizzle field more than once");
327 bool writesToSampleCoords,
328 int* elidedSampleCoordCount) {
329 MergeSampleUsageVisitor visitor(*program.
fContext, child, writesToSampleCoords);
331 if (elidedSampleCoordCount) {
332 *elidedSampleCoordCount += visitor.elidedSampleCoordCount();
339 for (
const auto& [variable,
counts] : program.
fUsage->fVariableCounts) {
340 if (
counts.fRead > 0 && variable->layout().fBuiltin == builtin) {
349 for (
const std::unique_ptr<ProgramElement>& pe : program.
fOwnedElements) {
370 SampleOutsideMainVisitor visitor;
371 return visitor.visit(program);
386 ReturnsNonOpaqueColorVisitor visitor;
387 return !visitor.visitProgramElement(
function);
393 bool visitExpression(
const Expression& expr)
override {
398 return INHERITED::visitExpression(expr);
404 ContainsRTAdjustVisitor visitor;
405 return visitor.visitExpression(expr);
411 ContainsVariableVisitor(
const Variable* v) : fVariable(v) {}
413 bool visitExpression(
const Expression& expr)
override {
418 return INHERITED::visitExpression(expr);
425 ContainsVariableVisitor visitor{&var};
426 return visitor.visitExpression(expr);
432 bool visitExpression(
const Expression& expr)
override {
433 switch (expr.
kind()) {
438 case Expression::Kind::kConstructorArray:
439 case Expression::Kind::kConstructorCompound:
440 case Expression::Kind::kConstructorDiagonalMatrix:
441 case Expression::Kind::kConstructorMatrixResize:
442 case Expression::Kind::kConstructorSplat:
443 case Expression::Kind::kConstructorStruct:
448 return INHERITED::visitExpression(expr);
457 bool fIsConstant =
true;
461 IsCompileTimeConstantVisitor visitor;
462 visitor.visitExpression(expr);
463 return visitor.fIsConstant;
494 "variable '" + std::string(var->
name()) +
"' must be created in a scope");
500 return NodeCountVisitor{limit}.visit(*
function.body());
504 return VariableWriteVisitor(&var).visit(stmt);
509 return IsAssignableVisitor{
errors ?
errors : &unusedErrors}.visit(expr,
info);
519 if (!
info.fAssignedVar) {
526 info.fAssignedVar->setRefKind(kind);
545 case Expression::Kind::kFunctionReference:
547 case Expression::Kind::kMethodReference:
548 case Expression::Kind::kPoison:
549 case Expression::Kind::kSetting:
550 case Expression::Kind::kTypeReference:
551 case Expression::Kind::kVariableReference:
555 case Expression::Kind::kBinary: {
556 auto&
b =
e.template as<BinaryExpression>();
557 return (
b.left() && this->visitExpressionPtr(
b.left())) ||
558 (
b.right() && this->visitExpressionPtr(
b.right()));
560 case Expression::Kind::kChildCall: {
562 auto& c =
e.template as<ChildCall>();
563 for (
auto& arg : c.arguments()) {
564 if (arg && this->visitExpressionPtr(arg)) {
return true; }
568 case Expression::Kind::kConstructorArray:
569 case Expression::Kind::kConstructorArrayCast:
570 case Expression::Kind::kConstructorCompound:
571 case Expression::Kind::kConstructorCompoundCast:
572 case Expression::Kind::kConstructorDiagonalMatrix:
573 case Expression::Kind::kConstructorMatrixResize:
574 case Expression::Kind::kConstructorScalarCast:
575 case Expression::Kind::kConstructorSplat:
576 case Expression::Kind::kConstructorStruct: {
577 auto& c =
e.asAnyConstructor();
578 for (
auto& arg : c.argumentSpan()) {
579 if (this->visitExpressionPtr(arg)) {
return true; }
583 case Expression::Kind::kFieldAccess:
584 return this->visitExpressionPtr(
e.template as<FieldAccess>().base());
586 case Expression::Kind::kFunctionCall: {
587 auto& c =
e.template as<FunctionCall>();
588 for (
auto& arg : c.arguments()) {
589 if (arg && this->visitExpressionPtr(arg)) {
return true; }
594 auto&
i =
e.template as<IndexExpression>();
595 return this->visitExpressionPtr(
i.base()) || this->visitExpressionPtr(
i.index());
597 case Expression::Kind::kPostfix:
598 return this->visitExpressionPtr(
e.template as<PostfixExpression>().operand());
600 case Expression::Kind::kPrefix:
601 return this->visitExpressionPtr(
e.template as<PrefixExpression>().operand());
603 case Expression::Kind::kSwizzle: {
604 auto&
s =
e.template as<Swizzle>();
605 return s.base() && this->visitExpressionPtr(
s.base());
608 case Expression::Kind::kTernary: {
609 auto& t =
e.template as<TernaryExpression>();
610 return this->visitExpressionPtr(t.test()) ||
611 (t.ifTrue() && this->visitExpressionPtr(t.ifTrue())) ||
612 (t.ifFalse() && this->visitExpressionPtr(t.ifFalse()));
621 case Statement::Kind::kBreak:
628 case Statement::Kind::kBlock:
629 for (
auto& stmt :
s.template as<Block>().children()) {
630 if (stmt && this->visitStatementPtr(stmt)) {
636 case Statement::Kind::kSwitchCase: {
637 auto& sc =
s.template as<SwitchCase>();
638 return this->visitStatementPtr(sc.statement());
640 case Statement::Kind::kDo: {
641 auto&
d =
s.template as<DoStatement>();
642 return this->visitExpressionPtr(
d.test()) || this->visitStatementPtr(
d.statement());
644 case Statement::Kind::kExpression:
645 return this->visitExpressionPtr(
s.template as<ExpressionStatement>().expression());
647 case Statement::Kind::kFor: {
648 auto&
f =
s.template as<ForStatement>();
649 return (
f.initializer() && this->visitStatementPtr(
f.initializer())) ||
650 (
f.test() && this->visitExpressionPtr(
f.test())) ||
651 (
f.next() && this->visitExpressionPtr(
f.next())) ||
652 this->visitStatementPtr(
f.statement());
654 case Statement::Kind::kIf: {
655 auto&
i =
s.template as<IfStatement>();
656 return (
i.test() && this->visitExpressionPtr(
i.test())) ||
657 (
i.ifTrue() && this->visitStatementPtr(
i.ifTrue())) ||
658 (
i.ifFalse() && this->visitStatementPtr(
i.ifFalse()));
660 case Statement::Kind::kReturn: {
661 auto& r =
s.template as<ReturnStatement>();
662 return r.expression() && this->visitExpressionPtr(r.expression());
664 case Statement::Kind::kSwitch: {
665 auto& sw =
s.template as<SwitchStatement>();
666 return this->visitExpressionPtr(sw.value()) || this->visitStatementPtr(sw.caseBlock());
668 case Statement::Kind::kVarDeclaration: {
669 auto& v =
s.template as<VarDeclaration>();
670 return v.value() && this->visitExpressionPtr(v.value());
680 case ProgramElement::Kind::kFunctionPrototype:
681 case ProgramElement::Kind::kInterfaceBlock:
682 case ProgramElement::Kind::kModifiers:
683 case ProgramElement::Kind::kStructDefinition:
688 return this->visitStatementPtr(pe.template as<FunctionDefinition>().body());
690 case ProgramElement::Kind::kGlobalVar:
691 return this->visitStatementPtr(pe.template as<GlobalVarDeclaration>().declaration());
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
#define INHERITED(method,...)
constexpr int SK_FRAGCOORD_BUILTIN
const StatementArray & children() const
const Variable & child() const
static constexpr const char RTADJUST_NAME[]
static const Expression * GetConstantValueForVariable(const Expression &value)
const Type & type() const
virtual std::optional< double > getConstantValue(int n) const
std::string description() const final
const Variable * getMainCoordsParameter() const
IntrinsicKind intrinsicKind() const
const FunctionDeclaration & declaration() const
std::unique_ptr< Expression > & base()
skia_private::THashMap< const Symbol *, int > fCallCounts
bool visit(const Program &program)
SampleUsage merge(const SampleUsage &other)
static SampleUsage Explicit()
static SampleUsage PassThrough()
std::unique_ptr< Expression > & base()
const ComponentArray & components() const
std::string_view name() const
virtual bool visitStatement(typename T::Statement &statement)
virtual bool visitExpression(typename T::Expression &expression)
virtual bool visitProgramElement(typename T::ProgramElement &programElement)
bool matches(const Type &other) const
const Variable * variable() const
std::string description() const override
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Dart_NativeFunction function
bool IsCompileTimeConstant(const Expression &expr)
bool ContainsVariable(const Expression &expr, const Variable &var)
bool ContainsRTAdjust(const Expression &expr)
bool ReturnsOpaqueColor(const FunctionDefinition &function)
bool ReferencesBuiltin(const Program &program, int builtin)
bool ReferencesFragCoords(const Program &program)
SampleUsage GetSampleUsage(const Program &program, const Variable &child, bool writesToSampleCoords=true, int *elidedSampleCoordCount=nullptr)
int NodeCountUpToLimit(const FunctionDefinition &function, int limit)
bool ReferencesSampleCoords(const Program &program)
bool DetectVarDeclarationWithoutScope(const Statement &stmt, ErrorReporter *errors=nullptr)
bool CallsColorTransformIntrinsics(const Program &program)
bool UpdateVariableRefKind(Expression *expr, VariableRefKind kind, ErrorReporter *errors=nullptr)
bool CallsSampleOutsideMain(const Program &program)
bool StatementWritesToVariable(const Statement &stmt, const Variable &var)
bool IsAssignable(Expression &expr, AssignmentInfo *info=nullptr, ErrorReporter *errors=nullptr)
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
std::vector< std::unique_ptr< ProgramElement > > fOwnedElements
ElementsCollection elements() const
std::shared_ptr< Context > fContext
const ProgramUsage * usage() const
std::unique_ptr< ProgramUsage > fUsage