• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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