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 "SkSLPipelineStageCodeGenerator.h" 9 10 #include "SkSLCompiler.h" 11 #include "SkSLHCodeGenerator.h" 12 13 namespace SkSL { 14 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 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 } 41 42 void PipelineStageCodeGenerator::writef(const char* s, ...) { 43 va_list va; 44 va_start(va, s); 45 this->writef(s, va); 46 va_end(va); 47 } 48 49 void PipelineStageCodeGenerator::writeHeader() { 50 } 51 52 bool PipelineStageCodeGenerator::usesPrecisionModifiers() const { 53 return false; 54 } 55 56 String PipelineStageCodeGenerator::getTypeName(const Type& type) { 57 return type.name(); 58 } 59 60 void PipelineStageCodeGenerator::writeBinaryExpression(const BinaryExpression& b, 61 Precedence parentPrecedence) { 62 if (b.fOperator == Token::PERCENT) { 63 // need to use "%%" instead of "%" b/c the code will be inside of a printf 64 Precedence precedence = GetBinaryPrecedence(b.fOperator); 65 if (precedence >= parentPrecedence) { 66 this->write("("); 67 } 68 this->writeExpression(*b.fLeft, precedence); 69 this->write(" %% "); 70 this->writeExpression(*b.fRight, precedence); 71 if (precedence >= parentPrecedence) { 72 this->write(")"); 73 } 74 } else { 75 INHERITED::writeBinaryExpression(b, parentPrecedence); 76 } 77 } 78 79 void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) { 80 if (c.fFunction.fBuiltin && c.fFunction.fName == "process") { 81 SkASSERT(c.fArguments.size() == 1); 82 SkASSERT(Expression::kVariableReference_Kind == c.fArguments[0]->fKind); 83 int index = 0; 84 bool found = false; 85 for (const auto& p : fProgram) { 86 if (ProgramElement::kVar_Kind == p.fKind) { 87 const VarDeclarations& decls = (const VarDeclarations&) p; 88 for (const auto& raw : decls.fVars) { 89 VarDeclaration& decl = (VarDeclaration&) *raw; 90 if (decl.fVar == &((VariableReference&) *c.fArguments[0]).fVariable) { 91 found = true; 92 } else if (decl.fVar->fType == *fContext.fFragmentProcessor_Type) { 93 ++index; 94 } 95 } 96 } 97 if (found) { 98 break; 99 } 100 } 101 SkASSERT(found); 102 fExtraEmitCodeCode += " this->emitChild(" + to_string(index) + ", fChildren[" + 103 to_string(index) + "], args);\n"; 104 this->write("%s"); 105 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kChildProcessor, 106 index)); 107 return; 108 } 109 INHERITED::writeFunctionCall(c); 110 } 111 112 void PipelineStageCodeGenerator::writeIntLiteral(const IntLiteral& i) { 113 this->write(to_string((int32_t) i.fValue)); 114 } 115 116 void PipelineStageCodeGenerator::writeVariableReference(const VariableReference& ref) { 117 switch (ref.fVariable.fModifiers.fLayout.fBuiltin) { 118 case SK_INCOLOR_BUILTIN: 119 this->write("%s"); 120 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kInput)); 121 break; 122 case SK_OUTCOLOR_BUILTIN: 123 this->write("%s"); 124 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput)); 125 break; 126 case SK_MAIN_X_BUILTIN: 127 this->write("sk_FragCoord.x"); 128 break; 129 case SK_MAIN_Y_BUILTIN: 130 this->write("sk_FragCoord.y"); 131 break; 132 default: 133 if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) { 134 this->write("%s"); 135 int index = 0; 136 bool found = false; 137 for (const auto& e : fProgram) { 138 if (found) { 139 break; 140 } 141 if (e.fKind == ProgramElement::Kind::kVar_Kind) { 142 const VarDeclarations& decls = (const VarDeclarations&) e; 143 for (const auto& decl : decls.fVars) { 144 const Variable& var = *((VarDeclaration&) *decl).fVar; 145 if (&var == &ref.fVariable) { 146 found = true; 147 break; 148 } 149 if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | 150 Modifiers::kUniform_Flag)) { 151 ++index; 152 } 153 } 154 } 155 } 156 SkASSERT(found); 157 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kUniform, 158 index)); 159 } 160 else { 161 this->write(ref.fVariable.fName); 162 } 163 } 164 } 165 166 void PipelineStageCodeGenerator::writeIfStatement(const IfStatement& s) { 167 if (s.fIsStatic) { 168 this->write("@"); 169 } 170 INHERITED::writeIfStatement(s); 171 } 172 173 void PipelineStageCodeGenerator::writeSwitchStatement(const SwitchStatement& s) { 174 if (s.fIsStatic) { 175 this->write("@"); 176 } 177 INHERITED::writeSwitchStatement(s); 178 } 179 180 void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) { 181 if (f.fDeclaration.fName == "main") { 182 fFunctionHeader = ""; 183 OutputStream* oldOut = fOut; 184 StringStream buffer; 185 fOut = &buffer; 186 this->write("%s = %s;\n"); 187 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput)); 188 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kInput)); 189 for (const auto& s : ((Block&) *f.fBody).fStatements) { 190 this->writeStatement(*s); 191 this->writeLine(); 192 } 193 194 fOut = oldOut; 195 this->write(fFunctionHeader); 196 this->writef("%s", buffer.str().c_str()); 197 } else { 198 INHERITED::writeFunction(f); 199 } 200 } 201 202 bool PipelineStageCodeGenerator::writeSection(const char* name, const char* prefix) { 203 const Section* s = fSectionAndParameterHelper.getSection(name); 204 if (s) { 205 this->writef("%s%s", prefix, s->fText.c_str()); 206 return true; 207 } 208 return false; 209 } 210 211 void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& p) { 212 if (p.fKind == ProgramElement::kSection_Kind) { 213 return; 214 } 215 if (p.fKind == ProgramElement::kVar_Kind) { 216 const VarDeclarations& decls = (const VarDeclarations&) p; 217 if (!decls.fVars.size()) { 218 return; 219 } 220 const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar; 221 if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) || 222 -1 != var.fModifiers.fLayout.fBuiltin) { 223 return; 224 } 225 } 226 INHERITED::writeProgramElement(p); 227 } 228 229 } // namespace 230