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