Home | History | Annotate | Download | only in sksl
      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