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 "src/sksl/ir/SkSLBoolLiteral.h" 15 #include "src/sksl/ir/SkSLExpression.h" 16 #include "src/sksl/ir/SkSLFloatLiteral.h" 17 #include "src/sksl/ir/SkSLIntLiteral.h" 18 #include "src/sksl/ir/SkSLModifiers.h" 19 #include "src/sksl/ir/SkSLProgramElement.h" 20 #include "src/sksl/ir/SkSLSymbolTable.h" 21 22 #ifdef SK_VULKAN 23 #include "src/gpu/vk/GrVkCaps.h" 24 #endif 25 26 // name of the render target width uniform 27 #define SKSL_RTWIDTH_NAME "u_skRTWidth" 28 29 // name of the render target height uniform 30 #define SKSL_RTHEIGHT_NAME "u_skRTHeight" 31 32 namespace SkSL { 33 34 class Context; 35 36 /** 37 * Represents a fully-digested program, ready for code generation. 38 */ 39 struct Program { 40 struct Settings { 41 struct Value { ValueProgram::Settings::Value42 Value(bool b) 43 : fKind(kBool_Kind) 44 , fValue(b) {} 45 ValueProgram::Settings::Value46 Value(int i) 47 : fKind(kInt_Kind) 48 , fValue(i) {} 49 ValueProgram::Settings::Value50 Value(unsigned int i) 51 : fKind(kInt_Kind) 52 , fValue(i) {} 53 ValueProgram::Settings::Value54 Value(float f) 55 : fKind(kFloat_Kind) 56 , fValue(f) {} 57 literalProgram::Settings::Value58 std::unique_ptr<Expression> literal(const Context& context, int offset) const { 59 switch (fKind) { 60 case Program::Settings::Value::kBool_Kind: 61 return std::unique_ptr<Expression>(new BoolLiteral(context, 62 offset, 63 fValue)); 64 case Program::Settings::Value::kInt_Kind: 65 return std::unique_ptr<Expression>(new IntLiteral(context, 66 offset, 67 fValue)); 68 case Program::Settings::Value::kFloat_Kind: 69 return std::unique_ptr<Expression>(new FloatLiteral(context, 70 offset, 71 fValue)); 72 default: 73 SkASSERT(false); 74 return nullptr; 75 } 76 } 77 78 enum { 79 kBool_Kind, 80 kInt_Kind, 81 kFloat_Kind, 82 } fKind; 83 84 int fValue; 85 }; 86 87 #if defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU 88 const StandaloneShaderCaps* fCaps = &standaloneCaps; 89 #else 90 const GrShaderCaps* fCaps = nullptr; 91 #ifdef SK_VULKAN 92 const GrVkCaps* fVkCaps = nullptr; 93 #endif 94 #endif 95 // if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate 96 // must be flipped. 97 bool fFlipY = false; 98 // If true the destination fragment color is read sk_FragColor. It must be declared inout. 99 bool fFragColorIsInOut = false; 100 // if true, Setting objects (e.g. sk_Caps.fbFetchSupport) should be replaced with their 101 // constant equivalents during compilation 102 bool fReplaceSettings = true; 103 // if true, all halfs are forced to be floats 104 bool fForceHighPrecision = false; 105 // if true, add -0.5 bias to LOD of all texture lookups 106 bool fSharpenTextures = false; 107 // if the program needs to create an RTHeight uniform, this is its offset in the uniform 108 // buffer 109 int fRTHeightOffset = -1; 110 std::unordered_map<String, Value> fArgs; 111 }; 112 113 struct Inputs { 114 // if true, this program requires the render target width uniform to be defined 115 bool fRTWidth; 116 117 // if true, this program requires the render target height uniform to be defined 118 bool fRTHeight; 119 120 // if true, this program must be recompiled if the flipY setting changes. If false, the 121 // program will compile to the same code regardless of the flipY setting. 122 bool fFlipY; 123 resetProgram::Inputs124 void reset() { 125 fRTWidth = false; 126 fRTHeight = false; 127 fFlipY = false; 128 } 129 isEmptyProgram::Inputs130 bool isEmpty() { 131 return !fRTWidth && !fRTHeight && !fFlipY; 132 } 133 }; 134 135 class iterator { 136 public: 137 ProgramElement& operator*() { 138 if (fIter1 != fEnd1) { 139 return **fIter1; 140 } 141 return **fIter2; 142 } 143 144 iterator& operator++() { 145 if (fIter1 != fEnd1) { 146 ++fIter1; 147 return *this; 148 } 149 ++fIter2; 150 return *this; 151 } 152 153 bool operator==(const iterator& other) const { 154 return fIter1 == other.fIter1 && fIter2 == other.fIter2; 155 } 156 157 bool operator!=(const iterator& other) const { 158 return !(*this == other); 159 } 160 161 private: 162 using inner = std::vector<std::unique_ptr<ProgramElement>>::iterator; 163 iteratorProgram164 iterator(inner begin1, inner end1, inner begin2, inner end2) 165 : fIter1(begin1) 166 , fEnd1(end1) 167 , fIter2(begin2) 168 , fEnd2(end2) {} 169 170 inner fIter1; 171 inner fEnd1; 172 inner fIter2; 173 inner fEnd2; 174 175 friend struct Program; 176 }; 177 178 class const_iterator { 179 public: 180 const ProgramElement& operator*() { 181 if (fIter1 != fEnd1) { 182 return **fIter1; 183 } 184 return **fIter2; 185 } 186 187 const_iterator& operator++() { 188 if (fIter1 != fEnd1) { 189 ++fIter1; 190 return *this; 191 } 192 ++fIter2; 193 return *this; 194 } 195 196 bool operator==(const const_iterator& other) const { 197 return fIter1 == other.fIter1 && fIter2 == other.fIter2; 198 } 199 200 bool operator!=(const const_iterator& other) const { 201 return !(*this == other); 202 } 203 204 private: 205 using inner = std::vector<std::unique_ptr<ProgramElement>>::const_iterator; 206 const_iteratorProgram207 const_iterator(inner begin1, inner end1, inner begin2, inner end2) 208 : fIter1(begin1) 209 , fEnd1(end1) 210 , fIter2(begin2) 211 , fEnd2(end2) {} 212 213 inner fIter1; 214 inner fEnd1; 215 inner fIter2; 216 inner fEnd2; 217 218 friend struct Program; 219 }; 220 221 enum Kind { 222 kFragment_Kind, 223 kVertex_Kind, 224 kGeometry_Kind, 225 kFragmentProcessor_Kind, 226 kPipelineStage_Kind, 227 kGeneric_Kind, 228 }; 229 ProgramProgram230 Program(Kind kind, 231 std::unique_ptr<String> source, 232 Settings settings, 233 std::shared_ptr<Context> context, 234 std::vector<std::unique_ptr<ProgramElement>>* inheritedElements, 235 std::vector<std::unique_ptr<ProgramElement>> elements, 236 std::shared_ptr<SymbolTable> symbols, 237 Inputs inputs) 238 : fKind(kind) 239 , fSource(std::move(source)) 240 , fSettings(settings) 241 , fContext(context) 242 , fSymbols(symbols) 243 , fInputs(inputs) 244 , fInheritedElements(inheritedElements) 245 , fElements(std::move(elements)) {} 246 beginProgram247 iterator begin() { 248 if (fInheritedElements) { 249 return iterator(fInheritedElements->begin(), fInheritedElements->end(), 250 fElements.begin(), fElements.end()); 251 } 252 return iterator(fElements.begin(), fElements.end(), fElements.end(), fElements.end()); 253 } 254 endProgram255 iterator end() { 256 if (fInheritedElements) { 257 return iterator(fInheritedElements->end(), fInheritedElements->end(), 258 fElements.end(), fElements.end()); 259 } 260 return iterator(fElements.end(), fElements.end(), fElements.end(), fElements.end()); 261 } 262 beginProgram263 const_iterator begin() const { 264 if (fInheritedElements) { 265 return const_iterator(fInheritedElements->begin(), fInheritedElements->end(), 266 fElements.begin(), fElements.end()); 267 } 268 return const_iterator(fElements.begin(), fElements.end(), fElements.end(), fElements.end()); 269 } 270 endProgram271 const_iterator end() const { 272 if (fInheritedElements) { 273 return const_iterator(fInheritedElements->end(), fInheritedElements->end(), 274 fElements.end(), fElements.end()); 275 } 276 return const_iterator(fElements.end(), fElements.end(), fElements.end(), fElements.end()); 277 } 278 279 Kind fKind; 280 std::unique_ptr<String> fSource; 281 Settings fSettings; 282 std::shared_ptr<Context> fContext; 283 // it's important to keep fElements defined after (and thus destroyed before) fSymbols, 284 // because destroying elements can modify reference counts in symbols 285 std::shared_ptr<SymbolTable> fSymbols; 286 Inputs fInputs; 287 bool fIsOptimized = false; 288 289 private: 290 std::vector<std::unique_ptr<ProgramElement>>* fInheritedElements; 291 std::vector<std::unique_ptr<ProgramElement>> fElements; 292 293 friend class Compiler; 294 }; 295 296 } // namespace 297 298 #endif 299