Child fragment processors are now written as separate functions

Bug: skia:
Change-Id: Icbf8f542637a874b3e2d3513d932b39728fa5e77
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/229385
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2019-07-24 16:51:36 -04:00 committed by Skia Commit-Bot
parent b380e71cfe
commit c6dce5ac87
24 changed files with 141 additions and 83 deletions

View File

@ -50,7 +50,7 @@ private:
"Xform", &xformUniName); "Xform", &xformUniName);
SkString dstNormalColorName("dstNormalColor"); SkString dstNormalColorName("dstNormalColor");
this->emitChild(0, &dstNormalColorName, args); this->invokeChild(0, &dstNormalColorName, args);
fragBuilder->codeAppendf("float3 normal = normalize(%s.rgb - float3(0.5));", fragBuilder->codeAppendf("float3 normal = normalize(%s.rgb - float3(0.5));",
dstNormalColorName.c_str()); dstNormalColorName.c_str());

View File

@ -66,7 +66,7 @@ public:
if (this->numChildProcessors()) { if (this->numChildProcessors()) {
SkString childColor("src_color"); SkString childColor("src_color");
this->emitChild(0, &childColor, args); this->invokeChild(0, &childColor, args);
SkString xformedColor; SkString xformedColor;
fragBuilder->appendColorGamutXform(&xformedColor, childColor.c_str(), &fColorSpaceHelper); fragBuilder->appendColorGamutXform(&xformedColor, childColor.c_str(), &fColorSpaceHelper);

View File

@ -233,7 +233,7 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulB
public: public:
void emitCode(EmitArgs& args) override { void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
this->emitChild(0, args); this->invokeChild(0, args);
fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor, fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
args.fInputColor); args.fInputColor);
fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor); fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
@ -310,15 +310,15 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(
void emitCode(EmitArgs& args) override { void emitCode(EmitArgs& args) override {
// First guy's input might be nil. // First guy's input might be nil.
SkString temp("out0"); SkString temp("out0");
this->emitChild(0, args.fInputColor, &temp, args); this->invokeChild(0, args.fInputColor, &temp, args);
SkString input = temp; SkString input = temp;
for (int i = 1; i < this->numChildProcessors() - 1; ++i) { for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
temp.printf("out%d", i); temp.printf("out%d", i);
this->emitChild(i, input.c_str(), &temp, args); this->invokeChild(i, input.c_str(), &temp, args);
input = temp; input = temp;
} }
// Last guy writes to our output variable. // Last guy writes to our output variable.
this->emitChild(this->numChildProcessors() - 1, input.c_str(), args); this->invokeChild(this->numChildProcessors() - 1, input.c_str(), args);
} }
}; };
return new GLFP; return new GLFP;

View File

@ -162,7 +162,7 @@ public:
std::vector<SkString> childNames; std::vector<SkString> childNames;
for (int i = 0; i < this->numChildProcessors(); ++i) { for (int i = 0; i < this->numChildProcessors(); ++i) {
childNames.push_back(SkStringPrintf("_child%d", i)); childNames.push_back(SkStringPrintf("_child%d", i));
this->emitChild(i, &childNames[i], args); this->invokeChild(i, &childNames[i], args);
} }
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
int substringStartIndex = 0; int substringStartIndex = 0;

View File

@ -221,10 +221,10 @@ void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
// declare outputColor and emit the code for each of the two children // declare outputColor and emit the code for each of the two children
SkString srcColor("xfer_src"); SkString srcColor("xfer_src");
this->emitChild(0, inputColor, &srcColor, args); this->invokeChild(0, inputColor, &srcColor, args);
SkString dstColor("xfer_dst"); SkString dstColor("xfer_dst");
this->emitChild(1, inputColor, &dstColor, args); this->invokeChild(1, inputColor, &dstColor, args);
// emit blend code // emit blend code
SkBlendMode mode = cs.getMode(); SkBlendMode mode = cs.getMode();
@ -439,7 +439,7 @@ public:
ComposeOneFragmentProcessor::Child child = ComposeOneFragmentProcessor::Child child =
args.fFp.cast<ComposeOneFragmentProcessor>().child(); args.fFp.cast<ComposeOneFragmentProcessor>().child();
SkString childColor("child"); SkString childColor("child");
this->emitChild(0, &childColor, args); this->invokeChild(0, &childColor, args);
// emit blend code // emit blend code
fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode)); fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));

View File

@ -29,13 +29,13 @@ public:
args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType, "weight"); args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType, "weight");
SkString _child0("_child0"); SkString _child0("_child0");
if (_outer.child1_index >= 0) { if (_outer.child1_index >= 0) {
this->emitChild(_outer.child1_index, &_child0, args); this->invokeChild(_outer.child1_index, &_child0, args);
} else { } else {
fragBuilder->codeAppendf("half4 %s;", _child0.c_str()); fragBuilder->codeAppendf("half4 %s;", _child0.c_str());
} }
SkString _child1("_child1"); SkString _child1("_child1");
if (_outer.child2_index >= 0) { if (_outer.child2_index >= 0) {
this->emitChild(_outer.child2_index, &_child1, args); this->invokeChild(_outer.child2_index, &_child1, args);
} else { } else {
fragBuilder->codeAppendf("half4 %s;", _child1.c_str()); fragBuilder->codeAppendf("half4 %s;", _child1.c_str());
} }

View File

@ -25,18 +25,18 @@ public:
(void)_outer; (void)_outer;
SkString _child0("_child0"); SkString _child0("_child0");
if (_outer.child1_index >= 0) { if (_outer.child1_index >= 0) {
this->emitChild(_outer.child1_index, &_child0, args); this->invokeChild(_outer.child1_index, &_child0, args);
} else { } else {
fragBuilder->codeAppendf("half4 %s;", _child0.c_str()); fragBuilder->codeAppendf("half4 %s;", _child0.c_str());
} }
SkString _child1("_child1"); SkString _child1("_child1");
if (_outer.child2_index >= 0) { if (_outer.child2_index >= 0) {
this->emitChild(_outer.child2_index, &_child1, args); this->invokeChild(_outer.child2_index, &_child1, args);
} else { } else {
fragBuilder->codeAppendf("half4 %s;", _child1.c_str()); fragBuilder->codeAppendf("half4 %s;", _child1.c_str());
} }
SkString _child2("_child2"); SkString _child2("_child2");
this->emitChild(_outer.lerp_index, &_child2, args); this->invokeChild(_outer.lerp_index, &_child2, args);
fragBuilder->codeAppendf("%s = mix(%s ? %s : %s, %s ? %s : %s, %s.x);\n", args.fOutputColor, fragBuilder->codeAppendf("%s = mix(%s ? %s : %s, %s ? %s : %s, %s.x);\n", args.fOutputColor,
_outer.child1_index >= 0 ? "true" : "false", _child0.c_str(), _outer.child1_index >= 0 ? "true" : "false", _child0.c_str(),
args.fInputColor, _outer.child2_index >= 0 ? "true" : "false", args.fInputColor, _outer.child2_index >= 0 ? "true" : "false",

View File

@ -29,12 +29,12 @@ public:
args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "weight"); args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "weight");
SkString _input0 = SkStringPrintf("%s", args.fInputColor); SkString _input0 = SkStringPrintf("%s", args.fInputColor);
SkString _child0("_child0"); SkString _child0("_child0");
this->emitChild(_outer.fp0_index, _input0.c_str(), &_child0, args); this->invokeChild(_outer.fp0_index, _input0.c_str(), &_child0, args);
fragBuilder->codeAppendf("half4 in0 = %s;", _child0.c_str()); fragBuilder->codeAppendf("half4 in0 = %s;", _child0.c_str());
SkString _input1 = SkStringPrintf("%s", args.fInputColor); SkString _input1 = SkStringPrintf("%s", args.fInputColor);
SkString _child1("_child1"); SkString _child1("_child1");
if (_outer.fp1_index >= 0) { if (_outer.fp1_index >= 0) {
this->emitChild(_outer.fp1_index, _input1.c_str(), &_child1, args); this->invokeChild(_outer.fp1_index, _input1.c_str(), &_child1, args);
} else { } else {
fragBuilder->codeAppendf("half4 %s;", _child1.c_str()); fragBuilder->codeAppendf("half4 %s;", _child1.c_str());
} }

View File

@ -44,7 +44,7 @@ public:
_outer.literalColor.fA); _outer.literalColor.fA);
SkString _input0("constColor"); SkString _input0("constColor");
SkString _child0("_child0"); SkString _child0("_child0");
this->emitChild(_outer.fp_index, _input0.c_str(), &_child0, args); this->invokeChild(_outer.fp_index, _input0.c_str(), &_child0, args);
fragBuilder->codeAppendf("\n%s = %s;\n", args.fOutputColor, _child0.c_str()); fragBuilder->codeAppendf("\n%s = %s;\n", args.fOutputColor, _child0.c_str());
} }

View File

@ -16,20 +16,32 @@ void GrGLSLFragmentProcessor::setData(const GrGLSLProgramDataManager& pdman,
this->onSetData(pdman, processor); this->onSetData(pdman, processor);
} }
void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor, EmitArgs& args) { void GrGLSLFragmentProcessor::invokeChild(int childIndex, const char* inputColor, EmitArgs& args) {
this->internalEmitChild(childIndex, inputColor, args.fOutputColor, args); while (childIndex >= (int) fFunctionNames.size()) {
fFunctionNames.emplace_back();
}
this->internalInvokeChild(childIndex, inputColor, args.fOutputColor, args);
} }
void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor, void GrGLSLFragmentProcessor::invokeChild(int childIndex, const char* inputColor,
SkString* outputColor, EmitArgs& args) { SkString* outputColor, EmitArgs& args) {
SkASSERT(outputColor); SkASSERT(outputColor);
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
outputColor->append(fragBuilder->getMangleString()); outputColor->append(fragBuilder->getMangleString());
fragBuilder->codeAppendf("half4 %s;", outputColor->c_str()); fragBuilder->codeAppendf("half4 %s;", outputColor->c_str());
this->internalEmitChild(childIndex, inputColor, outputColor->c_str(), args); while (childIndex >= (int) fFunctionNames.size()) {
fFunctionNames.emplace_back();
}
if (fFunctionNames[childIndex].size() == 0) {
this->internalInvokeChild(childIndex, inputColor, outputColor->c_str(), args);
} else {
fragBuilder->codeAppendf("%s = %s(%s);", outputColor->c_str(),
fFunctionNames[childIndex].c_str(),
inputColor ? inputColor : "half4(1)");
}
} }
void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inputColor, void GrGLSLFragmentProcessor::internalInvokeChild(int childIndex, const char* inputColor,
const char* outputColor, EmitArgs& args) { const char* outputColor, EmitArgs& args) {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
@ -48,24 +60,24 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu
const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex); const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
// emit the code for the child in its own scope
fragBuilder->codeAppend("{\n");
fragBuilder->codeAppendf("// Child Index %d (mangle: %s): %s\n", childIndex,
fragBuilder->getMangleString().c_str(), childProc.name());
TransformedCoordVars coordVars = args.fTransformedCoords.childInputs(childIndex); TransformedCoordVars coordVars = args.fTransformedCoords.childInputs(childIndex);
TextureSamplers textureSamplers = args.fTexSamplers.childInputs(childIndex); TextureSamplers textureSamplers = args.fTexSamplers.childInputs(childIndex);
// EmitArgs properly updates inputColor to half4(1) if it was null
EmitArgs childArgs(fragBuilder, EmitArgs childArgs(fragBuilder,
args.fUniformHandler, args.fUniformHandler,
args.fShaderCaps, args.fShaderCaps,
childProc, childProc,
outputColor, outputColor,
inputName.size() > 0 ? inputName.c_str() : nullptr, "_input",
coordVars, coordVars,
textureSamplers); textureSamplers);
this->childProcessor(childIndex)->emitCode(childArgs); fFunctionNames[childIndex] = fragBuilder->writeProcessorFunction(
fragBuilder->codeAppend("}\n"); this->childProcessor(childIndex),
childArgs);
fragBuilder->codeAppendf("%s = %s(%s);\n", outputColor,
fFunctionNames[childIndex].c_str(),
inputName.size() > 0 ? inputName.c_str()
: "half4(1)");
fragBuilder->onAfterChildProcEmitCode(); fragBuilder->onAfterChildProcEmitCode();
} }

View File

@ -136,31 +136,31 @@ public:
return fChildProcessors[index]; return fChildProcessors[index];
} }
// Emit the child with the default input color (solid white) // Invoke the child with the default input color (solid white)
inline void emitChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) { inline void invokeChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) {
this->emitChild(childIndex, nullptr, outputColor, parentArgs); this->invokeChild(childIndex, nullptr, outputColor, parentArgs);
} }
/** Will emit the code of a child proc in its own scope. Pass in the parent's EmitArgs and /** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will
* emitChild will automatically extract the coords and samplers of that child and pass them * automatically extract the coords and samplers of that child and pass them on to the child's
* on to the child's emitCode(). Also, any uniforms or functions emitted by the child will * emitCode(). Also, any uniforms or functions emitted by the child will have their names
* have their names mangled to prevent redefinitions. The output color name is also mangled * mangled to prevent redefinitions. The output color name is also mangled therefore in an
* therefore in an in/out param. It will be declared in mangled form by emitChild(). It is * in/out param. It will be declared in mangled form by invokeChild(). It is legal to pass
* legal to pass nullptr as inputColor, since all fragment processors are required to work * nullptr as inputColor, since all fragment processors are required to work without an input
* without an input color. * color.
*/ */
void emitChild(int childIndex, const char* inputColor, SkString* outputColor, void invokeChild(int childIndex, const char* inputColor, SkString* outputColor,
EmitArgs& parentArgs); EmitArgs& parentArgs);
// Use the parent's output color to hold child's output, and use the // Use the parent's output color to hold child's output, and use the
// default input color of solid white // default input color of solid white
inline void emitChild(int childIndex, EmitArgs& args) { inline void invokeChild(int childIndex, EmitArgs& args) {
// null pointer cast required to disambiguate the function call // null pointer cast required to disambiguate the function call
this->emitChild(childIndex, (const char*) nullptr, args); this->invokeChild(childIndex, (const char*) nullptr, args);
} }
/** Variation that uses the parent's output color variable to hold the child's output.*/ /** Variation that uses the parent's output color variable to hold the child's output.*/
void emitChild(int childIndex, const char* inputColor, EmitArgs& parentArgs); void invokeChild(int childIndex, const char* inputColor, EmitArgs& parentArgs);
/** /**
* Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
@ -189,7 +189,10 @@ protected:
virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {} virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}
private: private:
void internalEmitChild(int, const char*, const char*, EmitArgs&); void internalInvokeChild(int, const char*, const char*, EmitArgs&);
// one per child; either not present or empty string if not yet emitted
SkTArray<SkString> fFunctionNames;
SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors; SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors;

View File

@ -156,6 +156,26 @@ void GrGLSLFragmentShaderBuilder::applyFnToMultisampleMask(
this->codeAppendf("}"); this->codeAppendf("}");
} }
SkString GrGLSLFPFragmentBuilder::writeProcessorFunction(GrGLSLFragmentProcessor* fp,
GrGLSLFragmentProcessor::EmitArgs& args) {
this->onBeforeChildProcEmitCode();
this->nextStage();
this->codeAppendf("half4 %s;\n", args.fOutputColor);
fp->emitCode(args);
this->codeAppendf("return %s;", args.fOutputColor);
GrShaderVar inColor(args.fInputColor, kHalf4_GrSLType);
SkString result;
this->emitFunction(kHalf4_GrSLType,
"stage",
1,
&inColor,
this->code().c_str(),
&result);
this->deleteStage();
this->onAfterChildProcEmitCode();
return result;
}
const char* GrGLSLFragmentShaderBuilder::dstColor() { const char* GrGLSLFragmentShaderBuilder::dstColor() {
SkDEBUGCODE(fHasReadDstColorThisStage_DebugOnly = true;) SkDEBUGCODE(fHasReadDstColorThisStage_DebugOnly = true;)

View File

@ -10,6 +10,7 @@
#include "include/gpu/GrBlend.h" #include "include/gpu/GrBlend.h"
#include "src/gpu/GrProcessor.h" #include "src/gpu/GrProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLShaderBuilder.h" #include "src/gpu/glsl/GrGLSLShaderBuilder.h"
class GrRenderTarget; class GrRenderTarget;
@ -97,6 +98,9 @@ public:
virtual void onBeforeChildProcEmitCode() = 0; virtual void onBeforeChildProcEmitCode() = 0;
virtual void onAfterChildProcEmitCode() = 0; virtual void onAfterChildProcEmitCode() = 0;
virtual SkString writeProcessorFunction(GrGLSLFragmentProcessor* fp,
GrGLSLFragmentProcessor::EmitArgs& args);
virtual const SkString& getMangleString() const = 0; virtual const SkString& getMangleString() const = 0;
virtual void forceHighPrecision() = 0; virtual void forceHighPrecision() = 0;

View File

@ -198,6 +198,11 @@ protected:
fCodeIndex++; fCodeIndex++;
} }
void deleteStage() {
fShaderStrings.pop_back();
fCodeIndex--;
}
SkString& extensions() { return fShaderStrings[kExtensions]; } SkString& extensions() { return fShaderStrings[kExtensions]; }
SkString& definitions() { return fShaderStrings[kDefinitions]; } SkString& definitions() { return fShaderStrings[kDefinitions]; }
SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; } SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; }

View File

@ -36,7 +36,7 @@ public:
rightBorderColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, rightBorderColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
kHalf4_GrSLType, "rightBorderColor"); kHalf4_GrSLType, "rightBorderColor");
SkString _child1("_child1"); SkString _child1("_child1");
this->emitChild(_outer.gradLayout_index, &_child1, args); this->invokeChild(_outer.gradLayout_index, &_child1, args);
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"half4 t = %s;\nif (!%s && t.y < 0.0) {\n %s = half4(0.0);\n} else if (t.x < " "half4 t = %s;\nif (!%s && t.y < 0.0) {\n %s = half4(0.0);\n} else if (t.x < "
"0.0) {\n %s = %s;\n} else if (t.x > 1.0) {\n %s = %s;\n} else {", "0.0) {\n %s = %s;\n} else if (t.x > 1.0) {\n %s = %s;\n} else {",
@ -48,7 +48,7 @@ public:
args.fUniformHandler->getUniformCStr(rightBorderColorVar)); args.fUniformHandler->getUniformCStr(rightBorderColorVar));
SkString _input0("t"); SkString _input0("t");
SkString _child0("_child0"); SkString _child0("_child0");
this->emitChild(_outer.colorizer_index, _input0.c_str(), &_child0, args); this->invokeChild(_outer.colorizer_index, _input0.c_str(), &_child0, args);
fragBuilder->codeAppendf("\n %s = %s;\n}\n@if (%s) {\n %s.xyz *= %s.w;\n}\n", fragBuilder->codeAppendf("\n %s = %s;\n}\n@if (%s) {\n %s.xyz *= %s.w;\n}\n",
args.fOutputColor, _child0.c_str(), args.fOutputColor, _child0.c_str(),
(_outer.makePremul ? "true" : "false"), args.fOutputColor, (_outer.makePremul ? "true" : "false"), args.fOutputColor,

View File

@ -30,7 +30,7 @@ public:
auto colorsAreOpaque = _outer.colorsAreOpaque; auto colorsAreOpaque = _outer.colorsAreOpaque;
(void)colorsAreOpaque; (void)colorsAreOpaque;
SkString _child1("_child1"); SkString _child1("_child1");
this->emitChild(_outer.gradLayout_index, &_child1, args); this->invokeChild(_outer.gradLayout_index, &_child1, args);
fragBuilder->codeAppendf( fragBuilder->codeAppendf(
"half4 t = %s;\nif (!%s && t.y < 0.0) {\n %s = half4(0.0);\n} else {\n @if " "half4 t = %s;\nif (!%s && t.y < 0.0) {\n %s = half4(0.0);\n} else {\n @if "
"(%s) {\n half t_1 = t.x - 1.0;\n half tiled_t = (t_1 - 2.0 * " "(%s) {\n half t_1 = t.x - 1.0;\n half tiled_t = (t_1 - 2.0 * "
@ -43,7 +43,7 @@ public:
args.fOutputColor, (_outer.mirror ? "true" : "false")); args.fOutputColor, (_outer.mirror ? "true" : "false"));
SkString _input0("t"); SkString _input0("t");
SkString _child0("_child0"); SkString _child0("_child0");
this->emitChild(_outer.colorizer_index, _input0.c_str(), &_child0, args); this->invokeChild(_outer.colorizer_index, _input0.c_str(), &_child0, args);
fragBuilder->codeAppendf("\n %s = %s;\n}\n@if (%s) {\n %s.xyz *= %s.w;\n}\n", fragBuilder->codeAppendf("\n %s = %s;\n}\n@if (%s) {\n %s.xyz *= %s.w;\n}\n",
args.fOutputColor, _child0.c_str(), args.fOutputColor, _child0.c_str(),
(_outer.makePremul ? "true" : "false"), args.fOutputColor, (_outer.makePremul ? "true" : "false"), args.fOutputColor,

View File

@ -166,7 +166,7 @@ private:
fragBuilder->codeAppendf("half4 diffuseColor = %s;", args.fInputColor); fragBuilder->codeAppendf("half4 diffuseColor = %s;", args.fInputColor);
SkString dstNormalName("dstNormal"); SkString dstNormalName("dstNormal");
this->emitChild(0, &dstNormalName, args); this->invokeChild(0, &dstNormalName, args);
fragBuilder->codeAppendf("float3 normal = %s.xyz;", dstNormalName.c_str()); fragBuilder->codeAppendf("float3 normal = %s.xyz;", dstNormalName.c_str());

View File

@ -431,16 +431,16 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
// Set to the empty string when no input color parameter should be emitted, which means this // Set to the empty string when no input color parameter should be emitted, which means this
// must be properly formatted with a prefixed comma when the parameter should be inserted // must be properly formatted with a prefixed comma when the parameter should be inserted
// into the emitChild() parameter list. // into the invokeChild() parameter list.
String inputArg; String inputArg;
if (c.fArguments.size() > 1) { if (c.fArguments.size() > 1) {
SkASSERT(c.fArguments.size() == 2); SkASSERT(c.fArguments.size() == 2);
// Use the emitChild() variant that accepts an input color, so convert the 2nd // Use the invokeChild() variant that accepts an input color, so convert the 2nd
// argument's expression into C++ code that produces sksl stored in an SkString. // argument's expression into C++ code that produces sksl stored in an SkString.
String inputName = "_input" + to_string(index); String inputName = "_input" + to_string(index);
addExtraEmitCodeLine(convertSKSLExpressionToCPP(*c.fArguments[1], inputName)); addExtraEmitCodeLine(convertSKSLExpressionToCPP(*c.fArguments[1], inputName));
// emitChild() needs a char* // invokeChild() needs a char*
inputArg = ", " + inputName + ".c_str()"; inputArg = ", " + inputName + ".c_str()";
} }
@ -450,7 +450,7 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) { if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
addExtraEmitCodeLine("if (_outer." + String(child.fName) + "_index >= 0) {\n "); addExtraEmitCodeLine("if (_outer." + String(child.fName) + "_index >= 0) {\n ");
} }
addExtraEmitCodeLine("this->emitChild(_outer." + String(child.fName) + "_index" + addExtraEmitCodeLine("this->invokeChild(_outer." + String(child.fName) + "_index" +
inputArg + ", &" + childName + ", args);"); inputArg + ", &" + childName + ", args);");
if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) { if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
// Null FPs are not emitted, but their output can still be referenced in dependent // Null FPs are not emitted, but their output can still be referenced in dependent

View File

@ -1035,6 +1035,8 @@ void GLSLCodeGenerator::writeSetting(const Setting& s) {
} }
void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
fSetupFragPositionLocal = false;
fSetupFragCoordWorkaround = false;
if (fProgramKind != Program::kPipelineStage_Kind) { if (fProgramKind != Program::kPipelineStage_Kind) {
this->writeTypePrecision(f.fDeclaration.fReturnType); this->writeTypePrecision(f.fDeclaration.fReturnType);
this->writeType(f.fDeclaration.fReturnType); this->writeType(f.fDeclaration.fReturnType);

View File

@ -244,6 +244,11 @@ void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) {
this->write("_globals"); this->write("_globals");
separator = ", "; separator = ", ";
} }
if (this->requirements(c.fFunction) & kFragCoord_Requirement) {
this->write(separator);
this->write("_fragCoord");
separator = ", ";
}
for (size_t i = 0; i < c.fArguments.size(); ++i) { for (size_t i = 0; i < c.fArguments.size(); ++i) {
const Expression& arg = *c.fArguments[i]; const Expression& arg = *c.fArguments[i];
this->write(separator); this->write(separator);
@ -499,8 +504,8 @@ void MetalCodeGenerator::writeConstructor(const Constructor& c, Precedence paren
void MetalCodeGenerator::writeFragCoord() { void MetalCodeGenerator::writeFragCoord() {
if (fProgram.fInputs.fRTHeight) { if (fProgram.fInputs.fRTHeight) {
this->write("float4(_fragCoord.x, _anonInterface0.u_skRTHeight - _fragCoord.y, 0.0, " this->write("float4(_fragCoord.x, _globals->_anonInterface0->u_skRTHeight - "
"_fragCoord.w)"); "_fragCoord.y, 0.0, _fragCoord.w)");
} else { } else {
this->write("float4(_fragCoord.x, _fragCoord.y, 0.0, _fragCoord.w)"); this->write("float4(_fragCoord.x, _fragCoord.y, 0.0, _fragCoord.w)");
} }
@ -853,25 +858,31 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
this->write(" "); this->write(" ");
this->writeName(f.fDeclaration.fName); this->writeName(f.fDeclaration.fName);
this->write("("); this->write("(");
if (this->requirements(f.fDeclaration) & kInputs_Requirement) { Requirements requirements = this->requirements(f.fDeclaration);
if (requirements & kInputs_Requirement) {
this->write("Inputs _in"); this->write("Inputs _in");
separator = ", "; separator = ", ";
} }
if (this->requirements(f.fDeclaration) & kOutputs_Requirement) { if (requirements & kOutputs_Requirement) {
this->write(separator); this->write(separator);
this->write("thread Outputs* _out"); this->write("thread Outputs* _out");
separator = ", "; separator = ", ";
} }
if (this->requirements(f.fDeclaration) & kUniforms_Requirement) { if (requirements & kUniforms_Requirement) {
this->write(separator); this->write(separator);
this->write("Uniforms _uniforms"); this->write("Uniforms _uniforms");
separator = ", "; separator = ", ";
} }
if (this->requirements(f.fDeclaration) & kGlobals_Requirement) { if (requirements & kGlobals_Requirement) {
this->write(separator); this->write(separator);
this->write("thread Globals* _globals"); this->write("thread Globals* _globals");
separator = ", "; separator = ", ";
} }
if (requirements & kFragCoord_Requirement) {
this->write(separator);
this->write("float4 _fragCoord");
separator = ", ";
}
} }
for (const auto& param : f.fDeclaration.fParameters) { for (const auto& param : f.fDeclaration.fParameters) {
this->write(separator); this->write(separator);
@ -1543,7 +1554,7 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi
const VariableReference& v = (const VariableReference&) e; const VariableReference& v = (const VariableReference&) e;
Requirements result = kNo_Requirements; Requirements result = kNo_Requirements;
if (v.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) { if (v.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
result = kInputs_Requirement; result = kGlobals_Requirement | kFragCoord_Requirement;
} else if (Variable::kGlobal_Storage == v.fVariable.fStorage) { } else if (Variable::kGlobal_Storage == v.fVariable.fStorage) {
if (v.fVariable.fModifiers.fFlags & Modifiers::kIn_Flag) { if (v.fVariable.fModifiers.fFlags & Modifiers::kIn_Flag) {
result = kInputs_Requirement; result = kInputs_Requirement;

View File

@ -95,6 +95,7 @@ protected:
static constexpr Requirements kOutputs_Requirement = 1 << 1; static constexpr Requirements kOutputs_Requirement = 1 << 1;
static constexpr Requirements kUniforms_Requirement = 1 << 2; static constexpr Requirements kUniforms_Requirement = 1 << 2;
static constexpr Requirements kGlobals_Requirement = 1 << 3; static constexpr Requirements kGlobals_Requirement = 1 << 3;
static constexpr Requirements kFragCoord_Requirement = 1 << 4;
enum IntrinsicKind { enum IntrinsicKind {
kSpecial_IntrinsicKind, kSpecial_IntrinsicKind,

View File

@ -100,7 +100,7 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
} }
} }
SkASSERT(found); SkASSERT(found);
fExtraEmitCodeCode += " this->emitChild(" + to_string(index) + ", fChildren[" + fExtraEmitCodeCode += " this->invokeChild(" + to_string(index) + ", fChildren[" +
to_string(index) + "], args);\n"; to_string(index) + "], args);\n";
this->write("%s"); this->write("%s");
fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kChildProcessor, fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kChildProcessor,

View File

@ -115,7 +115,7 @@ private:
class GLFP : public GrGLSLFragmentProcessor { class GLFP : public GrGLSLFragmentProcessor {
public: public:
void emitCode(EmitArgs& args) override { void emitCode(EmitArgs& args) override {
this->emitChild(0, args); this->invokeChild(0, args);
} }
private: private:

View File

@ -467,9 +467,9 @@ DEF_TEST(SkSLFPChildProcessors, r) {
}, },
{ {
"SkString _child0(\"_child0\");", "SkString _child0(\"_child0\");",
"this->emitChild(_outer.child1_index, &_child0, args);", "this->invokeChild(_outer.child1_index, &_child0, args);",
"SkString _child1(\"_child1\");", "SkString _child1(\"_child1\");",
"this->emitChild(_outer.child2_index, &_child1, args);", "this->invokeChild(_outer.child2_index, &_child1, args);",
"this->registerChildProcessor(src.childProcessor(child1_index).clone());", "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
"this->registerChildProcessor(src.childProcessor(child2_index).clone());" "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
}); });
@ -493,10 +493,10 @@ DEF_TEST(SkSLFPChildProcessorsWithInput, r) {
{ {
"SkString _input0(\"childIn\");", "SkString _input0(\"childIn\");",
"SkString _child0(\"_child0\");", "SkString _child0(\"_child0\");",
"this->emitChild(_outer.child1_index, _input0.c_str(), &_child0, args);", "this->invokeChild(_outer.child1_index, _input0.c_str(), &_child0, args);",
"SkString _input1(\"childOut1\");", "SkString _input1(\"childOut1\");",
"SkString _child1(\"_child1\");", "SkString _child1(\"_child1\");",
"this->emitChild(_outer.child2_index, _input1.c_str(), &_child1, args);", "this->invokeChild(_outer.child2_index, _input1.c_str(), &_child1, args);",
"this->registerChildProcessor(src.childProcessor(child1_index).clone());", "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
"this->registerChildProcessor(src.childProcessor(child2_index).clone());" "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
}); });
@ -515,7 +515,7 @@ DEF_TEST(SkSLFPChildProcessorWithInputExpression, r) {
{ {
"SkString _input0 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);", "SkString _input0 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
"SkString _child0(\"_child0\");", "SkString _child0(\"_child0\");",
"this->emitChild(_outer.child_index, _input0.c_str(), &_child0, args);", "this->invokeChild(_outer.child_index, _input0.c_str(), &_child0, args);",
"this->registerChildProcessor(src.childProcessor(child_index).clone());", "this->registerChildProcessor(src.childProcessor(child_index).clone());",
}); });
} }
@ -535,10 +535,10 @@ DEF_TEST(SkSLFPNestedChildProcessors, r) {
{ {
"SkString _input0 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);", "SkString _input0 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
"SkString _child0(\"_child0\");", "SkString _child0(\"_child0\");",
"this->emitChild(_outer.child1_index, _input0.c_str(), &_child0, args);", "this->invokeChild(_outer.child1_index, _input0.c_str(), &_child0, args);",
"SkString _input1 = SkStringPrintf(\"%s * %s\", args.fInputColor, _child0.c_str());", "SkString _input1 = SkStringPrintf(\"%s * %s\", args.fInputColor, _child0.c_str());",
"SkString _child1(\"_child1\");", "SkString _child1(\"_child1\");",
"this->emitChild(_outer.child2_index, _input1.c_str(), &_child1, args);", "this->invokeChild(_outer.child2_index, _input1.c_str(), &_child1, args);",
"this->registerChildProcessor(src.childProcessor(child1_index).clone());", "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
"this->registerChildProcessor(src.childProcessor(child2_index).clone());" "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
}); });
@ -565,7 +565,7 @@ DEF_TEST(SkSLFPChildFPAndGlobal, r) {
"(hasCap ? \"true\" : \"false\"));", "(hasCap ? \"true\" : \"false\"));",
"SkString _input0 = SkStringPrintf(\"%s\", args.fInputColor);", "SkString _input0 = SkStringPrintf(\"%s\", args.fInputColor);",
"SkString _child0(\"_child0\");", "SkString _child0(\"_child0\");",
"this->emitChild(_outer.child_index, _input0.c_str(), &_child0, args);", "this->invokeChild(_outer.child_index, _input0.c_str(), &_child0, args);",
"fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}" "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}"
"\\n\", args.fOutputColor, _child0.c_str(), args.fOutputColor);", "\\n\", args.fOutputColor, _child0.c_str(), args.fOutputColor);",
"this->registerChildProcessor(src.childProcessor(child_index).clone());" "this->registerChildProcessor(src.childProcessor(child_index).clone());"
@ -592,7 +592,7 @@ DEF_TEST(SkSLFPChildProcessorInlineFieldAccess, r) {
"\"true\" : \"false\"));", "\"true\" : \"false\"));",
"SkString _input0 = SkStringPrintf(\"%s\", args.fInputColor);", "SkString _input0 = SkStringPrintf(\"%s\", args.fInputColor);",
"SkString _child0(\"_child0\");", "SkString _child0(\"_child0\");",
"this->emitChild(_outer.child_index, _input0.c_str(), &_child0, args);", "this->invokeChild(_outer.child_index, _input0.c_str(), &_child0, args);",
"fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\"" "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\""
", args.fOutputColor, _child0.c_str(), args.fOutputColor);", ", args.fOutputColor, _child0.c_str(), args.fOutputColor);",
"this->registerChildProcessor(src.childProcessor(child_index).clone());" "this->registerChildProcessor(src.childProcessor(child_index).clone());"
@ -619,7 +619,7 @@ DEF_TEST(SkSLFPChildProcessorFieldAccess, r) {
"fragBuilder->codeAppendf(\"bool opaque = %s;\\nif (opaque) {\", " "fragBuilder->codeAppendf(\"bool opaque = %s;\\nif (opaque) {\", "
"(opaque ? \"true\" : \"false\"));", "(opaque ? \"true\" : \"false\"));",
"SkString _child0(\"_child0\");", "SkString _child0(\"_child0\");",
"this->emitChild(_outer.child_index, &_child0, args);", "this->invokeChild(_outer.child_index, &_child0, args);",
"fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(0.5);\\n}\\n\"" "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(0.5);\\n}\\n\""
", args.fOutputColor, _child0.c_str(), args.fOutputColor);", ", args.fOutputColor, _child0.c_str(), args.fOutputColor);",
"this->registerChildProcessor(src.childProcessor(child_index).clone());" "this->registerChildProcessor(src.childProcessor(child_index).clone());"
@ -641,7 +641,7 @@ DEF_TEST(SkSLFPNullableChildProcessor, r) {
{ {
"SkString _child0(\"_child0\");", "SkString _child0(\"_child0\");",
"if (_outer.child_index >= 0) {", "if (_outer.child_index >= 0) {",
"this->emitChild(_outer.child_index, &_child0, args);", "this->invokeChild(_outer.child_index, &_child0, args);",
"} else {", "} else {",
"fragBuilder->codeAppendf(\"half4 %s;\", _child0.c_str());", "fragBuilder->codeAppendf(\"half4 %s;\", _child0.c_str());",
"}", "}",