Added modifier support to DSLFunction

This also includes a couple of fixes to DSLFunction error reporting.

Change-Id: Iab813143511c408df2dba7a4dc8beddea1a8e8d0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/427736
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
Ethan Nicholas 2021-07-14 09:52:16 -04:00 committed by Skia Commit-Bot
parent 6b7ec00e6e
commit 292a09da2b
5 changed files with 73 additions and 14 deletions

View File

@ -27,7 +27,12 @@ class DSLType;
class DSLFunction {
public:
template<class... Parameters>
DSLFunction(const DSLType& returnType, skstd::string_view name, Parameters&... parameters) {
DSLFunction(const DSLType& returnType, skstd::string_view name, Parameters&... parameters)
: DSLFunction(DSLModifiers(), returnType, name, parameters...) {}
template<class... Parameters>
DSLFunction(DSLModifiers modifiers, const DSLType& returnType, skstd::string_view name,
Parameters&... parameters) {
SkTArray<DSLVar*> parameterArray;
parameterArray.reserve_back(sizeof...(parameters));
@ -35,11 +40,16 @@ public:
// (parameterArray.push_back(&parameters), ...);
int unused[] = {0, (static_cast<void>(parameterArray.push_back(&parameters)), 0)...};
static_cast<void>(unused);
this->init(returnType, name, std::move(parameterArray));
this->init(modifiers, returnType, name, std::move(parameterArray));
}
DSLFunction(const DSLType& returnType, const char* name, SkTArray<DSLVar*> parameters) {
this->init(returnType, name, std::move(parameters));
DSLFunction(const DSLType& returnType, skstd::string_view name, SkTArray<DSLVar*> parameters) {
this->init(DSLModifiers(), returnType, name, std::move(parameters));
}
DSLFunction(DSLModifiers modifiers, const DSLType& returnType, skstd::string_view name,
SkTArray<DSLVar*> parameters) {
this->init(modifiers, returnType, name, std::move(parameters));
}
DSLFunction(const SkSL::FunctionDeclaration* decl)
@ -88,7 +98,8 @@ private:
collectArgs(args, std::forward<RemainingArgs>(remaining)...);
}
void init(const DSLType& returnType, skstd::string_view name, SkTArray<DSLVar*> params);
void init(DSLModifiers modifiers, const DSLType& returnType, skstd::string_view name,
SkTArray<DSLVar*> params);
const SkSL::FunctionDeclaration* fDecl = nullptr;
};

View File

@ -18,8 +18,20 @@ namespace SkSL {
namespace dsl {
void DSLFunction::init(const DSLType& returnType, skstd::string_view name,
void DSLFunction::init(DSLModifiers modifiers, const DSLType& returnType, skstd::string_view name,
SkTArray<DSLVar*> params) {
// Conservatively assume all user-defined functions have side effects.
if (!DSLWriter::IsModule()) {
modifiers.fModifiers.fFlags |= Modifiers::kHasSideEffects_Flag;
}
if (DSLWriter::Context().fConfig->fSettings.fForceNoInline) {
// Apply the `noinline` modifier to every function. This allows us to test Runtime
// Effects without any inlining, even when the code is later added to a paint.
modifiers.fModifiers.fFlags &= ~Modifiers::kInline_Flag;
modifiers.fModifiers.fFlags |= Modifiers::kNoInline_Flag;
}
std::vector<std::unique_ptr<Variable>> paramVars;
paramVars.reserve(params.size());
bool isMain = name == "main";
@ -66,20 +78,26 @@ void DSLFunction::init(const DSLType& returnType, skstd::string_view name,
param->fDeclaration = nullptr;
}
SkASSERT(paramVars.size() == params.size());
for (size_t i = 0; i < params.size(); ++i) {
params[i]->fVar = paramVars[i].get();
}
fDecl = SkSL::FunctionDeclaration::Convert(DSLWriter::Context(),
*DSLWriter::SymbolTable(),
/*offset=*/-1,
DSLWriter::Modifiers(SkSL::Modifiers()),
DSLWriter::Modifiers(modifiers.fModifiers),
isMain ? name : DSLWriter::Name(name),
std::move(paramVars), &returnType.skslType(),
/*isBuiltin=*/false);
DSLWriter::IsModule());
DSLWriter::ReportErrors();
if (fDecl) {
for (size_t i = 0; i < params.size(); ++i) {
params[i]->fVar = fDecl->parameters()[i];
}
}
}
void DSLFunction::define(DSLBlock block) {
if (!fDecl) {
// Evidently we failed to create the declaration; error should already have been reported.
// Release the block so we don't fail its destructor assert.
block.release();
return;
}
SkASSERTF(!fDecl->definition(), "function '%s' already defined", fDecl->description().c_str());
@ -98,7 +116,8 @@ DSLExpression DSLFunction::call(SkTArray<DSLWrapper<DSLExpression>> args) {
for (DSLWrapper<DSLExpression>& arg : args) {
released.push_back(arg->release());
}
return DSLExpression(DSLWriter::Call(*fDecl, std::move(released)));
std::unique_ptr<SkSL::Expression> result = DSLWriter::Call(*fDecl, std::move(released));
return result ? DSLExpression(std::move(result)) : DSLExpression();
}
} // namespace dsl

View File

@ -36,7 +36,8 @@ DSLWriter::DSLWriter(SkSL::Compiler* compiler, SkSL::ProgramKind kind,
const SkSL::ProgramSettings& settings, SkSL::ParsedModule module,
bool isModule)
: fCompiler(compiler)
, fSettings(settings) {
, fSettings(settings)
, fIsModule(isModule) {
fOldModifiersPool = fCompiler->fContext->fModifiersPool;
fOldConfig = fCompiler->fContext->fConfig;
@ -151,6 +152,9 @@ DSLPossibleExpression DSLWriter::Construct(const SkSL::Type& type,
args.reserve_back(rawArgs.size());
for (DSLExpression& arg : rawArgs) {
if (!arg.valid()) {
return DSLPossibleExpression(nullptr);
}
args.push_back(arg.release());
}
return SkSL::Constructor::Convert(Context(), /*offset=*/-1, type, std::move(args));

View File

@ -98,6 +98,8 @@ public:
*/
static std::unique_ptr<ProgramConfig>& GetProgramConfig() { return Instance().fConfig; }
static bool IsModule() { return Instance().fIsModule; }
static void Reset();
/**
@ -272,6 +274,7 @@ private:
ErrorHandler* fErrorHandler = nullptr;
ProgramSettings fSettings;
Mangler fMangler;
bool fIsModule;
bool fEncounteredErrors = false;
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
struct StackFrame {

View File

@ -126,7 +126,8 @@ static SkSL::String stringize(DSLPossibleStatement& stmt) { return stmt.release
static SkSL::String stringize(DSLExpression& expr) { return expr.release()->description(); }
static SkSL::String stringize(DSLPossibleExpression& expr) { return expr.release()->description(); }
static SkSL::String stringize(DSLBlock& blck) { return blck.release()->description(); }
static SkSL::String stringize(SkSL::IRNode& node) { return node.description(); }
static SkSL::String stringize(SkSL::IRNode& node) { return node.description(); }
static SkSL::String stringize(SkSL::Program& program) { return program.description(); }
template <typename T>
static void expect_equal(skiatest::Reporter* r, int lineNumber, T& input, const char* expected) {
@ -1978,3 +1979,24 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLRTAdjust, r, ctxInfo) {
"(sk_PerVertex.sk_Position.ww * sk_RTAdjust.yw)), 0.0, sk_PerVertex.sk_Position.w));"
"}");
}
DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLInlining, r, ctxInfo) {
AutoDSLContext context(ctxInfo.directContext()->priv().getGpu(), no_mark_vars_declared());
DSLVar x(kFloat_Type, "x");
DSLFunction sqr(kFloat_Type, "sqr", x);
sqr.define(
Return(x * x)
);
DSLFunction(kVoid_Type, "main").define(
sk_FragColor() = (sqr(2), Half4(sqr(3)))
);
std::unique_ptr<SkSL::Program> program = ReleaseProgram();
EXPECT_EQUAL(*program,
"layout(location = 0, index = 0, builtin = 10001) out half4 sk_FragColor;"
"layout(builtin = 17)in bool sk_Clockwise;"
"void main() {"
"/* inlined: sqr */;"
"/* inlined: sqr */;"
"(sk_FragColor = (4.0 , half4(half(9.0))));"
"}");
}