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