63namespace PipelineStage {
68 const char* sampleCoords,
69 const char* inputColor,
70 const char* destColor,
73 , fSampleCoords(sampleCoords)
74 , fInputColor(inputColor)
75 , fDestColor(destColor)
76 , fCallbacks(callbacks) {}
83 void write(std::string_view
s);
84 void writeLine(std::string_view
s = std::string_view());
86 std::string typeName(
const Type&
type);
97 std::string typedVariable(
const Type&
type, std::string_view
name);
103 void writeExpression(
const Expression& expr, Precedence parentPrecedence);
106 void writeAnyConstructor(
const AnyConstructor& c, Precedence parentPrecedence);
108 void writeSwizzle(
const Swizzle& swizzle);
109 void writeBinaryExpression(
const BinaryExpression&
b, Precedence parentPrecedence);
110 void writeTernaryExpression(
const TernaryExpression& t, Precedence parentPrecedence);
112 void writePrefixExpression(
const PrefixExpression&
p, Precedence parentPrecedence);
117 void writeBlock(
const Block&
b);
127 struct AutoOutputBuffer {
129 fOldBuffer = fGenerator->fBuffer;
130 fGenerator->fBuffer = &fBuffer;
133 ~AutoOutputBuffer() {
134 fGenerator->fBuffer = fOldBuffer;
138 StringStream* fOldBuffer;
139 StringStream fBuffer;
142 const Program& fProgram;
143 const char* fSampleCoords;
144 const char* fInputColor;
145 const char* fDestColor;
146 Callbacks* fCallbacks;
152 StringStream* fBuffer =
nullptr;
153 bool fCastReturnsToHalf =
false;
154 const FunctionDeclaration* fCurrentFunction =
nullptr;
158void PipelineStageCodeGenerator::write(std::string_view
s) {
159 fBuffer->
write(
s.data(),
s.length());
162void PipelineStageCodeGenerator::writeLine(std::string_view
s) {
163 fBuffer->
write(
s.data(),
s.length());
167void PipelineStageCodeGenerator::writeChildCall(
const ChildCall& c) {
168 const ExpressionArray& arguments = c.arguments();
172 for (
const ProgramElement*
p : fProgram.
elements()) {
173 if (
p->is<GlobalVarDeclaration>()) {
174 const GlobalVarDeclaration& global =
p->as<GlobalVarDeclaration>();
175 const VarDeclaration& decl = global.varDeclaration();
176 if (decl.var() == &c.child()) {
178 }
else if (decl.var()->type().isEffectChild()) {
190 std::string sampleOutput;
192 AutoOutputBuffer exprBuffer(
this);
193 this->writeExpression(*arguments[0], Precedence::kSequence);
195 switch (c.child().type().typeKind()) {
199 sampleOutput = fCallbacks->
sampleShader(index, exprBuffer.fBuffer.str());
205 arguments[0]->type().matches(*fProgram.
fContext->fTypes.fFloat4));
212 arguments[0]->type().matches(*fProgram.
fContext->fTypes.fFloat4));
214 arguments[1]->type().matches(*fProgram.
fContext->fTypes.fFloat4));
216 AutoOutputBuffer exprBuffer2(
this);
217 this->writeExpression(*arguments[1], Precedence::kSequence);
219 sampleOutput = fCallbacks->
sampleBlender(index, exprBuffer.fBuffer.str(),
220 exprBuffer2.fBuffer.str());
225 c.child().type().description().c_str());
229 this->write(sampleOutput);
232void PipelineStageCodeGenerator::writeFunctionCall(
const FunctionCall& c) {
233 const FunctionDeclaration&
function = c.function();
235 if (
function.intrinsicKind() == IntrinsicKind::k_toLinearSrgb_IntrinsicKind ||
236 function.intrinsicKind() == IntrinsicKind::k_fromLinearSrgb_IntrinsicKind) {
237 SkASSERT(c.arguments().size() == 1);
238 std::string colorArg;
240 AutoOutputBuffer exprBuffer(
this);
241 this->writeExpression(*c.arguments()[0], Precedence::kSequence);
242 colorArg = exprBuffer.fBuffer.str();
246 case IntrinsicKind::k_toLinearSrgb_IntrinsicKind:
247 this->write(fCallbacks->
toLinearSrgb(std::move(colorArg)));
249 case IntrinsicKind::k_fromLinearSrgb_IntrinsicKind:
262 this->write(this->functionName(
function));
267 for (
const auto& arg : c.arguments()) {
268 this->write(separator());
269 this->writeExpression(*arg, Precedence::kSequence);
274void PipelineStageCodeGenerator::writeVariableReference(
const VariableReference& ref) {
275 const Variable* var = ref.variable();
278 this->write(fSampleCoords);
282 this->write(fInputColor);
286 this->write(fDestColor);
290 std::string*
name = fVariableNames.find(var);
291 this->write(
name ? *
name : var->name());
294void PipelineStageCodeGenerator::writeIfStatement(
const IfStatement& stmt) {
296 this->writeExpression(*stmt.test(), Precedence::kExpression);
298 this->writeStatement(*stmt.ifTrue());
299 if (stmt.ifFalse()) {
300 this->write(
" else ");
301 this->writeStatement(*stmt.ifFalse());
305void PipelineStageCodeGenerator::writeReturnStatement(
const ReturnStatement& r) {
306 this->write(
"return");
307 if (r.expression()) {
309 if (fCastReturnsToHalf) {
310 this->write(
"half4(");
312 this->writeExpression(*r.expression(), Precedence::kExpression);
313 if (fCastReturnsToHalf) {
320void PipelineStageCodeGenerator::writeSwitchStatement(
const SwitchStatement&
s) {
321 this->write(
"switch (");
322 this->writeExpression(*
s.value(), Precedence::kExpression);
323 this->writeLine(
") {");
324 for (
const std::unique_ptr<Statement>& stmt :
s.cases()) {
325 const SwitchCase& c = stmt->as<SwitchCase>();
327 this->writeLine(
"default:");
329 this->write(
"case ");
331 this->writeLine(
":");
333 if (!c.statement()->isEmpty()) {
334 this->writeStatement(*c.statement());
342std::string PipelineStageCodeGenerator::functionName(
const FunctionDeclaration& decl) {
347 std::string*
name = fFunctionNames.find(&decl);
352 std::string mangledName = fCallbacks->
getMangledName(std::string(decl.name()).c_str());
353 fFunctionNames.set(&decl, mangledName);
357void PipelineStageCodeGenerator::writeFunction(
const FunctionDefinition&
f) {
358 if (
f.declaration().isBuiltin()) {
364 fCurrentFunction = &
f.declaration();
366 AutoOutputBuffer body(
this);
373 const FunctionDeclaration& decl =
f.declaration();
377 fCastReturnsToHalf =
true;
380 for (
const std::unique_ptr<Statement>& stmt :
f.body()->as<
Block>().children()) {
381 this->writeStatement(*stmt);
386 fCastReturnsToHalf =
false;
389 fCallbacks->
defineFunction(this->functionDeclaration(decl).c_str(),
390 body.fBuffer.str().c_str(),
393 fCurrentFunction =
nullptr;
396std::string PipelineStageCodeGenerator::functionDeclaration(
const FunctionDeclaration& decl) {
399 std::string declString =
401 decl.modifierFlags().isInline() ?
"inline " :
"",
402 decl.modifierFlags().isNoInline() ?
"noinline " :
"",
403 this->typeName(decl.returnType()).c_str(),
404 this->functionName(decl).c_str());
406 for (
const Variable*
p : decl.parameters()) {
407 declString.append(separator());
408 declString.append(this->modifierString(
p->modifierFlags()));
409 declString.append(this->typedVariable(
p->type(),
p->name()).c_str());
412 return declString +
")";
415void PipelineStageCodeGenerator::writeFunctionDeclaration(
const FunctionDeclaration& decl) {
416 if (!decl.isMain() && !decl.isBuiltin()) {
417 std::string prototype = this->functionDeclaration(decl) +
';';
422void PipelineStageCodeGenerator::writeGlobalVarDeclaration(
const GlobalVarDeclaration& g) {
423 const VarDeclaration& decl = g.varDeclaration();
424 const Variable& var = *decl.var();
426 if (var.isBuiltin() || var.type().isOpaque()) {
428 }
else if (var.modifierFlags().isUniform()) {
430 fVariableNames.set(&var, std::move(uniformName));
432 std::string mangledName = fCallbacks->
getMangledName(std::string(var.name()).c_str());
433 std::string declaration = this->modifierString(var.modifierFlags()) +
434 this->typedVariable(var.type(), mangledName);
436 AutoOutputBuffer outputToBuffer(
this);
437 this->writeExpression(*decl.value(), Precedence::kExpression);
438 declaration +=
" = ";
439 declaration += outputToBuffer.fBuffer.str();
441 declaration +=
";\n";
443 fVariableNames.set(&var, std::move(mangledName));
447void PipelineStageCodeGenerator::writeStructDefinition(
const StructDefinition&
s) {
450 std::string definition =
"struct " + mangledName +
" {\n";
451 for (
const auto&
f :
type.fields()) {
452 definition += this->typedVariable(*
f.fType,
f.fName) +
";\n";
454 definition +=
"};\n";
455 fStructNames.set(&
type, std::move(mangledName));
459void PipelineStageCodeGenerator::writeProgramElementFirstPass(
const ProgramElement&
e) {
461 case ProgramElement::Kind::kGlobalVar:
462 this->writeGlobalVarDeclaration(
e.as<GlobalVarDeclaration>());
465 this->writeFunctionDeclaration(
e.as<FunctionDefinition>().declaration());
467 case ProgramElement::Kind::kFunctionPrototype:
471 case ProgramElement::Kind::kStructDefinition:
472 this->writeStructDefinition(
e.as<StructDefinition>());
476 case ProgramElement::Kind::kInterfaceBlock:
477 case ProgramElement::Kind::kModifiers:
479 SkDEBUGFAILF(
"unsupported program element %s\n",
e.description().c_str());
484void PipelineStageCodeGenerator::writeProgramElementSecondPass(
const ProgramElement&
e) {
485 if (
e.is<FunctionDefinition>()) {
486 this->writeFunction(
e.as<FunctionDefinition>());
490std::string PipelineStageCodeGenerator::typeName(
const Type& raw) {
491 const Type&
type = raw.resolve().scalarTypeForLiteral();
492 if (
type.isArray()) {
494 std::string arrayName = this->typeName(
type.componentType());
495 arrayName.push_back(
'[');
497 arrayName.push_back(
']');
501 std::string*
name = fStructNames.find(&
type);
505void PipelineStageCodeGenerator::writeType(
const Type&
type) {
506 this->write(this->typeName(
type));
509void PipelineStageCodeGenerator::writeExpression(
const Expression& expr,
510 Precedence parentPrecedence) {
511 switch (expr.kind()) {
512 case Expression::Kind::kBinary:
513 this->writeBinaryExpression(expr.as<BinaryExpression>(), parentPrecedence);
516 case Expression::Kind::kSetting:
517 this->write(expr.description());
519 case Expression::Kind::kChildCall:
520 this->writeChildCall(expr.as<ChildCall>());
522 case Expression::Kind::kConstructorArray:
523 case Expression::Kind::kConstructorArrayCast:
524 case Expression::Kind::kConstructorCompound:
525 case Expression::Kind::kConstructorCompoundCast:
526 case Expression::Kind::kConstructorDiagonalMatrix:
527 case Expression::Kind::kConstructorMatrixResize:
528 case Expression::Kind::kConstructorScalarCast:
529 case Expression::Kind::kConstructorSplat:
530 case Expression::Kind::kConstructorStruct:
531 this->writeAnyConstructor(expr.asAnyConstructor(), parentPrecedence);
534 this->write(
"false");
536 case Expression::Kind::kFieldAccess:
537 this->writeFieldAccess(expr.as<FieldAccess>());
539 case Expression::Kind::kFunctionCall:
540 this->writeFunctionCall(expr.as<FunctionCall>());
542 case Expression::Kind::kPrefix:
543 this->writePrefixExpression(expr.as<PrefixExpression>(), parentPrecedence);
545 case Expression::Kind::kPostfix:
546 this->writePostfixExpression(expr.as<PostfixExpression>(), parentPrecedence);
548 case Expression::Kind::kSwizzle:
549 this->writeSwizzle(expr.as<Swizzle>());
551 case Expression::Kind::kVariableReference:
552 this->writeVariableReference(expr.as<VariableReference>());
554 case Expression::Kind::kTernary:
555 this->writeTernaryExpression(expr.as<TernaryExpression>(), parentPrecedence);
558 this->writeIndexExpression(expr.as<IndexExpression>());
561 SkDEBUGFAILF(
"unsupported expression: %s", expr.description().c_str());
566void PipelineStageCodeGenerator::writeAnyConstructor(
const AnyConstructor& c,
567 Precedence parentPrecedence) {
568 this->writeType(c.type());
571 for (
const auto& arg : c.argumentSpan()) {
572 this->write(separator());
573 this->writeExpression(*arg, Precedence::kSequence);
578void PipelineStageCodeGenerator::writeIndexExpression(
const IndexExpression& expr) {
579 this->writeExpression(*expr.base(), Precedence::kPostfix);
581 this->writeExpression(*expr.index(), Precedence::kExpression);
585void PipelineStageCodeGenerator::writeFieldAccess(
const FieldAccess&
f) {
587 this->writeExpression(*
f.base(), Precedence::kPostfix);
590 const Type& baseType =
f.base()->type();
591 this->write(baseType.fields()[
f.fieldIndex()].fName);
594void PipelineStageCodeGenerator::writeSwizzle(
const Swizzle& swizzle) {
595 this->writeExpression(*swizzle.base(), Precedence::kPostfix);
600void PipelineStageCodeGenerator::writeBinaryExpression(
const BinaryExpression&
b,
601 Precedence parentPrecedence) {
602 const Expression&
left = *
b.left();
603 const Expression&
right = *
b.right();
604 Operator op =
b.getOperator();
606 Precedence precedence = op.getBinaryPrecedence();
607 if (precedence >= parentPrecedence) {
610 this->writeExpression(left, precedence);
611 this->write(op.operatorName());
612 this->writeExpression(right, precedence);
613 if (precedence >= parentPrecedence) {
618void PipelineStageCodeGenerator::writeTernaryExpression(
const TernaryExpression& t,
619 Precedence parentPrecedence) {
620 if (Precedence::kTernary >= parentPrecedence) {
623 this->writeExpression(*t.test(), Precedence::kTernary);
625 this->writeExpression(*t.ifTrue(), Precedence::kTernary);
627 this->writeExpression(*t.ifFalse(), Precedence::kTernary);
628 if (Precedence::kTernary >= parentPrecedence) {
633void PipelineStageCodeGenerator::writePrefixExpression(
const PrefixExpression&
p,
634 Precedence parentPrecedence) {
635 if (Precedence::kPrefix >= parentPrecedence) {
638 this->write(
p.getOperator().tightOperatorName());
639 this->writeExpression(*
p.operand(), Precedence::kPrefix);
640 if (Precedence::kPrefix >= parentPrecedence) {
645void PipelineStageCodeGenerator::writePostfixExpression(
const PostfixExpression&
p,
646 Precedence parentPrecedence) {
647 if (Precedence::kPostfix >= parentPrecedence) {
650 this->writeExpression(*
p.operand(), Precedence::kPostfix);
651 this->write(
p.getOperator().tightOperatorName());
652 if (Precedence::kPostfix >= parentPrecedence) {
657std::string PipelineStageCodeGenerator::modifierString(ModifierFlags
flags) {
659 if (
flags.isConst()) {
673std::string PipelineStageCodeGenerator::typedVariable(
const Type&
type, std::string_view
name) {
676 std::string decl = this->typeName(baseType) +
" " + std::string(
name);
677 if (
type.isArray()) {
683void PipelineStageCodeGenerator::writeVarDeclaration(
const VarDeclaration& var) {
684 this->write(this->modifierString(var.var()->modifierFlags()));
685 this->write(this->typedVariable(var.var()->type(), var.var()->name()));
688 this->writeExpression(*var.value(), Precedence::kExpression);
693void PipelineStageCodeGenerator::writeStatement(
const Statement&
s) {
695 case Statement::Kind::kBlock:
696 this->writeBlock(
s.as<
Block>());
698 case Statement::Kind::kBreak:
699 this->write(
"break;");
702 this->write(
"continue;");
704 case Statement::Kind::kExpression:
705 this->writeExpression(*
s.as<ExpressionStatement>().expression(),
706 Precedence::kStatement);
709 case Statement::Kind::kDo:
710 this->writeDoStatement(
s.as<DoStatement>());
712 case Statement::Kind::kFor:
713 this->writeForStatement(
s.as<ForStatement>());
715 case Statement::Kind::kIf:
716 this->writeIfStatement(
s.as<IfStatement>());
718 case Statement::Kind::kReturn:
719 this->writeReturnStatement(
s.as<ReturnStatement>());
721 case Statement::Kind::kSwitch:
722 this->writeSwitchStatement(
s.as<SwitchStatement>());
724 case Statement::Kind::kVarDeclaration:
725 this->writeVarDeclaration(
s.as<VarDeclaration>());
734 SkDEBUGFAILF(
"unsupported statement: %s",
s.description().c_str());
739void PipelineStageCodeGenerator::writeBlock(
const Block&
b) {
742 bool isScope =
b.isScope() ||
b.isEmpty();
744 this->writeLine(
"{");
746 for (
const std::unique_ptr<Statement>& stmt :
b.children()) {
747 if (!stmt->isEmpty()) {
748 this->writeStatement(*stmt);
757void PipelineStageCodeGenerator::writeDoStatement(
const DoStatement&
d) {
759 this->writeStatement(*
d.statement());
760 this->write(
" while (");
761 this->writeExpression(*
d.test(), Precedence::kExpression);
765void PipelineStageCodeGenerator::writeForStatement(
const ForStatement&
f) {
767 if (!
f.initializer() &&
f.test() && !
f.next()) {
768 this->write(
"while (");
769 this->writeExpression(*
f.test(), Precedence::kExpression);
771 this->writeStatement(*
f.statement());
775 this->write(
"for (");
776 if (
f.initializer() && !
f.initializer()->isEmpty()) {
777 this->writeStatement(*
f.initializer());
782 this->writeExpression(*
f.test(), Precedence::kExpression);
786 this->writeExpression(*
f.next(), Precedence::kExpression);
789 this->writeStatement(*
f.statement());
795 this->writeProgramElementFirstPass(*
e);
802 this->writeProgramElementSecondPass(*
e);
807 const char* sampleCoords,
808 const char* inputColor,
809 const char* destColor,
#define SkDEBUGFAIL(message)
#define SkDEBUGFAILF(fmt,...)
const Variable * getMainInputColorParameter() const
const Variable * getMainCoordsParameter() const
const Variable * getMainDestColorParameter() const
virtual std::string sampleShader(int index, std::string coords)=0
virtual std::string getMainName()
virtual std::string sampleBlender(int index, std::string src, std::string dst)=0
virtual void defineStruct(const char *definition)=0
virtual void declareFunction(const char *declaration)=0
virtual std::string toLinearSrgb(std::string color)=0
virtual void declareGlobal(const char *declaration)=0
virtual std::string sampleColorFilter(int index, std::string color)=0
virtual std::string fromLinearSrgb(std::string color)=0
virtual void defineFunction(const char *declaration, const char *body, bool isMain)=0
virtual std::string declareUniform(const VarDeclaration *)=0
virtual std::string getMangledName(const char *name)
PipelineStageCodeGenerator(const Program &program, const char *sampleCoords, const char *inputColor, const char *destColor, Callbacks *callbacks)
void writeText(const char *s) override
void write(const void *s, size_t size) override
static std::string MaskString(const ComponentArray &inComponents)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
FlutterSemanticsFlag flags
Dart_NativeFunction function
void ConvertProgram(const Program &program, const char *sampleCoords, const char *inputColor, const char *destColor, Callbacks *callbacks)
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
std::string void void auto Separator()
DEF_SWITCHES_START aot vmservice shared library name
static SkString to_string(int n)
ElementsCollection elements() const
std::shared_ptr< Context > fContext
std::unique_ptr< ProgramConfig > fConfig