blob: 907009def5d7a464e35e37346f6a3858755a1470 [file] [log] [blame]
Ethan Nicholas00543112018-07-31 09:44:36 -04001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLPipelineStageCodeGenerator.h"
Ethan Nicholas00543112018-07-31 09:44:36 -04009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/sksl/SkSLCompiler.h"
11#include "src/sksl/SkSLHCodeGenerator.h"
Ethan Nicholas00543112018-07-31 09:44:36 -040012
Brian Osman2e29ab52019-09-20 12:19:11 -040013#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
14
Ethan Nicholas00543112018-07-31 09:44:36 -040015namespace SkSL {
16
17PipelineStageCodeGenerator::PipelineStageCodeGenerator(
Brian Osman2e29ab52019-09-20 12:19:11 -040018 const Context* context,
19 const Program* program,
20 ErrorReporter* errors,
21 OutputStream* out,
Brian Osman300fe1d2020-01-23 15:42:43 -050022 PipelineStageArgs* outArgs)
Brian Osman7abc7aa2020-01-23 14:03:25 -050023 : INHERITED(context, program, errors, out)
Brian Osman300fe1d2020-01-23 15:42:43 -050024 , fArgs(outArgs) {}
Ethan Nicholas00543112018-07-31 09:44:36 -040025
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,
Ethan Nicholas0d997662019-04-08 09:46:01 -040038 Precedence parentPrecedence) {
Ethan Nicholas00543112018-07-31 09:44:36 -040039 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
Ethan Nicholasce008112018-08-30 09:19:50 -040056void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
Ethan Nicholas13863662019-07-29 13:05:15 -040057 if (c.fFunction.fBuiltin && c.fFunction.fName == "sample" &&
58 c.fArguments[0]->fType.kind() != Type::Kind::kSampler_Kind) {
Brian Osman87e3bef2020-01-27 16:21:34 -050059 SkASSERT(c.fArguments.size() == 2);
Ethan Nicholas13863662019-07-29 13:05:15 -040060 SkASSERT("fragmentProcessor" == c.fArguments[0]->fType.name() ||
61 "fragmentProcessor?" == c.fArguments[0]->fType.name());
Brian Osman87e3bef2020-01-27 16:21:34 -050062 SkASSERT("float2" == c.fArguments[1]->fType.name());
Ethan Nicholasce008112018-08-30 09:19:50 -040063 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);
Ethan Nicholasce008112018-08-30 09:19:50 -040083 this->write("%s");
Brian Osman87e3bef2020-01-27 16:21:34 -050084 size_t childCallIndex = fArgs->fFormatArgs.size();
Brian Osman300fe1d2020-01-23 15:42:43 -050085 fArgs->fFormatArgs.push_back(
86 Compiler::FormatArg(Compiler::FormatArg::Kind::kChildProcessor, index));
Brian Osman87e3bef2020-01-27 16:21:34 -050087 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();
Ethan Nicholasce008112018-08-30 09:19:50 -040093 return;
94 }
Brian Osman2e29ab52019-09-20 12:19:11 -040095 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 }
Brian Osman300fe1d2020-01-23 15:42:43 -0500108 fArgs->fFormatArgs.push_back(
109 Compiler::FormatArg(Compiler::FormatArg::Kind::kFunctionName, index));
Brian Osman2e29ab52019-09-20 12:19:11 -0400110 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 }
Ethan Nicholasce008112018-08-30 09:19:50 -0400119}
120
Ethan Nicholas00543112018-07-31 09:44:36 -0400121void 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");
Brian Osman300fe1d2020-01-23 15:42:43 -0500129 fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kInput));
Ethan Nicholas00543112018-07-31 09:44:36 -0400130 break;
131 case SK_OUTCOLOR_BUILTIN:
132 this->write("%s");
Brian Osman300fe1d2020-01-23 15:42:43 -0500133 fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
Ethan Nicholas00543112018-07-31 09:44:36 -0400134 break;
135 case SK_MAIN_X_BUILTIN:
Brian Osman3b1e4c22019-08-12 15:12:14 -0400136 this->write("%s");
Brian Osman300fe1d2020-01-23 15:42:43 -0500137 fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kCoordX));
Ethan Nicholas00543112018-07-31 09:44:36 -0400138 break;
139 case SK_MAIN_Y_BUILTIN:
Brian Osman3b1e4c22019-08-12 15:12:14 -0400140 this->write("%s");
Brian Osman300fe1d2020-01-23 15:42:43 -0500141 fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kCoordY));
Ethan Nicholas00543112018-07-31 09:44:36 -0400142 break;
143 default:
Ethan Nicholasce008112018-08-30 09:19:50 -0400144 if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) {
145 this->write("%s");
146 int index = 0;
147 bool found = false;
148 for (const auto& e : fProgram) {
149 if (found) {
150 break;
151 }
152 if (e.fKind == ProgramElement::Kind::kVar_Kind) {
153 const VarDeclarations& decls = (const VarDeclarations&) e;
154 for (const auto& decl : decls.fVars) {
155 const Variable& var = *((VarDeclaration&) *decl).fVar;
156 if (&var == &ref.fVariable) {
157 found = true;
158 break;
159 }
Ethan Nicholas0d997662019-04-08 09:46:01 -0400160 if (var.fModifiers.fFlags & Modifiers::kUniform_Flag) {
Ethan Nicholasce008112018-08-30 09:19:50 -0400161 ++index;
162 }
163 }
164 }
165 }
166 SkASSERT(found);
Brian Osman300fe1d2020-01-23 15:42:43 -0500167 fArgs->fFormatArgs.push_back(
168 Compiler::FormatArg(Compiler::FormatArg::Kind::kUniform, index));
Ethan Nicholas0d997662019-04-08 09:46:01 -0400169 } else {
Ethan Nicholasce008112018-08-30 09:19:50 -0400170 this->write(ref.fVariable.fName);
171 }
Ethan Nicholas00543112018-07-31 09:44:36 -0400172 }
173}
174
175void PipelineStageCodeGenerator::writeIfStatement(const IfStatement& s) {
176 if (s.fIsStatic) {
177 this->write("@");
178 }
179 INHERITED::writeIfStatement(s);
180}
181
182void PipelineStageCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
183 if (s.fIsStatic) {
184 this->write("@");
185 }
186 INHERITED::writeSwitchStatement(s);
187}
188
Brian Osman2e29ab52019-09-20 12:19:11 -0400189static GrSLType glsltype(const Context& context, const Type& type) {
190 if (type == *context.fFloat_Type) {
191 return GrSLType::kFloat_GrSLType;
192 } else if (type == *context.fHalf_Type) {
193 return GrSLType::kHalf_GrSLType;
194 } else if (type == *context.fFloat2_Type) {
195 return GrSLType::kFloat2_GrSLType;
196 } else if (type == *context.fHalf2_Type) {
197 return GrSLType::kHalf2_GrSLType;
Ethan Nicholasfc671ad2019-11-21 11:14:11 -0500198 } else if (type == *context.fFloat3_Type) {
199 return GrSLType::kFloat3_GrSLType;
200 } else if (type == *context.fHalf3_Type) {
201 return GrSLType::kHalf3_GrSLType;
Brian Osman2e29ab52019-09-20 12:19:11 -0400202 } else if (type == *context.fFloat4_Type) {
203 return GrSLType::kFloat4_GrSLType;
204 } else if (type == *context.fHalf4_Type) {
205 return GrSLType::kHalf4_GrSLType;
206 } else if (type == *context.fFloat4x4_Type) {
207 return GrSLType::kFloat4x4_GrSLType;
208 } else if (type == *context.fHalf4x4_Type) {
209 return GrSLType::kHalf4x4_GrSLType;
210 } else if (type == *context.fVoid_Type) {
211 return GrSLType::kVoid_GrSLType;
212 }
213 SkASSERT(false);
214 return GrSLType::kVoid_GrSLType;
215}
216
217
Ethan Nicholas00543112018-07-31 09:44:36 -0400218void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
Brian Osman2e29ab52019-09-20 12:19:11 -0400219 fFunctionHeader = "";
220 OutputStream* oldOut = fOut;
221 StringStream buffer;
222 fOut = &buffer;
Ethan Nicholas00543112018-07-31 09:44:36 -0400223 if (f.fDeclaration.fName == "main") {
Ethan Nicholas00543112018-07-31 09:44:36 -0400224 this->write("%s = %s;\n");
Brian Osman300fe1d2020-01-23 15:42:43 -0500225 fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
226 fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kInput));
Ethan Nicholas00543112018-07-31 09:44:36 -0400227 for (const auto& s : ((Block&) *f.fBody).fStatements) {
228 this->writeStatement(*s);
229 this->writeLine();
230 }
Ethan Nicholas00543112018-07-31 09:44:36 -0400231 fOut = oldOut;
232 this->write(fFunctionHeader);
Brian Osman7abc7aa2020-01-23 14:03:25 -0500233 this->write(buffer.str());
Ethan Nicholas00543112018-07-31 09:44:36 -0400234 } else {
Brian Osman2e29ab52019-09-20 12:19:11 -0400235 const FunctionDeclaration& decl = f.fDeclaration;
236 Compiler::GLSLFunction result;
237 result.fReturnType = glsltype(fContext, decl.fReturnType);
238 result.fName = decl.fName;
239 for (const Variable* v : decl.fParameters) {
240 result.fParameters.emplace_back(v->fName, glsltype(fContext, v->fType));
241 }
242 for (const auto& s : ((Block&) *f.fBody).fStatements) {
243 this->writeStatement(*s);
244 this->writeLine();
245 }
246 fOut = oldOut;
247 result.fBody = buffer.str();
Brian Osman300fe1d2020-01-23 15:42:43 -0500248 result.fFormatArgs = std::move(fArgs->fFormatArgs);
249 fArgs->fFunctions.push_back(result);
Ethan Nicholas00543112018-07-31 09:44:36 -0400250 }
251}
252
Ethan Nicholas00543112018-07-31 09:44:36 -0400253void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& p) {
254 if (p.fKind == ProgramElement::kSection_Kind) {
255 return;
256 }
257 if (p.fKind == ProgramElement::kVar_Kind) {
258 const VarDeclarations& decls = (const VarDeclarations&) p;
259 if (!decls.fVars.size()) {
260 return;
261 }
262 const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar;
263 if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
264 -1 != var.fModifiers.fLayout.fBuiltin) {
265 return;
266 }
267 }
268 INHERITED::writeProgramElement(p);
269}
270
271} // namespace
Brian Osman2e29ab52019-09-20 12:19:11 -0400272#endif