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_GLSLCODEGENERATOR
9#define SKSL_GLSLCODEGENERATOR
10
11#include <unordered_map>
12
13#include "src/sksl/SkSLOperators.h"
14#include "src/sksl/SkSLStringStream.h"
15#include "src/sksl/codegen/SkSLCodeGenerator.h"
16
17namespace SkSL {
18
19class BinaryExpression;
20class Block;
21class ConstructorDiagonalMatrix;
22class ConstructorScalarCast;
23class DoStatement;
24class Extension;
25class FieldAccess;
26class ForStatement;
27class FunctionCall;
28class FunctionDeclaration;
29class FunctionDefinition;
30class FunctionPrototype;
31class IfStatement;
32struct IndexExpression;
33class InterfaceBlock;
34class Literal;
35class PostfixExpression;
36class PrefixExpression;
37class ReturnStatement;
38class Setting;
39class StructDefinition;
40class SwitchStatement;
41struct Swizzle;
42class TernaryExpression;
43class VarDeclaration;
44class VariableReference;
45
46/**
47 * Converts a Program into GLSL code.
48 */
49class GLSLCodeGenerator : public CodeGenerator {
50public:
51    GLSLCodeGenerator(const Context* context, const Program* program, OutputStream* out)
52    : INHERITED(context, program, out)
53    , fLineEnding("\n") {}
54
55    bool generateCode() override;
56
57protected:
58    using Precedence = Operator::Precedence;
59
60    void write(skstd::string_view s);
61
62    void writeLine(skstd::string_view s = skstd::string_view());
63
64    void finishLine();
65
66    virtual void writeHeader();
67
68    virtual bool usesPrecisionModifiers() const;
69
70    virtual String getTypeName(const Type& type);
71
72    void writeStructDefinition(const StructDefinition& s);
73
74    void writeType(const Type& type);
75
76    void writeExtension(skstd::string_view name, bool require = true);
77
78    void writeInterfaceBlock(const InterfaceBlock& intf);
79
80    void writeFunctionStart(const FunctionDeclaration& f);
81
82    void writeFunctionDeclaration(const FunctionDeclaration& f);
83
84    void writeFunctionPrototype(const FunctionPrototype& f);
85
86    virtual void writeFunction(const FunctionDefinition& f);
87
88    void writeLayout(const Layout& layout);
89
90    void writeModifiers(const Modifiers& modifiers, bool globalContext);
91
92    virtual void writeInputVars();
93
94    virtual void writeVarInitializer(const Variable& var, const Expression& value);
95
96    const char* getTypePrecision(const Type& type);
97
98    void writeTypePrecision(const Type& type);
99
100    void writeVarDeclaration(const VarDeclaration& var, bool global);
101
102    void writeFragCoord();
103
104    virtual void writeVariableReference(const VariableReference& ref);
105
106    void writeExpression(const Expression& expr, Precedence parentPrecedence);
107
108    void writeIntrinsicCall(const FunctionCall& c);
109
110    void writeMinAbsHack(Expression& absExpr, Expression& otherExpr);
111
112    void writeDeterminantHack(const Expression& mat);
113
114    void writeInverseHack(const Expression& mat);
115
116    void writeTransposeHack(const Expression& mat);
117
118    void writeInverseSqrtHack(const Expression& x);
119
120    void writeMatrixComparisonWorkaround(const BinaryExpression& x);
121
122    virtual void writeFunctionCall(const FunctionCall& c);
123
124    void writeConstructorDiagonalMatrix(const ConstructorDiagonalMatrix& c,
125                                        Precedence parentPrecedence);
126
127    virtual void writeAnyConstructor(const AnyConstructor& c, Precedence parentPrecedence);
128
129    virtual void writeCastConstructor(const AnyConstructor& c, Precedence parentPrecedence);
130
131    virtual void writeFieldAccess(const FieldAccess& f);
132
133    virtual void writeSwizzle(const Swizzle& swizzle);
134
135    virtual void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence);
136
137    void writeShortCircuitWorkaroundExpression(const BinaryExpression& b,
138                                               Precedence parentPrecedence);
139
140    virtual void writeTernaryExpression(const TernaryExpression& t, Precedence parentPrecedence);
141
142    virtual void writeIndexExpression(const IndexExpression& expr);
143
144    void writePrefixExpression(const PrefixExpression& p, Precedence parentPrecedence);
145
146    void writePostfixExpression(const PostfixExpression& p, Precedence parentPrecedence);
147
148    virtual void writeLiteral(const Literal& l);
149
150    virtual void writeSetting(const Setting& s);
151
152    void writeStatement(const Statement& s);
153
154    void writeBlock(const Block& b);
155
156    virtual void writeIfStatement(const IfStatement& stmt);
157
158    void writeForStatement(const ForStatement& f);
159
160    void writeDoStatement(const DoStatement& d);
161
162    virtual void writeSwitchStatement(const SwitchStatement& s);
163
164    virtual void writeReturnStatement(const ReturnStatement& r);
165
166    virtual void writeProgramElement(const ProgramElement& e);
167
168    const ShaderCapsClass& caps() const { return fContext.fCaps; }
169
170    const char* fLineEnding;
171    StringStream fExtensions;
172    StringStream fGlobals;
173    StringStream fExtraFunctions;
174    String fFunctionHeader;
175    int fVarCount = 0;
176    int fIndentation = 0;
177    bool fAtLineStart = false;
178    std::set<String> fWrittenIntrinsics;
179    // true if we have run into usages of dFdx / dFdy
180    bool fFoundDerivatives = false;
181    bool fFoundExternalSamplerDecl = false;
182    bool fFoundRectSamplerDecl = false;
183    bool fSetupClockwise = false;
184    bool fSetupFragPosition = false;
185    bool fSetupFragCoordWorkaround = false;
186    // if non-empty, replace all texture / texture2D / textureProj / etc. calls with this name
187    String fTextureFunctionOverride;
188
189    // We map function names to function class so we can quickly deal with function calls that need
190    // extra processing
191    enum class FunctionClass {
192        kAbs,
193        kAtan,
194        kDeterminant,
195        kDFdx,
196        kDFdy,
197        kFwidth,
198        kFMA,
199        kFract,
200        kInverse,
201        kInverseSqrt,
202        kMin,
203        kPow,
204        kSaturate,
205        kTexture,
206        kTranspose
207    };
208    static std::unordered_map<skstd::string_view, FunctionClass>* fFunctionClasses;
209
210    using INHERITED = CodeGenerator;
211};
212
213}  // namespace SkSL
214
215#endif
216