123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- /*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "src/sksl/SkSLPipelineStageCodeGenerator.h"
- #include "src/sksl/SkSLCompiler.h"
- #include "src/sksl/SkSLHCodeGenerator.h"
- namespace SkSL {
- PipelineStageCodeGenerator::PipelineStageCodeGenerator(
- const Context* context,
- const Program* program,
- ErrorReporter* errors,
- OutputStream* out,
- std::vector<Compiler::FormatArg>* outFormatArgs)
- : INHERITED(context, program, errors, out)
- , fName("Temp")
- , fFullName(String::printf("Gr%s", fName.c_str()))
- , fSectionAndParameterHelper(*program, *errors)
- , fFormatArgs(outFormatArgs) {}
- void PipelineStageCodeGenerator::writef(const char* s, va_list va) {
- static constexpr int BUFFER_SIZE = 1024;
- va_list copy;
- va_copy(copy, va);
- char buffer[BUFFER_SIZE];
- int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
- if (length < BUFFER_SIZE) {
- fOut->write(buffer, length);
- } else {
- std::unique_ptr<char[]> heap(new char[length + 1]);
- vsprintf(heap.get(), s, copy);
- fOut->write(heap.get(), length);
- }
- va_end(copy);
- }
- void PipelineStageCodeGenerator::writef(const char* s, ...) {
- va_list va;
- va_start(va, s);
- this->writef(s, va);
- va_end(va);
- }
- void PipelineStageCodeGenerator::writeHeader() {
- }
- bool PipelineStageCodeGenerator::usesPrecisionModifiers() const {
- return false;
- }
- String PipelineStageCodeGenerator::getTypeName(const Type& type) {
- return type.name();
- }
- void PipelineStageCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
- Precedence parentPrecedence) {
- if (b.fOperator == Token::PERCENT) {
- // need to use "%%" instead of "%" b/c the code will be inside of a printf
- Precedence precedence = GetBinaryPrecedence(b.fOperator);
- if (precedence >= parentPrecedence) {
- this->write("(");
- }
- this->writeExpression(*b.fLeft, precedence);
- this->write(" %% ");
- this->writeExpression(*b.fRight, precedence);
- if (precedence >= parentPrecedence) {
- this->write(")");
- }
- } else {
- INHERITED::writeBinaryExpression(b, parentPrecedence);
- }
- }
- void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
- if (c.fFunction.fBuiltin && c.fFunction.fName == "process") {
- SkASSERT(c.fArguments.size() == 1);
- SkASSERT(Expression::kVariableReference_Kind == c.fArguments[0]->fKind);
- int index = 0;
- bool found = false;
- for (const auto& p : fProgram) {
- if (ProgramElement::kVar_Kind == p.fKind) {
- const VarDeclarations& decls = (const VarDeclarations&) p;
- for (const auto& raw : decls.fVars) {
- VarDeclaration& decl = (VarDeclaration&) *raw;
- if (decl.fVar == &((VariableReference&) *c.fArguments[0]).fVariable) {
- found = true;
- } else if (decl.fVar->fType == *fContext.fFragmentProcessor_Type) {
- ++index;
- }
- }
- }
- if (found) {
- break;
- }
- }
- SkASSERT(found);
- fExtraEmitCodeCode += " this->emitChild(" + to_string(index) + ", fChildren[" +
- to_string(index) + "], args);\n";
- this->write("%s");
- fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kChildProcessor,
- index));
- return;
- }
- INHERITED::writeFunctionCall(c);
- }
- void PipelineStageCodeGenerator::writeIntLiteral(const IntLiteral& i) {
- this->write(to_string((int32_t) i.fValue));
- }
- void PipelineStageCodeGenerator::writeVariableReference(const VariableReference& ref) {
- switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
- case SK_INCOLOR_BUILTIN:
- this->write("%s");
- fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kInput));
- break;
- case SK_OUTCOLOR_BUILTIN:
- this->write("%s");
- fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
- break;
- case SK_MAIN_X_BUILTIN:
- this->write("sk_FragCoord.x");
- break;
- case SK_MAIN_Y_BUILTIN:
- this->write("sk_FragCoord.y");
- break;
- default:
- if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) {
- this->write("%s");
- int index = 0;
- bool found = false;
- for (const auto& e : fProgram) {
- if (found) {
- break;
- }
- if (e.fKind == ProgramElement::Kind::kVar_Kind) {
- const VarDeclarations& decls = (const VarDeclarations&) e;
- for (const auto& decl : decls.fVars) {
- const Variable& var = *((VarDeclaration&) *decl).fVar;
- if (&var == &ref.fVariable) {
- found = true;
- break;
- }
- if (var.fModifiers.fFlags & Modifiers::kUniform_Flag) {
- ++index;
- }
- }
- }
- }
- SkASSERT(found);
- fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kUniform,
- index));
- } else {
- this->write(ref.fVariable.fName);
- }
- }
- }
- void PipelineStageCodeGenerator::writeIfStatement(const IfStatement& s) {
- if (s.fIsStatic) {
- this->write("@");
- }
- INHERITED::writeIfStatement(s);
- }
- void PipelineStageCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
- if (s.fIsStatic) {
- this->write("@");
- }
- INHERITED::writeSwitchStatement(s);
- }
- void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
- fCurrentFunction = &f.fDeclaration;
- if (f.fDeclaration.fName == "main") {
- fFunctionHeader = "";
- OutputStream* oldOut = fOut;
- StringStream buffer;
- fOut = &buffer;
- this->write("%s = %s;\n");
- fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
- fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kInput));
- for (const auto& s : ((Block&) *f.fBody).fStatements) {
- this->writeStatement(*s);
- this->writeLine();
- }
- fOut = oldOut;
- this->write(fFunctionHeader);
- this->writef("%s", buffer.str().c_str());
- } else {
- INHERITED::writeFunction(f);
- }
- }
- bool PipelineStageCodeGenerator::writeSection(const char* name, const char* prefix) {
- const Section* s = fSectionAndParameterHelper.getSection(name);
- if (s) {
- this->writef("%s%s", prefix, s->fText.c_str());
- return true;
- }
- return false;
- }
- void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& p) {
- if (p.fKind == ProgramElement::kSection_Kind) {
- return;
- }
- if (p.fKind == ProgramElement::kVar_Kind) {
- const VarDeclarations& decls = (const VarDeclarations&) p;
- if (!decls.fVars.size()) {
- return;
- }
- const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar;
- if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
- -1 != var.fModifiers.fLayout.fBuiltin) {
- return;
- }
- }
- INHERITED::writeProgramElement(p);
- }
- } // namespace
|