blob: 9f140877b7850a38448ba94a0abbb6cca8e86a99 [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 Nicholas5b5f0962017-09-11 13:50:14 -070042 std::unique_ptr<Expression> literal(const Context& context, int offset) const {
Ethan Nicholas762466e2017-06-29 10:03:38 -040043 switch (fKind) {
44 case Program::Settings::Value::kBool_Kind:
45 return std::unique_ptr<Expression>(new BoolLiteral(context,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070046 offset,
Ethan Nicholas762466e2017-06-29 10:03:38 -040047 fValue));
48 case Program::Settings::Value::kInt_Kind:
49 return std::unique_ptr<Expression>(new IntLiteral(context,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070050 offset,
Ethan Nicholas762466e2017-06-29 10:03:38 -040051 fValue));
52 default:
Ethan Nicholasd9d33c32018-06-12 11:05:59 -040053 SkASSERT(false);
Ethan Nicholas762466e2017-06-29 10:03:38 -040054 return nullptr;
55 }
56 }
57
58 enum {
59 kBool_Kind,
60 kInt_Kind,
61 } fKind;
62
63 int fValue;
64 };
65
Ethan Nicholas0df1b042017-03-31 13:56:23 -040066#ifdef SKSL_STANDALONE
67 const StandaloneShaderCaps* fCaps = &standaloneCaps;
68#else
Ethan Nicholas941e7e22016-12-12 15:33:30 -050069 const GrShaderCaps* fCaps = nullptr;
Ethan Nicholas0df1b042017-03-31 13:56:23 -040070#endif
Ethan Nicholas38657112017-02-09 17:01:22 -050071 // if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate
72 // must be flipped.
Ethan Nicholas941e7e22016-12-12 15:33:30 -050073 bool fFlipY = false;
Brian Salomondc092132018-04-04 10:14:16 -040074 // If true the destination fragment color is read sk_FragColor. It must be declared inout.
75 bool fFragColorIsInOut = false;
Ethan Nicholas762466e2017-06-29 10:03:38 -040076 // if true, Setting objects (e.g. sk_Caps.fbFetchSupport) should be replaced with their
77 // constant equivalents during compilation
78 bool fReplaceSettings = true;
Ethan Nicholasf7b88202017-09-18 14:10:39 -040079 // if true, all halfs are forced to be floats
80 bool fForceHighPrecision = false;
Brian Osman8a83ca42018-02-12 14:32:17 -050081 // if true, add -0.5 bias to LOD of all texture lookups
82 bool fSharpenTextures = false;
Ethan Nicholas762466e2017-06-29 10:03:38 -040083 std::unordered_map<String, Value> fArgs;
Ethan Nicholas941e7e22016-12-12 15:33:30 -050084 };
85
86 struct Inputs {
87 // if true, this program requires the render target height uniform to be defined
88 bool fRTHeight;
89
Ethan Nicholas38657112017-02-09 17:01:22 -050090 // if true, this program must be recompiled if the flipY setting changes. If false, the
91 // program will compile to the same code regardless of the flipY setting.
92 bool fFlipY;
93
Ethan Nicholas941e7e22016-12-12 15:33:30 -050094 void reset() {
95 fRTHeight = false;
Ethan Nicholas38657112017-02-09 17:01:22 -050096 fFlipY = false;
Ethan Nicholas941e7e22016-12-12 15:33:30 -050097 }
98
99 bool isEmpty() {
Ethan Nicholas38657112017-02-09 17:01:22 -0500100 return !fRTHeight && !fFlipY;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500101 }
102 };
103
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400104 class iterator {
105 public:
106 ProgramElement& operator*() {
107 if (fIter1 != fEnd1) {
108 return **fIter1;
109 }
110 return **fIter2;
111 }
112
113 iterator& operator++() {
114 if (fIter1 != fEnd1) {
115 ++fIter1;
116 return *this;
117 }
118 ++fIter2;
119 return *this;
120 }
121
122 bool operator==(const iterator& other) const {
123 return fIter1 == other.fIter1 && fIter2 == other.fIter2;
124 }
125
126 bool operator!=(const iterator& other) const {
127 return !(*this == other);
128 }
129
130 private:
131 using inner = std::vector<std::unique_ptr<ProgramElement>>::iterator;
132
133 iterator(inner begin1, inner end1, inner begin2, inner end2)
134 : fIter1(begin1)
135 , fEnd1(end1)
136 , fIter2(begin2)
137 , fEnd2(end2) {}
138
139 inner fIter1;
140 inner fEnd1;
141 inner fIter2;
142 inner fEnd2;
143
144 friend struct Program;
145 };
146
147 class const_iterator {
148 public:
149 const ProgramElement& operator*() {
150 if (fIter1 != fEnd1) {
151 return **fIter1;
152 }
153 return **fIter2;
154 }
155
156 const_iterator& operator++() {
157 if (fIter1 != fEnd1) {
158 ++fIter1;
159 return *this;
160 }
161 ++fIter2;
162 return *this;
163 }
164
165 bool operator==(const const_iterator& other) const {
166 return fIter1 == other.fIter1 && fIter2 == other.fIter2;
167 }
168
169 bool operator!=(const const_iterator& other) const {
170 return !(*this == other);
171 }
172
173 private:
174 using inner = std::vector<std::unique_ptr<ProgramElement>>::const_iterator;
175
176 const_iterator(inner begin1, inner end1, inner begin2, inner end2)
177 : fIter1(begin1)
178 , fEnd1(end1)
179 , fIter2(begin2)
180 , fEnd2(end2) {}
181
182 inner fIter1;
183 inner fEnd1;
184 inner fIter2;
185 inner fEnd2;
186
187 friend struct Program;
188 };
189
ethannicholasb3058bd2016-07-01 08:22:01 -0700190 enum Kind {
191 kFragment_Kind,
Ethan Nicholas52cad152017-02-16 16:37:32 -0500192 kVertex_Kind,
Ethan Nicholas762466e2017-06-29 10:03:38 -0400193 kGeometry_Kind,
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400194 kFragmentProcessor_Kind,
Kevin Lubickf2030782018-06-19 12:04:18 +0000195 kCPU_Kind
ethannicholasb3058bd2016-07-01 08:22:01 -0700196 };
197
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500198 Program(Kind kind,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700199 std::unique_ptr<String> source,
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500200 Settings settings,
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400201 std::shared_ptr<Context> context,
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400202 std::vector<std::unique_ptr<ProgramElement>>* inheritedElements,
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500203 std::vector<std::unique_ptr<ProgramElement>> elements,
204 std::shared_ptr<SymbolTable> symbols,
205 Inputs inputs)
206 : fKind(kind)
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700207 , fSource(std::move(source))
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500208 , fSettings(settings)
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500209 , fContext(context)
Ethan Nicholas6415e0d2017-01-19 16:31:32 +0000210 , fSymbols(symbols)
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400211 , fInputs(inputs)
212 , fInheritedElements(inheritedElements)
213 , fElements(std::move(elements)) {}
214
215 iterator begin() {
216 if (fInheritedElements) {
217 return iterator(fInheritedElements->begin(), fInheritedElements->end(),
218 fElements.begin(), fElements.end());
219 }
220 return iterator(fElements.begin(), fElements.end(), fElements.end(), fElements.end());
221 }
222
223 iterator end() {
224 if (fInheritedElements) {
225 return iterator(fInheritedElements->end(), fInheritedElements->end(),
226 fElements.end(), fElements.end());
227 }
228 return iterator(fElements.end(), fElements.end(), fElements.end(), fElements.end());
229 }
230
231 const_iterator begin() const {
232 if (fInheritedElements) {
233 return const_iterator(fInheritedElements->begin(), fInheritedElements->end(),
234 fElements.begin(), fElements.end());
235 }
236 return const_iterator(fElements.begin(), fElements.end(), fElements.end(), fElements.end());
237 }
238
239 const_iterator end() const {
240 if (fInheritedElements) {
241 return const_iterator(fInheritedElements->end(), fInheritedElements->end(),
242 fElements.end(), fElements.end());
243 }
244 return const_iterator(fElements.end(), fElements.end(), fElements.end(), fElements.end());
245 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700246
247 Kind fKind;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700248 std::unique_ptr<String> fSource;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500249 Settings fSettings;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400250 std::shared_ptr<Context> fContext;
Ethan Nicholas86a43402017-01-19 13:32:00 -0500251 // it's important to keep fElements defined after (and thus destroyed before) fSymbols,
252 // because destroying elements can modify reference counts in symbols
Ethan Nicholas6415e0d2017-01-19 16:31:32 +0000253 std::shared_ptr<SymbolTable> fSymbols;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500254 Inputs fInputs;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400255
256private:
257 std::vector<std::unique_ptr<ProgramElement>>* fInheritedElements;
258 std::vector<std::unique_ptr<ProgramElement>> fElements;
ethannicholasb3058bd2016-07-01 08:22:01 -0700259};
260
261} // namespace
262
263#endif