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 namespace SkSL {
14
PipelineStageCodeGenerator(const Context * context,const Program * program,ErrorReporter * errors,OutputStream * out,std::vector<Compiler::FormatArg> * outFormatArgs)15 PipelineStageCodeGenerator::PipelineStageCodeGenerator(
16 const Context* context,
17 const Program* program,
18 ErrorReporter* errors,
19 OutputStream* out,
20 std::vector<Compiler::FormatArg>* outFormatArgs)
21 : INHERITED(context, program, errors, out)
22 , fName("Temp")
23 , fFullName(String::printf("Gr%s", fName.c_str()))
24 , fSectionAndParameterHelper(*program, *errors)
25 , fFormatArgs(outFormatArgs) {}
26
writef(const char * s,va_list va)27 void PipelineStageCodeGenerator::writef(const char* s, va_list va) {
28 static constexpr int BUFFER_SIZE = 1024;
29 va_list copy;
30 va_copy(copy, va);
31 char buffer[BUFFER_SIZE];
32 int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
33 if (length < BUFFER_SIZE) {
34 fOut->write(buffer, length);
35 } else {
36 std::unique_ptr<char[]> heap(new char[length + 1]);
37 vsprintf(heap.get(), s, copy);
38 fOut->write(heap.get(), length);
39 }
40 va_end(copy);
41 }
42
writef(const char * s,...)43 void PipelineStageCodeGenerator::writef(const char* s, ...) {
44 va_list va;
45 va_start(va, s);
46 this->writef(s, va);
47 va_end(va);
48 }
49
writeHeader()50 void PipelineStageCodeGenerator::writeHeader() {
51 }
52
usesPrecisionModifiers() const53 bool PipelineStageCodeGenerator::usesPrecisionModifiers() const {
54 return false;
55 }
56
getTypeName(const Type & type)57 String PipelineStageCodeGenerator::getTypeName(const Type& type) {
58 return type.name();
59 }
60
writeBinaryExpression(const BinaryExpression & b,Precedence parentPrecedence)61 void PipelineStageCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
62 Precedence parentPrecedence) {
63 if (b.fOperator == Token::PERCENT) {
64 // need to use "%%" instead of "%" b/c the code will be inside of a printf
65 Precedence precedence = GetBinaryPrecedence(b.fOperator);
66 if (precedence >= parentPrecedence) {
67 this->write("(");
68 }
69 this->writeExpression(*b.fLeft, precedence);
70 this->write(" %% ");
71 this->writeExpression(*b.fRight, precedence);
72 if (precedence >= parentPrecedence) {
73 this->write(")");
74 }
75 } else {
76 INHERITED::writeBinaryExpression(b, parentPrecedence);
77 }
78 }
79
writeFunctionCall(const FunctionCall & c)80 void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
81 if (c.fFunction.fBuiltin && c.fFunction.fName == "sample" &&
82 c.fArguments[0]->fType.kind() != Type::Kind::kSampler_Kind) {
83 SkASSERT(c.fArguments.size() == 1);
84 SkASSERT("fragmentProcessor" == c.fArguments[0]->fType.name() ||
85 "fragmentProcessor?" == c.fArguments[0]->fType.name());
86 SkASSERT(Expression::kVariableReference_Kind == c.fArguments[0]->fKind);
87 int index = 0;
88 bool found = false;
89 for (const auto& p : fProgram) {
90 if (ProgramElement::kVar_Kind == p.fKind) {
91 const VarDeclarations& decls = (const VarDeclarations&) p;
92 for (const auto& raw : decls.fVars) {
93 VarDeclaration& decl = (VarDeclaration&) *raw;
94 if (decl.fVar == &((VariableReference&) *c.fArguments[0]).fVariable) {
95 found = true;
96 } else if (decl.fVar->fType == *fContext.fFragmentProcessor_Type) {
97 ++index;
98 }
99 }
100 }
101 if (found) {
102 break;
103 }
104 }
105 SkASSERT(found);
106 fExtraEmitCodeCode += " this->invokeChild(" + to_string(index) + ", fChildren[" +
107 to_string(index) + "], args);\n";
108 this->write("%s");
109 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kChildProcessor,
110 index));
111 return;
112 }
113 INHERITED::writeFunctionCall(c);
114 }
115
writeIntLiteral(const IntLiteral & i)116 void PipelineStageCodeGenerator::writeIntLiteral(const IntLiteral& i) {
117 this->write(to_string((int32_t) i.fValue));
118 }
119
writeVariableReference(const VariableReference & ref)120 void PipelineStageCodeGenerator::writeVariableReference(const VariableReference& ref) {
121 switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
122 case SK_INCOLOR_BUILTIN:
123 this->write("%s");
124 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kInput));
125 break;
126 case SK_OUTCOLOR_BUILTIN:
127 this->write("%s");
128 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
129 break;
130 case SK_MAIN_X_BUILTIN:
131 this->write("%s");
132 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kCoordX));
133 break;
134 case SK_MAIN_Y_BUILTIN:
135 this->write("%s");
136 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kCoordY));
137 break;
138 default:
139 if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) {
140 this->write("%s");
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 & Modifiers::kUniform_Flag) {
156 ++index;
157 }
158 }
159 }
160 }
161 SkASSERT(found);
162 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kUniform,
163 index));
164 } else {
165 this->write(ref.fVariable.fName);
166 }
167 }
168 }
169
writeIfStatement(const IfStatement & s)170 void PipelineStageCodeGenerator::writeIfStatement(const IfStatement& s) {
171 if (s.fIsStatic) {
172 this->write("@");
173 }
174 INHERITED::writeIfStatement(s);
175 }
176
writeSwitchStatement(const SwitchStatement & s)177 void PipelineStageCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
178 if (s.fIsStatic) {
179 this->write("@");
180 }
181 INHERITED::writeSwitchStatement(s);
182 }
183
writeFunction(const FunctionDefinition & f)184 void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
185 fCurrentFunction = &f.fDeclaration;
186 if (f.fDeclaration.fName == "main") {
187 fFunctionHeader = "";
188 OutputStream* oldOut = fOut;
189 StringStream buffer;
190 fOut = &buffer;
191 this->write("%s = %s;\n");
192 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
193 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kInput));
194 for (const auto& s : ((Block&) *f.fBody).fStatements) {
195 this->writeStatement(*s);
196 this->writeLine();
197 }
198
199 fOut = oldOut;
200 this->write(fFunctionHeader);
201 this->writef("%s", buffer.str().c_str());
202 } else {
203 INHERITED::writeFunction(f);
204 }
205 }
206
writeSection(const char * name,const char * prefix)207 bool PipelineStageCodeGenerator::writeSection(const char* name, const char* prefix) {
208 const Section* s = fSectionAndParameterHelper.getSection(name);
209 if (s) {
210 this->writef("%s%s", prefix, s->fText.c_str());
211 return true;
212 }
213 return false;
214 }
215
writeProgramElement(const ProgramElement & p)216 void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& p) {
217 if (p.fKind == ProgramElement::kSection_Kind) {
218 return;
219 }
220 if (p.fKind == ProgramElement::kVar_Kind) {
221 const VarDeclarations& decls = (const VarDeclarations&) p;
222 if (!decls.fVars.size()) {
223 return;
224 }
225 const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar;
226 if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
227 -1 != var.fModifiers.fLayout.fBuiltin) {
228 return;
229 }
230 }
231 INHERITED::writeProgramElement(p);
232 }
233
234 } // namespace
235