blob: 719767d91f472806ab7a9eae2c864c4ce1c6818e [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
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 */
Ethan Nicholas941e7e22016-12-12 15:33:30 -05007
ethannicholasb3058bd2016-07-01 08:22:01 -07008#ifndef SKSL_PROGRAM
9#define SKSL_PROGRAM
10
11#include <vector>
12#include <memory>
13
Ethan Nicholas762466e2017-06-29 10:03:38 -040014#include "SkSLBoolLiteral.h"
15#include "SkSLExpression.h"
16#include "SkSLIntLiteral.h"
ethannicholas5961bc92016-10-12 06:39:56 -070017#include "SkSLModifiers.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070018#include "SkSLProgramElement.h"
ethannicholasd598f792016-07-25 10:08:54 -070019#include "SkSLSymbolTable.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070020
Ethan Nicholascd700e92018-08-24 16:43:57 -040021// name of the render target width uniform
22#define SKSL_RTWIDTH_NAME "u_skRTWidth"
23
Greg Daniele6ab9982018-08-22 13:56:32 +000024// name of the render target height uniform
25#define SKSL_RTHEIGHT_NAME "u_skRTHeight"
Ethan Nicholas941e7e22016-12-12 15:33:30 -050026
ethannicholasb3058bd2016-07-01 08:22:01 -070027namespace SkSL {
28
Ethan Nicholas762466e2017-06-29 10:03:38 -040029class Context;
30
ethannicholasb3058bd2016-07-01 08:22:01 -070031/**
32 * Represents a fully-digested program, ready for code generation.
33 */
34struct Program {
Ethan Nicholas941e7e22016-12-12 15:33:30 -050035 struct Settings {
Ethan Nicholas762466e2017-06-29 10:03:38 -040036 struct Value {
37 Value(bool b)
38 : fKind(kBool_Kind)
39 , fValue(b) {}
40
41 Value(int i)
42 : fKind(kInt_Kind)
43 , fValue(i) {}
44
Ethan Nicholas00543112018-07-31 09:44:36 -040045 Value(unsigned int i)
46 : fKind(kInt_Kind)
47 , fValue(i) {}
48
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070049 std::unique_ptr<Expression> literal(const Context& context, int offset) const {
Ethan Nicholas762466e2017-06-29 10:03:38 -040050 switch (fKind) {
51 case Program::Settings::Value::kBool_Kind:
52 return std::unique_ptr<Expression>(new BoolLiteral(context,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070053 offset,
Ethan Nicholas762466e2017-06-29 10:03:38 -040054 fValue));
55 case Program::Settings::Value::kInt_Kind:
56 return std::unique_ptr<Expression>(new IntLiteral(context,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070057 offset,
Ethan Nicholas762466e2017-06-29 10:03:38 -040058 fValue));
59 default:
Ethan Nicholasd9d33c32018-06-12 11:05:59 -040060 SkASSERT(false);
Ethan Nicholas762466e2017-06-29 10:03:38 -040061 return nullptr;
62 }
63 }
64
65 enum {
66 kBool_Kind,
67 kInt_Kind,
68 } fKind;
69
70 int fValue;
71 };
72
Ethan Nicholas0df1b042017-03-31 13:56:23 -040073#ifdef SKSL_STANDALONE
74 const StandaloneShaderCaps* fCaps = &standaloneCaps;
75#else
Ethan Nicholas941e7e22016-12-12 15:33:30 -050076 const GrShaderCaps* fCaps = nullptr;
Ethan Nicholas0df1b042017-03-31 13:56:23 -040077#endif
Ethan Nicholas38657112017-02-09 17:01:22 -050078 // if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate
79 // must be flipped.
Ethan Nicholas941e7e22016-12-12 15:33:30 -050080 bool fFlipY = false;
Brian Salomondc092132018-04-04 10:14:16 -040081 // If true the destination fragment color is read sk_FragColor. It must be declared inout.
82 bool fFragColorIsInOut = false;
Ethan Nicholas762466e2017-06-29 10:03:38 -040083 // if true, Setting objects (e.g. sk_Caps.fbFetchSupport) should be replaced with their
84 // constant equivalents during compilation
85 bool fReplaceSettings = true;
Ethan Nicholasf7b88202017-09-18 14:10:39 -040086 // if true, all halfs are forced to be floats
87 bool fForceHighPrecision = false;
Brian Osman8a83ca42018-02-12 14:32:17 -050088 // if true, add -0.5 bias to LOD of all texture lookups
89 bool fSharpenTextures = false;
Ethan Nicholas762466e2017-06-29 10:03:38 -040090 std::unordered_map<String, Value> fArgs;
Ethan Nicholas941e7e22016-12-12 15:33:30 -050091 };
92
93 struct Inputs {
Ethan Nicholascd700e92018-08-24 16:43:57 -040094 // if true, this program requires the render target width uniform to be defined
95 bool fRTWidth;
96
Greg Daniele6ab9982018-08-22 13:56:32 +000097 // if true, this program requires the render target height uniform to be defined
98 bool fRTHeight;
Ethan Nicholas941e7e22016-12-12 15:33:30 -050099
Ethan Nicholas38657112017-02-09 17:01:22 -0500100 // if true, this program must be recompiled if the flipY setting changes. If false, the
101 // program will compile to the same code regardless of the flipY setting.
102 bool fFlipY;
103
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500104 void reset() {
Ethan Nicholascd700e92018-08-24 16:43:57 -0400105 fRTWidth = false;
Greg Daniele6ab9982018-08-22 13:56:32 +0000106 fRTHeight = false;
Ethan Nicholas38657112017-02-09 17:01:22 -0500107 fFlipY = false;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500108 }
109
110 bool isEmpty() {
Ethan Nicholascd700e92018-08-24 16:43:57 -0400111 return !fRTWidth && !fRTHeight && !fFlipY;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500112 }
113 };
114
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400115 class iterator {
116 public:
117 ProgramElement& operator*() {
118 if (fIter1 != fEnd1) {
119 return **fIter1;
120 }
121 return **fIter2;
122 }
123
124 iterator& operator++() {
125 if (fIter1 != fEnd1) {
126 ++fIter1;
127 return *this;
128 }
129 ++fIter2;
130 return *this;
131 }
132
133 bool operator==(const iterator& other) const {
134 return fIter1 == other.fIter1 && fIter2 == other.fIter2;
135 }
136
137 bool operator!=(const iterator& other) const {
138 return !(*this == other);
139 }
140
141 private:
142 using inner = std::vector<std::unique_ptr<ProgramElement>>::iterator;
143
144 iterator(inner begin1, inner end1, inner begin2, inner end2)
145 : fIter1(begin1)
146 , fEnd1(end1)
147 , fIter2(begin2)
148 , fEnd2(end2) {}
149
150 inner fIter1;
151 inner fEnd1;
152 inner fIter2;
153 inner fEnd2;
154
155 friend struct Program;
156 };
157
158 class const_iterator {
159 public:
160 const ProgramElement& operator*() {
161 if (fIter1 != fEnd1) {
162 return **fIter1;
163 }
164 return **fIter2;
165 }
166
167 const_iterator& operator++() {
168 if (fIter1 != fEnd1) {
169 ++fIter1;
170 return *this;
171 }
172 ++fIter2;
173 return *this;
174 }
175
176 bool operator==(const const_iterator& other) const {
177 return fIter1 == other.fIter1 && fIter2 == other.fIter2;
178 }
179
180 bool operator!=(const const_iterator& other) const {
181 return !(*this == other);
182 }
183
184 private:
185 using inner = std::vector<std::unique_ptr<ProgramElement>>::const_iterator;
186
187 const_iterator(inner begin1, inner end1, inner begin2, inner end2)
188 : fIter1(begin1)
189 , fEnd1(end1)
190 , fIter2(begin2)
191 , fEnd2(end2) {}
192
193 inner fIter1;
194 inner fEnd1;
195 inner fIter2;
196 inner fEnd2;
197
198 friend struct Program;
199 };
200
ethannicholasb3058bd2016-07-01 08:22:01 -0700201 enum Kind {
202 kFragment_Kind,
Ethan Nicholas52cad152017-02-16 16:37:32 -0500203 kVertex_Kind,
Ethan Nicholas762466e2017-06-29 10:03:38 -0400204 kGeometry_Kind,
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400205 kFragmentProcessor_Kind,
Ethan Nicholas00543112018-07-31 09:44:36 -0400206 kPipelineStage_Kind
ethannicholasb3058bd2016-07-01 08:22:01 -0700207 };
208
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500209 Program(Kind kind,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700210 std::unique_ptr<String> source,
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500211 Settings settings,
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400212 std::shared_ptr<Context> context,
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400213 std::vector<std::unique_ptr<ProgramElement>>* inheritedElements,
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500214 std::vector<std::unique_ptr<ProgramElement>> elements,
215 std::shared_ptr<SymbolTable> symbols,
216 Inputs inputs)
217 : fKind(kind)
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700218 , fSource(std::move(source))
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500219 , fSettings(settings)
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500220 , fContext(context)
Ethan Nicholas6415e0d2017-01-19 16:31:32 +0000221 , fSymbols(symbols)
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400222 , fInputs(inputs)
223 , fInheritedElements(inheritedElements)
224 , fElements(std::move(elements)) {}
225
Ethan Nicholas222e2752018-10-11 11:21:34 -0400226 ~Program() {
227 // destroy elements in reverse order, so references to variables are destroyed before the
228 // variables themselves
229 while (fElements.size()) {
230 fElements.pop_back();
231 }
232 }
233
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400234 iterator begin() {
235 if (fInheritedElements) {
236 return iterator(fInheritedElements->begin(), fInheritedElements->end(),
237 fElements.begin(), fElements.end());
238 }
239 return iterator(fElements.begin(), fElements.end(), fElements.end(), fElements.end());
240 }
241
242 iterator end() {
243 if (fInheritedElements) {
244 return iterator(fInheritedElements->end(), fInheritedElements->end(),
245 fElements.end(), fElements.end());
246 }
247 return iterator(fElements.end(), fElements.end(), fElements.end(), fElements.end());
248 }
249
250 const_iterator begin() const {
251 if (fInheritedElements) {
252 return const_iterator(fInheritedElements->begin(), fInheritedElements->end(),
253 fElements.begin(), fElements.end());
254 }
255 return const_iterator(fElements.begin(), fElements.end(), fElements.end(), fElements.end());
256 }
257
258 const_iterator end() const {
259 if (fInheritedElements) {
260 return const_iterator(fInheritedElements->end(), fInheritedElements->end(),
261 fElements.end(), fElements.end());
262 }
263 return const_iterator(fElements.end(), fElements.end(), fElements.end(), fElements.end());
264 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700265
266 Kind fKind;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700267 std::unique_ptr<String> fSource;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500268 Settings fSettings;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400269 std::shared_ptr<Context> fContext;
Ethan Nicholas86a43402017-01-19 13:32:00 -0500270 // it's important to keep fElements defined after (and thus destroyed before) fSymbols,
271 // because destroying elements can modify reference counts in symbols
Ethan Nicholas6415e0d2017-01-19 16:31:32 +0000272 std::shared_ptr<SymbolTable> fSymbols;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500273 Inputs fInputs;
Ethan Nicholas00543112018-07-31 09:44:36 -0400274 bool fIsOptimized = false;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400275
276private:
277 std::vector<std::unique_ptr<ProgramElement>>* fInheritedElements;
278 std::vector<std::unique_ptr<ProgramElement>> fElements;
Ethan Nicholas00543112018-07-31 09:44:36 -0400279
280 friend class Compiler;
ethannicholasb3058bd2016-07-01 08:22:01 -0700281};
282
283} // namespace
284
285#endif