1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#ifndef SKSL_PROGRAM 9cb93a386Sopenharmony_ci#define SKSL_PROGRAM 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include <vector> 12cb93a386Sopenharmony_ci#include <memory> 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_ci#include "include/private/SkSLDefines.h" 15cb93a386Sopenharmony_ci#include "include/private/SkSLModifiers.h" 16cb93a386Sopenharmony_ci#include "include/private/SkSLProgramElement.h" 17cb93a386Sopenharmony_ci#include "include/private/SkTHash.h" 18cb93a386Sopenharmony_ci#include "src/sksl/SkSLAnalysis.h" 19cb93a386Sopenharmony_ci#include "src/sksl/SkSLProgramSettings.h" 20cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLExpression.h" 21cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLLiteral.h" 22cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSymbolTable.h" 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ci#ifdef SK_VULKAN 25cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCaps.h" 26cb93a386Sopenharmony_ci#endif 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ci// name of the uniform used to handle features that are sensitive to whether Y is flipped. 29cb93a386Sopenharmony_ci#define SKSL_RTFLIP_NAME "u_skRTFlip" 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_cinamespace SkSL { 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ciclass Context; 34cb93a386Sopenharmony_ciclass Pool; 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci/** 37cb93a386Sopenharmony_ci * Side-car class holding mutable information about a Program's IR 38cb93a386Sopenharmony_ci */ 39cb93a386Sopenharmony_ciclass ProgramUsage { 40cb93a386Sopenharmony_cipublic: 41cb93a386Sopenharmony_ci struct VariableCounts { 42cb93a386Sopenharmony_ci int fDeclared = 0; 43cb93a386Sopenharmony_ci int fRead = 0; 44cb93a386Sopenharmony_ci int fWrite = 0; 45cb93a386Sopenharmony_ci }; 46cb93a386Sopenharmony_ci VariableCounts get(const Variable&) const; 47cb93a386Sopenharmony_ci bool isDead(const Variable&) const; 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci int get(const FunctionDeclaration&) const; 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci void add(const Expression* expr); 52cb93a386Sopenharmony_ci void add(const Statement* stmt); 53cb93a386Sopenharmony_ci void add(const ProgramElement& element); 54cb93a386Sopenharmony_ci void remove(const Expression* expr); 55cb93a386Sopenharmony_ci void remove(const Statement* stmt); 56cb93a386Sopenharmony_ci void remove(const ProgramElement& element); 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci SkTHashMap<const Variable*, VariableCounts> fVariableCounts; 59cb93a386Sopenharmony_ci SkTHashMap<const FunctionDeclaration*, int> fCallCounts; 60cb93a386Sopenharmony_ci}; 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ci/** 63cb93a386Sopenharmony_ci * Represents a fully-digested program, ready for code generation. 64cb93a386Sopenharmony_ci */ 65cb93a386Sopenharmony_cistruct Program { 66cb93a386Sopenharmony_ci using Settings = ProgramSettings; 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci struct Inputs { 69cb93a386Sopenharmony_ci bool fUseFlipRTUniform = false; 70cb93a386Sopenharmony_ci bool operator==(const Inputs& that) const { 71cb93a386Sopenharmony_ci return fUseFlipRTUniform == that.fUseFlipRTUniform; 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci bool operator!=(const Inputs& that) const { return !(*this == that); } 74cb93a386Sopenharmony_ci }; 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci Program(std::unique_ptr<String> source, 77cb93a386Sopenharmony_ci std::unique_ptr<ProgramConfig> config, 78cb93a386Sopenharmony_ci std::shared_ptr<Context> context, 79cb93a386Sopenharmony_ci std::vector<std::unique_ptr<ProgramElement>> elements, 80cb93a386Sopenharmony_ci std::vector<const ProgramElement*> sharedElements, 81cb93a386Sopenharmony_ci std::unique_ptr<ModifiersPool> modifiers, 82cb93a386Sopenharmony_ci std::shared_ptr<SymbolTable> symbols, 83cb93a386Sopenharmony_ci std::unique_ptr<Pool> pool, 84cb93a386Sopenharmony_ci Inputs inputs) 85cb93a386Sopenharmony_ci : fSource(std::move(source)) 86cb93a386Sopenharmony_ci , fConfig(std::move(config)) 87cb93a386Sopenharmony_ci , fContext(context) 88cb93a386Sopenharmony_ci , fSymbols(symbols) 89cb93a386Sopenharmony_ci , fPool(std::move(pool)) 90cb93a386Sopenharmony_ci , fOwnedElements(std::move(elements)) 91cb93a386Sopenharmony_ci , fSharedElements(std::move(sharedElements)) 92cb93a386Sopenharmony_ci , fInputs(inputs) 93cb93a386Sopenharmony_ci , fModifiers(std::move(modifiers)) { 94cb93a386Sopenharmony_ci fUsage = Analysis::GetUsage(*this); 95cb93a386Sopenharmony_ci } 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci ~Program() { 98cb93a386Sopenharmony_ci // Some or all of the program elements are in the pool. To free them safely, we must attach 99cb93a386Sopenharmony_ci // the pool before destroying any program elements. (Otherwise, we may accidentally call 100cb93a386Sopenharmony_ci // delete on a pooled node.) 101cb93a386Sopenharmony_ci AutoAttachPoolToThread attach(fPool.get()); 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci fOwnedElements.clear(); 104cb93a386Sopenharmony_ci fContext.reset(); 105cb93a386Sopenharmony_ci fSymbols.reset(); 106cb93a386Sopenharmony_ci fModifiers.reset(); 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ci class ElementsCollection { 110cb93a386Sopenharmony_ci public: 111cb93a386Sopenharmony_ci class iterator { 112cb93a386Sopenharmony_ci public: 113cb93a386Sopenharmony_ci const ProgramElement* operator*() { 114cb93a386Sopenharmony_ci if (fShared != fSharedEnd) { 115cb93a386Sopenharmony_ci return *fShared; 116cb93a386Sopenharmony_ci } else { 117cb93a386Sopenharmony_ci return fOwned->get(); 118cb93a386Sopenharmony_ci } 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci iterator& operator++() { 122cb93a386Sopenharmony_ci if (fShared != fSharedEnd) { 123cb93a386Sopenharmony_ci ++fShared; 124cb93a386Sopenharmony_ci } else { 125cb93a386Sopenharmony_ci ++fOwned; 126cb93a386Sopenharmony_ci } 127cb93a386Sopenharmony_ci return *this; 128cb93a386Sopenharmony_ci } 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci bool operator==(const iterator& other) const { 131cb93a386Sopenharmony_ci return fOwned == other.fOwned && fShared == other.fShared; 132cb93a386Sopenharmony_ci } 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ci bool operator!=(const iterator& other) const { 135cb93a386Sopenharmony_ci return !(*this == other); 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci private: 139cb93a386Sopenharmony_ci using Owned = std::vector<std::unique_ptr<ProgramElement>>::const_iterator; 140cb93a386Sopenharmony_ci using Shared = std::vector<const ProgramElement*>::const_iterator; 141cb93a386Sopenharmony_ci friend class ElementsCollection; 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci iterator(Owned owned, Owned ownedEnd, Shared shared, Shared sharedEnd) 144cb93a386Sopenharmony_ci : fOwned(owned), fOwnedEnd(ownedEnd), fShared(shared), fSharedEnd(sharedEnd) {} 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci Owned fOwned; 147cb93a386Sopenharmony_ci Owned fOwnedEnd; 148cb93a386Sopenharmony_ci Shared fShared; 149cb93a386Sopenharmony_ci Shared fSharedEnd; 150cb93a386Sopenharmony_ci }; 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ci iterator begin() const { 153cb93a386Sopenharmony_ci return iterator(fProgram.fOwnedElements.begin(), fProgram.fOwnedElements.end(), 154cb93a386Sopenharmony_ci fProgram.fSharedElements.begin(), fProgram.fSharedElements.end()); 155cb93a386Sopenharmony_ci } 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci iterator end() const { 158cb93a386Sopenharmony_ci return iterator(fProgram.fOwnedElements.end(), fProgram.fOwnedElements.end(), 159cb93a386Sopenharmony_ci fProgram.fSharedElements.end(), fProgram.fSharedElements.end()); 160cb93a386Sopenharmony_ci } 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci private: 163cb93a386Sopenharmony_ci friend struct Program; 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ci ElementsCollection(const Program& program) : fProgram(program) {} 166cb93a386Sopenharmony_ci const Program& fProgram; 167cb93a386Sopenharmony_ci }; 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_ci // Can be used to iterate over *all* elements in this Program, both owned and shared (builtin). 170cb93a386Sopenharmony_ci // The iterator's value type is 'const ProgramElement*', so it's clear that you *must not* 171cb93a386Sopenharmony_ci // modify anything (as you might be mutating shared data). 172cb93a386Sopenharmony_ci ElementsCollection elements() const { return ElementsCollection(*this); } 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci String description() const { 175cb93a386Sopenharmony_ci String result; 176cb93a386Sopenharmony_ci for (const ProgramElement* e : this->elements()) { 177cb93a386Sopenharmony_ci result += e->description(); 178cb93a386Sopenharmony_ci } 179cb93a386Sopenharmony_ci return result; 180cb93a386Sopenharmony_ci } 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci const ProgramUsage* usage() const { return fUsage.get(); } 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_ci std::unique_ptr<String> fSource; 185cb93a386Sopenharmony_ci std::unique_ptr<ProgramConfig> fConfig; 186cb93a386Sopenharmony_ci std::shared_ptr<Context> fContext; 187cb93a386Sopenharmony_ci // it's important to keep fOwnedElements defined after (and thus destroyed before) fSymbols, 188cb93a386Sopenharmony_ci // because destroying elements can modify reference counts in symbols 189cb93a386Sopenharmony_ci std::shared_ptr<SymbolTable> fSymbols; 190cb93a386Sopenharmony_ci std::unique_ptr<Pool> fPool; 191cb93a386Sopenharmony_ci // Contains *only* elements owned exclusively by this program. 192cb93a386Sopenharmony_ci std::vector<std::unique_ptr<ProgramElement>> fOwnedElements; 193cb93a386Sopenharmony_ci // Contains *only* elements owned by a built-in module that are included in this program. 194cb93a386Sopenharmony_ci // Use elements() to iterate over the combined set of owned + shared elements. 195cb93a386Sopenharmony_ci std::vector<const ProgramElement*> fSharedElements; 196cb93a386Sopenharmony_ci Inputs fInputs; 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_ciprivate: 199cb93a386Sopenharmony_ci std::unique_ptr<ModifiersPool> fModifiers; 200cb93a386Sopenharmony_ci std::unique_ptr<ProgramUsage> fUsage; 201cb93a386Sopenharmony_ci 202cb93a386Sopenharmony_ci friend class Compiler; 203cb93a386Sopenharmony_ci friend class Inliner; // fUsage 204cb93a386Sopenharmony_ci friend class SPIRVCodeGenerator; // fModifiers 205cb93a386Sopenharmony_ci}; 206cb93a386Sopenharmony_ci 207cb93a386Sopenharmony_ci} // namespace SkSL 208cb93a386Sopenharmony_ci 209cb93a386Sopenharmony_ci#endif 210