/* * Copyright 2022 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "include/private/SkSLModifiers.h" #include "include/private/SkSLProgramElement.h" #include "include/private/SkSLString.h" #include "include/private/SkSLSymbol.h" #include "src/sksl/SkSLAnalysis.h" #include "src/sksl/SkSLModifiersPool.h" #include "src/sksl/SkSLPool.h" #include "src/sksl/SkSLProgramSettings.h" #include "src/sksl/analysis/SkSLProgramUsage.h" #include "src/sksl/ir/SkSLFunctionDeclaration.h" #include "src/sksl/ir/SkSLProgram.h" #include "src/sksl/ir/SkSLSymbolTable.h" // IWYU pragma: keep #include "src/sksl/ir/SkSLVarDeclarations.h" #include "src/sksl/ir/SkSLVariable.h" #include #include namespace SkSL { Program::Program(std::unique_ptr source, std::unique_ptr config, std::shared_ptr context, std::vector> elements, std::vector sharedElements, std::unique_ptr modifiers, std::shared_ptr symbols, std::unique_ptr pool, Inputs inputs) : fSource(std::move(source)) , fConfig(std::move(config)) , fContext(context) , fModifiers(std::move(modifiers)) , fSymbols(symbols) , fPool(std::move(pool)) , fOwnedElements(std::move(elements)) , fSharedElements(std::move(sharedElements)) , fInputs(inputs) { fUsage = Analysis::GetUsage(*this); } Program::~Program() { // Some or all of the program elements are in the pool. To free them safely, we must attach // the pool before destroying any program elements. (Otherwise, we may accidentally call // delete on a pooled node.) AutoAttachPoolToThread attach(fPool.get()); fOwnedElements.clear(); fContext.reset(); fSymbols.reset(); fModifiers.reset(); } std::string Program::description() const { std::string result = fConfig->versionDescription(); for (const ProgramElement* e : this->elements()) { result += e->description(); } return result; } const FunctionDeclaration* Program::getFunction(const char* functionName) const { const Symbol* symbol = fSymbols->find(functionName); bool valid = symbol && symbol->is() && symbol->as().definition(); return valid ? &symbol->as() : nullptr; } static void gather_uniforms(UniformInfo* info, const Type& type, const std::string& name) { switch (type.typeKind()) { case Type::TypeKind::kStruct: for (const auto& f : type.fields()) { gather_uniforms(info, *f.fType, name + "." + std::string(f.fName)); } break; case Type::TypeKind::kArray: for (int i = 0; i < type.columns(); ++i) { gather_uniforms(info, type.componentType(), String::printf("%s[%d]", name.c_str(), i)); } break; case Type::TypeKind::kScalar: case Type::TypeKind::kVector: case Type::TypeKind::kMatrix: info->fUniforms.push_back({name, type.componentType().numberKind(), type.rows(), type.columns(), info->fUniformSlotCount}); info->fUniformSlotCount += type.slotCount(); break; default: break; } } std::unique_ptr Program::getUniformInfo() { auto info = std::make_unique(); for (const ProgramElement* e : this->elements()) { if (!e->is()) { continue; } const GlobalVarDeclaration& decl = e->as(); const Variable& var = *decl.varDeclaration().var(); if (var.modifiers().fFlags & Modifiers::kUniform_Flag) { gather_uniforms(info.get(), var.type(), std::string(var.name())); } } return info; } } // namespace SkSL