• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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