blob: 59c91229f85d893fc42ba32d9d27bca71126ba1e [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 Nicholas941e7e22016-12-12 15:33:30 -050021// name of the render target height uniform
22#define SKSL_RTHEIGHT_NAME "u_skRTHeight"
23
ethannicholasb3058bd2016-07-01 08:22:01 -070024namespace SkSL {
25
Ethan Nicholas762466e2017-06-29 10:03:38 -040026class Context;
27
ethannicholasb3058bd2016-07-01 08:22:01 -070028/**
29 * Represents a fully-digested program, ready for code generation.
30 */
31struct Program {
Ethan Nicholas941e7e22016-12-12 15:33:30 -050032 struct Settings {
Ethan Nicholas762466e2017-06-29 10:03:38 -040033 struct Value {
34 Value(bool b)
35 : fKind(kBool_Kind)
36 , fValue(b) {}
37
38 Value(int i)
39 : fKind(kInt_Kind)
40 , fValue(i) {}
41
Ethan Nicholasdfbfc732018-06-18 14:14:13 -040042 Value(unsigned int i)
43 : fKind(kInt_Kind)
44 , fValue(i) {}
45
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070046 std::unique_ptr<Expression> literal(const Context& context, int offset) const {
Ethan Nicholas762466e2017-06-29 10:03:38 -040047 switch (fKind) {
48 case Program::Settings::Value::kBool_Kind:
49 return std::unique_ptr<Expression>(new BoolLiteral(context,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070050 offset,
Ethan Nicholas762466e2017-06-29 10:03:38 -040051 fValue));
52 case Program::Settings::Value::kInt_Kind:
53 return std::unique_ptr<Expression>(new IntLiteral(context,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070054 offset,
Ethan Nicholas762466e2017-06-29 10:03:38 -040055 fValue));
56 default:
Ethan Nicholasd9d33c32018-06-12 11:05:59 -040057 SkASSERT(false);
Ethan Nicholas762466e2017-06-29 10:03:38 -040058 return nullptr;
59 }
60 }
61
62 enum {
63 kBool_Kind,
64 kInt_Kind,
65 } fKind;
66
67 int fValue;
68 };
69
Ethan Nicholas0df1b042017-03-31 13:56:23 -040070#ifdef SKSL_STANDALONE
71 const StandaloneShaderCaps* fCaps = &standaloneCaps;
72#else
Ethan Nicholas941e7e22016-12-12 15:33:30 -050073 const GrShaderCaps* fCaps = nullptr;
Ethan Nicholas0df1b042017-03-31 13:56:23 -040074#endif
Ethan Nicholas38657112017-02-09 17:01:22 -050075 // if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate
76 // must be flipped.
Ethan Nicholas941e7e22016-12-12 15:33:30 -050077 bool fFlipY = false;
Brian Salomondc092132018-04-04 10:14:16 -040078 // If true the destination fragment color is read sk_FragColor. It must be declared inout.
79 bool fFragColorIsInOut = false;
Ethan Nicholas762466e2017-06-29 10:03:38 -040080 // if true, Setting objects (e.g. sk_Caps.fbFetchSupport) should be replaced with their
81 // constant equivalents during compilation
82 bool fReplaceSettings = true;
Ethan Nicholasf7b88202017-09-18 14:10:39 -040083 // if true, all halfs are forced to be floats
84 bool fForceHighPrecision = false;
Brian Osman8a83ca42018-02-12 14:32:17 -050085 // if true, add -0.5 bias to LOD of all texture lookups
86 bool fSharpenTextures = false;
Ethan Nicholas762466e2017-06-29 10:03:38 -040087 std::unordered_map<String, Value> fArgs;
Ethan Nicholas941e7e22016-12-12 15:33:30 -050088 };
89
90 struct Inputs {
91 // if true, this program requires the render target height uniform to be defined
92 bool fRTHeight;
93
Ethan Nicholas38657112017-02-09 17:01:22 -050094 // if true, this program must be recompiled if the flipY setting changes. If false, the
95 // program will compile to the same code regardless of the flipY setting.
96 bool fFlipY;
97
Ethan Nicholas941e7e22016-12-12 15:33:30 -050098 void reset() {
99 fRTHeight = false;
Ethan Nicholas38657112017-02-09 17:01:22 -0500100 fFlipY = false;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500101 }
102
103 bool isEmpty() {
Ethan Nicholas38657112017-02-09 17:01:22 -0500104 return !fRTHeight && !fFlipY;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500105 }
106 };
107
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400108 class iterator {
109 public:
110 ProgramElement& operator*() {
111 if (fIter1 != fEnd1) {
112 return **fIter1;
113 }
114 return **fIter2;
115 }
116
117 iterator& operator++() {
118 if (fIter1 != fEnd1) {
119 ++fIter1;
120 return *this;
121 }
122 ++fIter2;
123 return *this;
124 }
125
126 bool operator==(const iterator& other) const {
127 return fIter1 == other.fIter1 && fIter2 == other.fIter2;
128 }
129
130 bool operator!=(const iterator& other) const {
131 return !(*this == other);
132 }
133
134 private:
135 using inner = std::vector<std::unique_ptr<ProgramElement>>::iterator;
136
137 iterator(inner begin1, inner end1, inner begin2, inner end2)
138 : fIter1(begin1)
139 , fEnd1(end1)
140 , fIter2(begin2)
141 , fEnd2(end2) {}
142
143 inner fIter1;
144 inner fEnd1;
145 inner fIter2;
146 inner fEnd2;
147
148 friend struct Program;
149 };
150
151 class const_iterator {
152 public:
153 const ProgramElement& operator*() {
154 if (fIter1 != fEnd1) {
155 return **fIter1;
156 }
157 return **fIter2;
158 }
159
160 const_iterator& operator++() {
161 if (fIter1 != fEnd1) {
162 ++fIter1;
163 return *this;
164 }
165 ++fIter2;
166 return *this;
167 }
168
169 bool operator==(const const_iterator& other) const {
170 return fIter1 == other.fIter1 && fIter2 == other.fIter2;
171 }
172
173 bool operator!=(const const_iterator& other) const {
174 return !(*this == other);
175 }
176
177 private:
178 using inner = std::vector<std::unique_ptr<ProgramElement>>::const_iterator;
179
180 const_iterator(inner begin1, inner end1, inner begin2, inner end2)
181 : fIter1(begin1)
182 , fEnd1(end1)
183 , fIter2(begin2)
184 , fEnd2(end2) {}
185
186 inner fIter1;
187 inner fEnd1;
188 inner fIter2;
189 inner fEnd2;
190
191 friend struct Program;
192 };
193
ethannicholasb3058bd2016-07-01 08:22:01 -0700194 enum Kind {
195 kFragment_Kind,
Ethan Nicholas52cad152017-02-16 16:37:32 -0500196 kVertex_Kind,
Ethan Nicholas762466e2017-06-29 10:03:38 -0400197 kGeometry_Kind,
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400198 kFragmentProcessor_Kind,
Ethan Nicholasdfbfc732018-06-18 14:14:13 -0400199 kPipelineStage_Kind
ethannicholasb3058bd2016-07-01 08:22:01 -0700200 };
201
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500202 Program(Kind kind,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700203 std::unique_ptr<String> source,
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500204 Settings settings,
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400205 std::shared_ptr<Context> context,
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400206 std::vector<std::unique_ptr<ProgramElement>>* inheritedElements,
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500207 std::vector<std::unique_ptr<ProgramElement>> elements,
208 std::shared_ptr<SymbolTable> symbols,
209 Inputs inputs)
210 : fKind(kind)
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700211 , fSource(std::move(source))
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500212 , fSettings(settings)
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500213 , fContext(context)
Ethan Nicholas6415e0d2017-01-19 16:31:32 +0000214 , fSymbols(symbols)
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400215 , fInputs(inputs)
216 , fInheritedElements(inheritedElements)
217 , fElements(std::move(elements)) {}
218
219 iterator begin() {
220 if (fInheritedElements) {
221 return iterator(fInheritedElements->begin(), fInheritedElements->end(),
222 fElements.begin(), fElements.end());
223 }
224 return iterator(fElements.begin(), fElements.end(), fElements.end(), fElements.end());
225 }
226
227 iterator end() {
228 if (fInheritedElements) {
229 return iterator(fInheritedElements->end(), fInheritedElements->end(),
230 fElements.end(), fElements.end());
231 }
232 return iterator(fElements.end(), fElements.end(), fElements.end(), fElements.end());
233 }
234
235 const_iterator begin() const {
236 if (fInheritedElements) {
237 return const_iterator(fInheritedElements->begin(), fInheritedElements->end(),
238 fElements.begin(), fElements.end());
239 }
240 return const_iterator(fElements.begin(), fElements.end(), fElements.end(), fElements.end());
241 }
242
243 const_iterator end() const {
244 if (fInheritedElements) {
245 return const_iterator(fInheritedElements->end(), fInheritedElements->end(),
246 fElements.end(), fElements.end());
247 }
248 return const_iterator(fElements.end(), fElements.end(), fElements.end(), fElements.end());
249 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700250
251 Kind fKind;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700252 std::unique_ptr<String> fSource;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500253 Settings fSettings;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400254 std::shared_ptr<Context> fContext;
Ethan Nicholas86a43402017-01-19 13:32:00 -0500255 // it's important to keep fElements defined after (and thus destroyed before) fSymbols,
256 // because destroying elements can modify reference counts in symbols
Ethan Nicholas6415e0d2017-01-19 16:31:32 +0000257 std::shared_ptr<SymbolTable> fSymbols;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500258 Inputs fInputs;
Ethan Nicholasdfbfc732018-06-18 14:14:13 -0400259 bool fIsOptimized = false;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400260
261private:
262 std::vector<std::unique_ptr<ProgramElement>>* fInheritedElements;
263 std::vector<std::unique_ptr<ProgramElement>> fElements;
Ethan Nicholasdfbfc732018-06-18 14:14:13 -0400264
265 friend class Compiler;
ethannicholasb3058bd2016-07-01 08:22:01 -0700266};
267
268} // namespace
269
270#endif