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 "src/sksl/ir/SkSLType.h" 12 13 #include <cstdint> 14 #include <memory> 15 #include <string> 16 #include <vector> 17 18 // name of the uniform used to handle features that are sensitive to whether Y is flipped. 19 #define SKSL_RTFLIP_NAME "u_skRTFlip" 20 21 namespace SkSL { 22 23 class Context; 24 class FunctionDeclaration; 25 class Pool; 26 class ProgramElement; 27 class ProgramUsage; 28 class SymbolTable; 29 struct ProgramConfig; 30 31 /** Represents a list the Uniforms contained within a Program. */ 32 struct UniformInfo { 33 struct Uniform { 34 std::string fName; 35 SkSL::Type::NumberKind fKind; 36 int fColumns; 37 int fRows; 38 int fSlot; 39 }; 40 std::vector<Uniform> fUniforms; 41 int fUniformSlotCount = 0; 42 }; 43 44 /** A program's inputs and outputs. */ 45 struct ProgramInterface { 46 enum RTFlip : uint8_t { 47 kRTFlip_None = 0b0000'0000, 48 kRTFlip_FragCoord = 0b0000'0001, 49 kRTFlip_Clockwise = 0b0000'0010, 50 kRTFlip_Derivative = 0b0000'0100, 51 }; 52 uint8_t fRTFlipUniform = kRTFlip_None; 53 bool fUseLastFragColor = false; 54 bool fOutputSecondaryColor = false; 55 56 bool operator==(const ProgramInterface& that) const { 57 return fRTFlipUniform == that.fRTFlipUniform && 58 fUseLastFragColor == that.fUseLastFragColor && 59 fOutputSecondaryColor == that.fOutputSecondaryColor; 60 } 61 bool operator!=(const ProgramInterface& that) const { return !(*this == that); } 62 }; 63 64 /** Represents a fully-digested program, ready for code generation. */ 65 struct Program { 66 Program(std::unique_ptr<std::string> source, 67 std::unique_ptr<ProgramConfig> config, 68 std::shared_ptr<Context> context, 69 std::vector<std::unique_ptr<ProgramElement>> elements, 70 std::unique_ptr<SymbolTable> symbols, 71 std::unique_ptr<Pool> pool); 72 73 ~Program(); 74 75 class ElementsCollection { 76 public: 77 class iterator { 78 public: 79 const ProgramElement* operator*() { 80 if (fShared != fSharedEnd) { 81 return *fShared; 82 } else { 83 return fOwned->get(); 84 } 85 } 86 87 iterator& operator++() { 88 if (fShared != fSharedEnd) { 89 ++fShared; 90 } else { 91 ++fOwned; 92 } 93 return *this; 94 } 95 96 bool operator==(const iterator& other) const { 97 return fOwned == other.fOwned && fShared == other.fShared; 98 } 99 100 bool operator!=(const iterator& other) const { 101 return !(*this == other); 102 } 103 104 private: 105 using Owned = std::vector<std::unique_ptr<ProgramElement>>::const_iterator; 106 using Shared = std::vector<const ProgramElement*>::const_iterator; 107 friend class ElementsCollection; 108 iteratorProgram109 iterator(Owned owned, Owned ownedEnd, Shared shared, Shared sharedEnd) 110 : fOwned(owned), fOwnedEnd(ownedEnd), fShared(shared), fSharedEnd(sharedEnd) {} 111 112 Owned fOwned; 113 Owned fOwnedEnd; 114 Shared fShared; 115 Shared fSharedEnd; 116 }; 117 beginProgram118 iterator begin() const { 119 return iterator(fProgram.fOwnedElements.begin(), fProgram.fOwnedElements.end(), 120 fProgram.fSharedElements.begin(), fProgram.fSharedElements.end()); 121 } 122 endProgram123 iterator end() const { 124 return iterator(fProgram.fOwnedElements.end(), fProgram.fOwnedElements.end(), 125 fProgram.fSharedElements.end(), fProgram.fSharedElements.end()); 126 } 127 128 private: 129 friend struct Program; 130 ElementsCollectionProgram131 ElementsCollection(const Program& program) : fProgram(program) {} 132 const Program& fProgram; 133 }; 134 135 /** 136 * Iterates over *all* elements in this Program, both owned and shared (builtin). The iterator's 137 * value type is `const ProgramElement*`, so it's clear that you *must not* modify anything (as 138 * you might be mutating shared data). 139 */ elementsProgram140 ElementsCollection elements() const { return ElementsCollection(*this); } 141 142 /** 143 * Returns a function declaration with the given name; null is returned if the function doesn't 144 * exist or has no definition. If the function might have overloads, you can use nextOverload() 145 * to search for the function with the expected parameter list. 146 */ 147 const FunctionDeclaration* getFunction(const char* functionName) const; 148 149 std::string description() const; usageProgram150 const ProgramUsage* usage() const { return fUsage.get(); } 151 152 std::unique_ptr<std::string> fSource; 153 std::unique_ptr<ProgramConfig> fConfig; 154 std::shared_ptr<Context> fContext; 155 std::unique_ptr<ProgramUsage> fUsage; 156 // it's important to keep fOwnedElements defined after (and thus destroyed before) fSymbols, 157 // because an IR element might access the symbol table during its destruction 158 std::unique_ptr<SymbolTable> fSymbols; 159 std::unique_ptr<Pool> fPool; 160 // Contains *only* elements owned exclusively by this program. 161 std::vector<std::unique_ptr<ProgramElement>> fOwnedElements; 162 // Contains *only* elements owned by a built-in module that are included in this program. 163 // Use elements() to iterate over the combined set of owned + shared elements. 164 std::vector<const ProgramElement*> fSharedElements; 165 ProgramInterface fInterface; 166 167 using Interface = ProgramInterface; 168 }; 169 170 } // namespace SkSL 171 172 #endif 173