Change pipeline stage callbacks to support mangling type names

Structs, enums, and global variables are all going to require name
mangling. Move that to a separate virtual on the callback. More
importantly, the generator is going to need to do type-name substitution
inside the function declaration string, so the contract has shifted:
The generator constructs the entire function declaration line (using the
mangled name it gets from the new callback), then it calls
defineFunction with two strings, and a flag indicating if this is main
or not.

Bug: skia:10939, skia:11295, skia:11296
Change-Id: I535eee9bfbb2337013b539908fe3d658ec3b2dbd
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/368397
Reviewed-by: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2021-02-09 16:52:53 -05:00 committed by Skia Commit-Bot
parent 0bd5578c31
commit 55761ae5e6
7 changed files with 56 additions and 63 deletions

View File

@ -8,7 +8,6 @@
#include "src/gpu/GrShaderCaps.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLPipelineStageCodeGenerator.h"
#include "src/sksl/ir/SkSLFunctionDeclaration.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"
#include "src/sksl/ir/SkSLVariable.h"
@ -34,9 +33,7 @@ bool FuzzSKSL2Pipeline(sk_sp<SkData> bytes) {
return decl->var().name();
}
String defineFunction(const SkSL::FunctionDeclaration* decl, String /*body*/) override {
return decl->name();
}
void defineFunction(const char* /*decl*/, const char* /*body*/, bool /*isMain*/) override {}
String sampleChild(int index, String coords) override {
return SkSL::String::printf("sample(%d%s%s)", index, coords.empty() ? "" : ", ",

View File

@ -71,16 +71,15 @@ public:
return String(uniformName);
}
String defineFunction(const SkSL::FunctionDeclaration* decl, String body) override {
GrGLSLFPFragmentBuilder* fragBuilder = fArgs.fFragBuilder;
if (decl->name() == "main") {
fragBuilder->codeAppend(body.c_str());
return String("main");
String getMangledName(const char* name) override {
return String(fArgs.fFragBuilder->getMangledFunctionName(name).c_str());
}
void defineFunction(const char* decl, const char* body, bool isMain) override {
if (isMain) {
fArgs.fFragBuilder->codeAppend(body);
} else {
SkString mangledName =
fragBuilder->getMangledFunctionName(SkString(decl->name()).c_str());
fragBuilder->emitFunction(decl, mangledName.c_str(), body.c_str());
return String(mangledName.c_str());
fArgs.fFragBuilder->emitFunction(decl, body);
}
}

View File

@ -13,7 +13,6 @@
#include "src/gpu/glsl/GrGLSLBlend.h"
#include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
#include "src/sksl/ir/SkSLFunctionDeclaration.h"
GrGLSLShaderBuilder::GrGLSLShaderBuilder(GrGLSLProgramBuilder* program)
: fProgramBuilder(program)
@ -63,32 +62,6 @@ void GrGLSLShaderBuilder::appendFunctionDecl(GrSLType returnType,
this->functions().append(")");
}
void GrGLSLShaderBuilder::appendFunctionDecl(const SkSL::FunctionDeclaration* decl,
const char* mangledName) {
// This function is similar to decl->description(), but substitutes mangledName, and handles
// modifiers on parameters (eg inout).
this->functions().appendf("%s %s(", decl->returnType().displayName().c_str(), mangledName);
const char* separator = "";
for (auto p : decl->parameters()) {
// TODO: Handle arrays
const char* typeModifier = "";
switch (p->modifiers().fFlags & (SkSL::Modifiers::kIn_Flag | SkSL::Modifiers::kOut_Flag)) {
case SkSL::Modifiers::kOut_Flag:
typeModifier = "out ";
break;
case SkSL::Modifiers::kIn_Flag | SkSL::Modifiers::kOut_Flag:
typeModifier = "inout ";
break;
default:
break;
}
this->functions().appendf("%s%s%s %s", separator, typeModifier,
p->type().displayName().c_str(), SkString(p->name()).c_str());
separator = ", ";
}
this->functions().append(")");
}
void GrGLSLShaderBuilder::emitFunction(GrSLType returnType,
const char* mangledName,
SkSpan<const GrShaderVar> args,
@ -100,13 +73,10 @@ void GrGLSLShaderBuilder::emitFunction(GrSLType returnType,
"}\n\n", body);
}
void GrGLSLShaderBuilder::emitFunction(const SkSL::FunctionDeclaration* decl,
const char* mangledName,
const char* body) {
this->appendFunctionDecl(decl, mangledName);
this->functions().appendf(" {\n"
void GrGLSLShaderBuilder::emitFunction(const char* declaration, const char* body) {
this->functions().appendf("%s {\n"
"%s"
"}\n\n", body);
"}\n\n", declaration, body);
}
void GrGLSLShaderBuilder::emitFunctionPrototype(GrSLType returnType,

View File

@ -17,10 +17,6 @@
#include <stdarg.h>
namespace SkSL {
class FunctionDeclaration;
} // namespace SkSL
class GrGLSLColorSpaceXformHelper;
/**
@ -144,9 +140,7 @@ public:
const char* body,
bool forceInline = false);
void emitFunction(const SkSL::FunctionDeclaration* decl,
const char* mangledName,
const char* body);
void emitFunction(const char* declaration, const char* body);
/**
* Combines the various parts of the shader to create a single finalized shader string.
@ -184,8 +178,6 @@ protected:
SkSpan<const GrShaderVar> args,
bool forceInline);
void appendFunctionDecl(const SkSL::FunctionDeclaration* decl, const char* mangledName);
/**
* Features that should only be enabled internally by the builders.
*/

View File

@ -414,10 +414,10 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
return decl->var().name();
}
String defineFunction(const SkSL::FunctionDeclaration* decl,
String body) override {
fOutput += (decl->description() + "{" + body + "}");
return decl->name();
void defineFunction(const char* decl,
const char* body,
bool /*isMain*/) override {
fOutput += String(decl) + "{" + body + "}";
}
String sampleChild(int index, String coords) override {

View File

@ -56,6 +56,7 @@ private:
void write(const String& s);
void write(StringFragment s);
String typeName(const Type& type);
void writeType(const Type& type);
void writeFunction(const FunctionDefinition& f);
@ -288,8 +289,36 @@ void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
fCastReturnsToHalf = false;
}
String fnName = fCallbacks->defineFunction(&f.declaration(), body.fBuffer.str());
String fnName =
isMain ? "main" : fCallbacks->getMangledName(String(f.declaration().name()).c_str());
// This is similar to decl->description(), but substitutes a mangled name, and handles
// modifiers on parameters (eg inout).
const FunctionDeclaration& decl = f.declaration();
String declString =
String::printf("%s %s(", this->typeName(decl.returnType()).c_str(), fnName.c_str());
const char* separator = "";
for (auto p : decl.parameters()) {
// TODO: Handle arrays
const char* typeModifier = "";
switch (p->modifiers().fFlags & (SkSL::Modifiers::kIn_Flag | SkSL::Modifiers::kOut_Flag)) {
case SkSL::Modifiers::kOut_Flag:
typeModifier = "out ";
break;
case SkSL::Modifiers::kIn_Flag | SkSL::Modifiers::kOut_Flag:
typeModifier = "inout ";
break;
default:
break;
}
declString.appendf("%s%s%s %s", separator, typeModifier, this->typeName(p->type()).c_str(),
String(p->name()).c_str());
separator = ", ";
}
declString.append(")");
fFunctionNames.insert({&f.declaration(), std::move(fnName)});
fCallbacks->defineFunction(declString.c_str(), body.fBuffer.str().c_str(), isMain);
}
void PipelineStageCodeGenerator::writeGlobalVarDeclaration(const GlobalVarDeclaration& g) {
@ -331,8 +360,12 @@ void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& e) {
}
}
String PipelineStageCodeGenerator::typeName(const Type& type) {
return type.name();
}
void PipelineStageCodeGenerator::writeType(const Type& type) {
this->write(type.name());
this->write(this->typeName(type));
}
void PipelineStageCodeGenerator::writeExpression(const Expression& expr,

View File

@ -14,7 +14,6 @@
namespace SkSL {
class FunctionDeclaration;
struct Program;
class VarDeclaration;
@ -22,8 +21,11 @@ namespace PipelineStage {
class Callbacks {
public:
virtual ~Callbacks() = default;
virtual String getMangledName(const char* name) { return name; }
virtual void defineFunction(const char* declaration, const char* body, bool isMain) = 0;
virtual String declareUniform(const VarDeclaration*) = 0;
virtual String defineFunction(const FunctionDeclaration*, String body) = 0;
virtual String sampleChild(int index, String coords) = 0;
virtual String sampleChildWithMatrix(int index, String matrix) = 0;
};