Emit helper function in GenerateDefaultGlueCode when children exist.
A runtime effect needs to be able to invoke a child snippet from a `child.eval()` expression anywhere. Because `eval` occurs in an expression context, we don't have the ability to emit multiple statements, or declare new variables. That means all of our glue code needs to eventually become glue-expressions. When there are no children, the default glue code is just a function call to a snippet, so this will actually work fine as an expression. However, when there _are_ children, the glue code becomes arbitrarily complex. (We need to call child snippets, which could themselves call more children.) Now, when children exist, the default glue code emits a helper function which invokes all of the children first, followed by invoking the shader snippet passing along all the child outputs. This gives us some of that Ganesh-like tree structure when it's needed, but simple flat code when it's not. Change-Id: I85e42f0794872c9f378ec63581364e0ed55f6047 Bug: skia:13508 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/558308 Auto-Submit: John Stiles <johnstiles@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
cd938c5b0f
commit
5556c2ca9a
@ -187,11 +187,8 @@ std::string SkShaderInfo::toSkSL() const {
|
|||||||
int binding = 0;
|
int binding = 0;
|
||||||
preamble += skgpu::graphite::GetMtlTexturesAndSamplers(fBlockReaders, &binding);
|
preamble += skgpu::graphite::GetMtlTexturesAndSamplers(fBlockReaders, &binding);
|
||||||
|
|
||||||
std::string mainBody = "void main() {\n";
|
std::string mainBody = "void main() {\n"
|
||||||
|
" const float4x4 initialPreLocal = float4x4(1.0);\n";
|
||||||
if (this->needsLocalCoords()) {
|
|
||||||
mainBody += " const float4x4 initialPreLocal = float4x4(1);\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string parentPreLocal = "initialPreLocal";
|
std::string parentPreLocal = "initialPreLocal";
|
||||||
std::string lastOutputVar = "initialColor";
|
std::string lastOutputVar = "initialColor";
|
||||||
@ -347,7 +344,7 @@ static std::string append_default_snippet_arguments(const SkShaderSnippet* entry
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The default glue code just calls a helper function with the signature:
|
// The default glue code just calls a built-in function with the signature:
|
||||||
// half4 BuiltinFunctionName(/* all uniforms as parameters */);
|
// half4 BuiltinFunctionName(/* all uniforms as parameters */);
|
||||||
// and stores the result in a variable named "resultName".
|
// and stores the result in a variable named "resultName".
|
||||||
void GenerateDefaultGlueCode(const SkShaderInfo& shaderInfo,
|
void GenerateDefaultGlueCode(const SkShaderInfo& shaderInfo,
|
||||||
@ -377,10 +374,12 @@ void GenerateDefaultGlueCode(const SkShaderInfo& shaderInfo,
|
|||||||
#endif // defined(SK_GRAPHITE_ENABLED) && defined(SK_ENABLE_SKSL)
|
#endif // defined(SK_GRAPHITE_ENABLED) && defined(SK_ENABLE_SKSL)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The default-with-children glue code just calls a helper function with the signature:
|
// The default-with-children glue code creates a function in the preamble with a signature of:
|
||||||
// half4 BuiltinFunctionName(/* all uniforms as parameters */,
|
// half4 BuiltinFunctionName_N(half4 inColor, float4x4 preLocal) { ... }
|
||||||
// /* all child output variable names as parameters */);
|
// This function invokes each child in sequence, and then calls the built-in function, passing all
|
||||||
// and stores the result in a variable named "resultName".
|
// uniforms and child outputs along:
|
||||||
|
// half4 BuiltinFunctionName(/* all uniforms as parameters */,
|
||||||
|
// /* all child output variable names as parameters */);
|
||||||
void GenerateDefaultGlueCodeWithChildren(const SkShaderInfo& shaderInfo,
|
void GenerateDefaultGlueCodeWithChildren(const SkShaderInfo& shaderInfo,
|
||||||
const std::string& resultName,
|
const std::string& resultName,
|
||||||
int* entryIndex,
|
int* entryIndex,
|
||||||
@ -400,22 +399,38 @@ void GenerateDefaultGlueCodeWithChildren(const SkShaderInfo& shaderInfo,
|
|||||||
SkASSERT(entry->fUniforms.front().type() == SkSLType::kFloat4x4);
|
SkASSERT(entry->fUniforms.front().type() == SkSLType::kFloat4x4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoke all children ahead of this entry's glue code.
|
// Create a helper function that invokes each of the children, then calls the snippet.
|
||||||
int curEntryIndex = *entryIndex;
|
int curEntryIndex = *entryIndex;
|
||||||
|
std::string helperFnName = get_mangled_name(entry->fStaticFunctionName, curEntryIndex);
|
||||||
|
std::string helperFn = SkSL::String::printf("half4 %s(half4 inColor, float4x4 preLocal) {",
|
||||||
|
helperFnName.c_str());
|
||||||
|
// Invoke all children from inside the helper function.
|
||||||
std::vector<std::string> childOutputVarNames = emit_child_glue_code(shaderInfo,
|
std::vector<std::string> childOutputVarNames = emit_child_glue_code(shaderInfo,
|
||||||
entryIndex,
|
entryIndex,
|
||||||
priorStageOutputName,
|
"inColor",
|
||||||
currentPreLocalName,
|
"preLocal",
|
||||||
preamble,
|
preamble,
|
||||||
mainBody,
|
&helperFn,
|
||||||
indent);
|
/*indent=*/0);
|
||||||
SkASSERT((int)childOutputVarNames.size() == entry->fNumChildren);
|
SkASSERT((int)childOutputVarNames.size() == entry->fNumChildren);
|
||||||
|
|
||||||
|
// Finally, invoke the snippet from the helper function, passing uniforms and child outputs.
|
||||||
|
SkSL::String::appendf(&helperFn, " return %s", entry->fStaticFunctionName);
|
||||||
|
helperFn += append_default_snippet_arguments(entry, curEntryIndex, "preLocal",
|
||||||
|
childOutputVarNames);
|
||||||
|
helperFn += ";\n"
|
||||||
|
"}\n";
|
||||||
|
// Add the helper function to the bottom of the preamble.
|
||||||
|
*preamble += helperFn;
|
||||||
|
|
||||||
|
// Invoke the helper function from the main body.
|
||||||
add_indent(mainBody, indent);
|
add_indent(mainBody, indent);
|
||||||
SkSL::String::appendf(mainBody, "%s = %s", resultName.c_str(), entry->fStaticFunctionName);
|
SkSL::String::appendf(mainBody,
|
||||||
*mainBody += append_default_snippet_arguments(entry, curEntryIndex, currentPreLocalName,
|
"%s = %s(%s, %s);",
|
||||||
childOutputVarNames);
|
resultName.c_str(),
|
||||||
*mainBody += ";\n";
|
helperFnName.c_str(),
|
||||||
|
priorStageOutputName.c_str(),
|
||||||
|
currentPreLocalName.c_str());
|
||||||
#endif // defined(SK_GRAPHITE_ENABLED) && defined(SK_ENABLE_SKSL)
|
#endif // defined(SK_GRAPHITE_ENABLED) && defined(SK_ENABLE_SKSL)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,8 +627,14 @@ public:
|
|||||||
|
|
||||||
void defineFunction(const char* decl, const char* body, bool isMain) override {
|
void defineFunction(const char* decl, const char* body, bool isMain) override {
|
||||||
if (isMain) {
|
if (isMain) {
|
||||||
SkSL::String::appendf(fPreamble, "half4 %s_%d(float2 coords, half4 inColor) {\n%s}\n",
|
SkSL::String::appendf(fPreamble,
|
||||||
kRuntimeShaderName, fEntryIndex, body);
|
"half4 %s_%d(float4x4 preLocal, half4 inColor) {\n"
|
||||||
|
" float2 coords=(preLocal * dev2LocalUni * sk_FragCoord).xy;\n"
|
||||||
|
"%s"
|
||||||
|
"}\n",
|
||||||
|
kRuntimeShaderName,
|
||||||
|
fEntryIndex,
|
||||||
|
body);
|
||||||
} else {
|
} else {
|
||||||
SkSL::String::appendf(fPreamble, "%s {\n%s}\n", decl, body);
|
SkSL::String::appendf(fPreamble, "%s {\n%s}\n", decl, body);
|
||||||
}
|
}
|
||||||
@ -695,8 +716,7 @@ void GenerateRuntimeShaderGlueCode(const SkShaderInfo& shaderInfo,
|
|||||||
SkASSERT(reader.entry()->fUniforms[0].type() == SkSLType::kFloat4x4);
|
SkASSERT(reader.entry()->fUniforms[0].type() == SkSLType::kFloat4x4);
|
||||||
|
|
||||||
add_indent(mainBody, indent);
|
add_indent(mainBody, indent);
|
||||||
SkSL::String::appendf(mainBody,
|
SkSL::String::appendf(mainBody, "%s = %s_%d(%s, %s);\n",
|
||||||
"%s = %s_%d((%s * dev2LocalUni * sk_FragCoord).xy, (%s));\n",
|
|
||||||
resultName.c_str(),
|
resultName.c_str(),
|
||||||
entry->fName, *entryIndex,
|
entry->fName, *entryIndex,
|
||||||
currentPreLocalName.c_str(),
|
currentPreLocalName.c_str(),
|
||||||
|
Loading…
Reference in New Issue
Block a user