Fix implicit references to _input when GrSkSLFP invokes children

This actually solves two different bugs:

1) A call to sample(child) in a helper function would fail to compile.
   We were invoking the child's entry point with the default color
   argument of args.fInputColor. That was "_input", which is a parameter
   to our main.
2) The runtime effect's FP hard-wired references to the main color
   parameter to args.fInputColor (via a builtin id). This meant that the
   user code could change the variable, then call sample and have those
   changes visible to the child. That shoudln't happen (unless you
   actually pass a color to the child explicitly).

Doing this with an extra global variable is somewhat ugly, and adds some
overhead. Hopefully the driver is able to see through it and optimize
this.

Bug: skia:10506
Change-Id: I11d152bd9f8b270afd53d3bfa71d2e728c8fd729
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/397154
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
Brian Osman 2021-04-15 15:39:03 -04:00 committed by Skia Commit-Bot
parent 829de5b409
commit ce585026db

View File

@ -37,8 +37,11 @@ public:
class FPCallbacks : public SkSL::PipelineStage::Callbacks {
public:
FPCallbacks(GrGLSLSkSLFP* self, EmitArgs& args, const SkSL::Context& context)
: fSelf(self), fArgs(args), fContext(context) {}
FPCallbacks(GrGLSLSkSLFP* self,
EmitArgs& args,
const char* inputColor,
const SkSL::Context& context)
: fSelf(self), fArgs(args), fInputColor(inputColor), fContext(context) {}
using String = SkSL::String;
@ -93,7 +96,7 @@ public:
}
String sampleChild(int index, String coords) override {
return String(fSelf->invokeChild(index, fArgs, coords).c_str());
return String(fSelf->invokeChild(index, fInputColor, fArgs, coords).c_str());
}
String sampleChildWithMatrix(int index, String matrix) override {
@ -104,16 +107,25 @@ public:
const GrFragmentProcessor* child = fArgs.fFp.childProcessor(index);
const bool hasUniformMatrix = child && child->sampleUsage().hasUniformMatrix();
return String(
fSelf->invokeChildWithMatrix(index, fArgs, hasUniformMatrix ? "" : matrix)
fSelf->invokeChildWithMatrix(
index, fInputColor, fArgs, hasUniformMatrix ? "" : matrix)
.c_str());
}
GrGLSLSkSLFP* fSelf;
EmitArgs& fArgs;
const char* fInputColor;
const SkSL::Context& fContext;
};
FPCallbacks callbacks(this, args, *program.fContext);
// Snap off a global copy of the input color at the start of main. We need this when
// we call child processors (particularly from helper functions, which can't "see" the
// parameter to main). Even from within main, if the code mutates the parameter, calls to
// sample should still be passing the original color (by default).
GrShaderVar inputColorCopy(args.fFragBuilder->getMangledFunctionName("inColor"),
kHalf4_GrSLType);
args.fFragBuilder->declareGlobal(inputColorCopy);
args.fFragBuilder->codeAppendf("%s = %s;\n", inputColorCopy.c_str(), args.fInputColor);
// Callback to define a function (and return its mangled name)
SkString coordsVarName = args.fFragBuilder->newTmpVarName("coords");
@ -123,6 +135,7 @@ public:
args.fFragBuilder->codeAppendf("float2 %s = %s;\n", coords, args.fSampleCoord);
}
FPCallbacks callbacks(this, args, inputColorCopy.c_str(), *program.fContext);
SkSL::PipelineStage::ConvertProgram(program, coords, args.fInputColor, &callbacks);
}