/* * Copyright 2024 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 "src/core/SkTHash.h" #include "src/sksl/SkSLContext.h" // IWYU pragma: keep #include "src/sksl/SkSLModule.h" #include "src/sksl/analysis/SkSLProgramUsage.h" #include "src/sksl/ir/SkSLProgram.h" #include "src/sksl/ir/SkSLProgramElement.h" #include "src/sksl/ir/SkSLStructDefinition.h" #include "src/sksl/ir/SkSLSymbol.h" #include "src/sksl/ir/SkSLType.h" #include "src/sksl/transform/SkSLTransform.h" #include #include #include using namespace skia_private; namespace SkSL { static bool contains_builtin_struct(const ProgramUsage& usage) { for (const auto& [symbol, count] : usage.fStructCounts) { const Type& type = symbol->as(); if (type.isBuiltin()) { return true; } } return false; } static void get_struct_definitions_from_module( Program& program, const Module& module, std::vector* addedStructDefs) { // We want to start at the root module and work our way towards the Program, so that structs // are added to the program in the same order that they appear in the Module hierarchy. if (module.fParent) { get_struct_definitions_from_module(program, *module.fParent, addedStructDefs); } // Find StructDefinitions from this Module that are used by the program, and copy them into our // array of shared elements. for (const std::unique_ptr& elem : module.fElements) { if (elem->is()) { const StructDefinition& structDef = elem->as(); int* structCount = program.fUsage->fStructCounts.find(&structDef.type()); if (structCount && *structCount > 0) { addedStructDefs->push_back(&structDef); } } } } void Transform::FindAndDeclareBuiltinStructs(Program& program) { // Check if the program references any builtin structs at all. if (contains_builtin_struct(*program.fUsage)) { // Visit all of our modules to find struct definitions that were referenced by ProgramUsage. std::vector addedStructDefs; get_struct_definitions_from_module(program, *program.fContext->fModule, &addedStructDefs); // Copy the struct definitions into our shared elements, and update ProgramUsage to match. program.fSharedElements.insert(program.fSharedElements.begin(), addedStructDefs.begin(), addedStructDefs.end()); for (const ProgramElement* element : addedStructDefs) { program.fUsage->add(*element); } } } } // namespace SkSL