1/*
2 * Copyright 2018 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#include "src/sksl/SkSLPipelineStageCodeGenerator.h"
9
10#include "src/sksl/SkSLCompiler.h"
11#include "src/sksl/SkSLHCodeGenerator.h"
12
13#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
14
15namespace SkSL {
16
17PipelineStageCodeGenerator::PipelineStageCodeGenerator(
18 const Context* context,
19 const Program* program,
20 ErrorReporter* errors,
21 OutputStream* out,
22 PipelineStageArgs* outArgs)
23 : INHERITED(context, program, errors, out)
24 , fArgs(outArgs) {}
25
26void PipelineStageCodeGenerator::writeHeader() {
27}
28
29bool PipelineStageCodeGenerator::usesPrecisionModifiers() const {
30 return false;
31}
32
33String PipelineStageCodeGenerator::getTypeName(const Type& type) {
34 return type.name();
35}
36
37void PipelineStageCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
38 Precedence parentPrecedence) {
39 if (b.fOperator == Token::PERCENT) {
40 // need to use "%%" instead of "%" b/c the code will be inside of a printf
41 Precedence precedence = GetBinaryPrecedence(b.fOperator);
42 if (precedence >= parentPrecedence) {
43 this->write("(");
44 }
45 this->writeExpression(*b.fLeft, precedence);
46 this->write(" %% ");
47 this->writeExpression(*b.fRight, precedence);
48 if (precedence >= parentPrecedence) {
49 this->write(")");
50 }
51 } else {
52 INHERITED::writeBinaryExpression(b, parentPrecedence);
53 }
54}
55
56void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
57 if (c.fFunction.fBuiltin && c.fFunction.fName == "sample" &&
58 c.fArguments[0]->fType.kind() != Type::Kind::kSampler_Kind) {
59 SkASSERT(c.fArguments.size() == 2);
60 SkASSERT("fragmentProcessor" == c.fArguments[0]->fType.name() ||
61 "fragmentProcessor?" == c.fArguments[0]->fType.name());
62 SkASSERT("float2" == c.fArguments[1]->fType.name());
63 SkASSERT(Expression::kVariableReference_Kind == c.fArguments[0]->fKind);
64 int index = 0;
65 bool found = false;
66 for (const auto& p : fProgram) {
67 if (ProgramElement::kVar_Kind == p.fKind) {
68 const VarDeclarations& decls = (const VarDeclarations&) p;
69 for (const auto& raw : decls.fVars) {
70 VarDeclaration& decl = (VarDeclaration&) *raw;
71 if (decl.fVar == &((VariableReference&) *c.fArguments[0]).fVariable) {
72 found = true;
73 } else if (decl.fVar->fType == *fContext.fFragmentProcessor_Type) {
74 ++index;
75 }
76 }
77 }
78 if (found) {
79 break;
80 }
81 }
82 SkASSERT(found);
83 this->write("%s");
84 size_t childCallIndex = fArgs->fFormatArgs.size();
85 fArgs->fFormatArgs.push_back(
86 Compiler::FormatArg(Compiler::FormatArg::Kind::kChildProcessor, index));
87 OutputStream* oldOut = fOut;
88 StringStream buffer;
89 fOut = &buffer;
90 this->writeExpression(*c.fArguments[1], kSequence_Precedence);
91 fOut = oldOut;
92 fArgs->fFormatArgs[childCallIndex].fCoords = buffer.str();
93 return;
94 }
95 if (c.fFunction.fBuiltin) {
96 INHERITED::writeFunctionCall(c);
97 } else {
98 this->write("%s");
99 int index = 0;
100 for (const auto& e : fProgram) {
101 if (e.fKind == ProgramElement::kFunction_Kind) {
102 if (&((FunctionDefinition&) e).fDeclaration == &c.fFunction) {
103 break;
104 }
105 ++index;
106 }
107 }
108 fArgs->fFormatArgs.push_back(
109 Compiler::FormatArg(Compiler::FormatArg::Kind::kFunctionName, index));
110 this->write("(");
111 const char* separator = "";
112 for (const auto& arg : c.fArguments) {
113 this->write(separator);
114 separator = ", ";
115 this->writeExpression(*arg, kSequence_Precedence);
116 }
117 this->write(")");
118 }
119}
120
121void PipelineStageCodeGenerator::writeIntLiteral(const IntLiteral& i) {
122 this->write(to_string((int32_t) i.fValue));
123}
124
125void PipelineStageCodeGenerator::writeVariableReference(const VariableReference& ref) {
126 switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
127 case SK_INCOLOR_BUILTIN:
128 this->write("%s");
129 fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kInput));
130 break;
131 case SK_OUTCOLOR_BUILTIN:
132 this->write("%s");
133 fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
134 break;
135 case SK_MAIN_COORDS_BUILTIN:
136 this->write("%s");
137 fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kCoords));
138 break;
139 default: {
140 auto varIndexByFlag = [this, &ref](uint32_t flag) {
141 int index = 0;
142 bool found = false;
143 for (const auto& e : fProgram) {
144 if (found) {
145 break;
146 }
147 if (e.fKind == ProgramElement::Kind::kVar_Kind) {
148 const VarDeclarations& decls = (const VarDeclarations&) e;
149 for (const auto& decl : decls.fVars) {
150 const Variable& var = *((VarDeclaration&) *decl).fVar;
151 if (&var == &ref.fVariable) {
152 found = true;
153 break;
154 }
155 if (var.fModifiers.fFlags & flag) {
156 ++index;
157 }
158 }
159 }
160 }
161 SkASSERT(found);
162 return index;
163 };
164
165 if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) {
166 this->write("%s");
167 fArgs->fFormatArgs.push_back(
168 Compiler::FormatArg(Compiler::FormatArg::Kind::kUniform,
169 varIndexByFlag(Modifiers::kUniform_Flag)));
170 } else if (ref.fVariable.fModifiers.fFlags & Modifiers::kVarying_Flag) {
171 this->write("_vtx_attr_");
172 this->write(to_string(varIndexByFlag(Modifiers::kVarying_Flag)));
173 } else {
174 this->write(ref.fVariable.fName);
175 }
176 }
177 }
178}
179
180void PipelineStageCodeGenerator::writeIfStatement(const IfStatement& s) {
181 if (s.fIsStatic) {
182 this->write("@");
183 }
184 INHERITED::writeIfStatement(s);
185}
186
187void PipelineStageCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
188 if (s.fIsStatic) {
189 this->write("@");
190 }
191 INHERITED::writeSwitchStatement(s);
192}
193
194static GrSLType glsltype(const Context& context, const Type& type) {
195 if (type == *context.fFloat_Type) {
196 return GrSLType::kFloat_GrSLType;
197 } else if (type == *context.fHalf_Type) {
198 return GrSLType::kHalf_GrSLType;
199 } else if (type == *context.fFloat2_Type) {
200 return GrSLType::kFloat2_GrSLType;
201 } else if (type == *context.fHalf2_Type) {
202 return GrSLType::kHalf2_GrSLType;
203 } else if (type == *context.fFloat3_Type) {
204 return GrSLType::kFloat3_GrSLType;
205 } else if (type == *context.fHalf3_Type) {
206 return GrSLType::kHalf3_GrSLType;
207 } else if (type == *context.fFloat4_Type) {
208 return GrSLType::kFloat4_GrSLType;
209 } else if (type == *context.fHalf4_Type) {
210 return GrSLType::kHalf4_GrSLType;
211 } else if (type == *context.fFloat4x4_Type) {
212 return GrSLType::kFloat4x4_GrSLType;
213 } else if (type == *context.fHalf4x4_Type) {
214 return GrSLType::kHalf4x4_GrSLType;
215 } else if (type == *context.fVoid_Type) {
216 return GrSLType::kVoid_GrSLType;
217 }
218 SkASSERT(false);
219 return GrSLType::kVoid_GrSLType;
220}
221
222
223void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
224 fFunctionHeader = "";
225 OutputStream* oldOut = fOut;
226 StringStream buffer;
227 fOut = &buffer;
228 if (f.fDeclaration.fName == "main") {
229 this->write("%s = %s;\n");
230 fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
231 fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kInput));
232 for (const auto& s : ((Block&) *f.fBody).fStatements) {
233 this->writeStatement(*s);
234 this->writeLine();
235 }
236 fOut = oldOut;
237 this->write(fFunctionHeader);
238 this->write(buffer.str());
239 } else {
240 const FunctionDeclaration& decl = f.fDeclaration;
241 Compiler::GLSLFunction result;
242 result.fReturnType = glsltype(fContext, decl.fReturnType);
243 result.fName = decl.fName;
244 for (const Variable* v : decl.fParameters) {
245 result.fParameters.emplace_back(v->fName, glsltype(fContext, v->fType));
246 }
247 for (const auto& s : ((Block&) *f.fBody).fStatements) {
248 this->writeStatement(*s);
249 this->writeLine();
250 }
251 fOut = oldOut;
252 result.fBody = buffer.str();
253 result.fFormatArgs = std::move(fArgs->fFormatArgs);
254 fArgs->fFunctions.push_back(result);
255 }
256}
257
258void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& p) {
259 if (p.fKind == ProgramElement::kSection_Kind) {
260 return;
261 }
262 if (p.fKind == ProgramElement::kVar_Kind) {
263 const VarDeclarations& decls = (const VarDeclarations&) p;
264 if (!decls.fVars.size()) {
265 return;
266 }
267 const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar;
268 if (var.fModifiers.fFlags &
269 (Modifiers::kIn_Flag | Modifiers::kUniform_Flag | Modifiers::kVarying_Flag) ||
270 -1 != var.fModifiers.fLayout.fBuiltin) {
271 return;
272 }
273 }
274 INHERITED::writeProgramElement(p);
275}
276
277} // namespace
278#endif
279