Migrate PermitInvalidStaticTests flag to Program::Settings.

This will make it accessible from the IR generator (in a future CL) and
is more in line with how we typically manage settings.

Change-Id: I478d617119cba079d1124b2b9c26d5573c7d6ae3
Bug: skia:11319
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/369480
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
John Stiles 2021-02-11 15:46:11 -05:00
parent bf79dff9d8
commit d6a5f449d8
4 changed files with 28 additions and 37 deletions

View File

@ -84,11 +84,10 @@ public:
const String* fOldSource;
};
Compiler::Compiler(const ShaderCapsClass* caps, Flags flags)
Compiler::Compiler(const ShaderCapsClass* caps)
: fContext(std::make_shared<Context>(/*errors=*/*this))
, fCaps(caps)
, fInliner(fContext.get())
, fFlags(flags)
, fErrorCount(0) {
SkASSERT(fCaps);
fRootSymbolTable = std::make_shared<SymbolTable>(this, /*builtin=*/true);
@ -1411,12 +1410,13 @@ void Compiler::simplifyStatement(DefinitionMap& definitions,
found = true;
break;
} else {
if (s.isStatic() && !(fFlags & kPermitInvalidStaticTests_Flag) &&
optimizationContext->fSilences.find(&s) ==
optimizationContext->fSilences.end()) {
this->error(s.fOffset,
"static switch contains non-static conditional break");
optimizationContext->fSilences.insert(&s);
if (s.isStatic() &&
!fIRGenerator->fSettings->fPermitInvalidStaticTests) {
auto [iter, didInsert] = optimizationContext->fSilences.insert(&s);
if (didInsert) {
this->error(s.fOffset, "static switch contains non-static "
"conditional break");
}
}
return; // can't simplify
}
@ -1429,12 +1429,13 @@ void Compiler::simplifyStatement(DefinitionMap& definitions,
if (newBlock) {
(*iter)->setStatement(std::move(newBlock), usage);
} else {
if (s.isStatic() && !(fFlags & kPermitInvalidStaticTests_Flag) &&
optimizationContext->fSilences.find(&s) ==
optimizationContext->fSilences.end()) {
this->error(s.fOffset,
"static switch contains non-static conditional break");
optimizationContext->fSilences.insert(&s);
if (s.isStatic() &&
!fIRGenerator->fSettings->fPermitInvalidStaticTests) {
auto [iter, didInsert] = optimizationContext->fSilences.insert(&s);
if (didInsert) {
this->error(s.fOffset, "static switch contains non-static "
"conditional break");
}
}
return; // can't simplify
}
@ -1560,16 +1561,16 @@ bool Compiler::scanCFG(FunctionDefinition& f, ProgramUsage* usage) {
switch (s.kind()) {
case Statement::Kind::kIf:
if (s.as<IfStatement>().isStatic() &&
!(fFlags & kPermitInvalidStaticTests_Flag)) {
!fIRGenerator->fSettings->fPermitInvalidStaticTests) {
this->error(s.fOffset, "static if has non-static test");
}
++iter;
break;
case Statement::Kind::kSwitch:
if (s.as<SwitchStatement>().isStatic() &&
!(fFlags & kPermitInvalidStaticTests_Flag) &&
!fIRGenerator->fSettings->fPermitInvalidStaticTests &&
optimizationContext.fSilences.find(&s) ==
optimizationContext.fSilences.end()) {
optimizationContext.fSilences.end()) {
this->error(s.fOffset, "static switch has non-static test");
}
++iter;

View File

@ -78,14 +78,6 @@ public:
static constexpr const char* RTADJUST_NAME = "sk_RTAdjust";
static constexpr const char* PERVERTEX_NAME = "sk_PerVertex";
enum Flags {
kNone_Flags = 0,
// permits static if/switch statements to be used with non-constant tests. This is used when
// producing H and CPP code; the static tests don't have to have constant values *yet*, but
// the generated code will contain a static test which then does have to be a constant.
kPermitInvalidStaticTests_Flag = 1,
};
struct OptimizationContext {
// nodes we have already reported errors for and should not error on again
std::unordered_set<const IRNode*> fSilences;
@ -99,7 +91,7 @@ public:
StatementArray fOwnedStatements;
};
Compiler(const ShaderCapsClass* caps, Flags flags = kNone_Flags);
Compiler(const ShaderCapsClass* caps);
~Compiler() override;
@ -244,7 +236,6 @@ private:
Inliner fInliner;
std::unique_ptr<IRGenerator> fIRGenerator;
int fFlags;
const String* fSource;
int fErrorCount;

View File

@ -313,9 +313,9 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
puts(errorText);
};
auto compileProgram = [&](SkSL::Compiler::Flags flags, const auto& writeFn) -> ResultCode {
auto compileProgram = [&](const auto& writeFn) -> ResultCode {
SkSL::FileOutputStream out(outputPath);
SkSL::Compiler compiler(caps, flags);
SkSL::Compiler compiler(caps);
if (!out.isValid()) {
printf("error writing '%s'\n", outputPath.c_str());
return ResultCode::kOutputError;
@ -334,14 +334,12 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
if (outputPath.endsWith(".spirv")) {
return compileProgram(
SkSL::Compiler::kNone_Flags,
[](SkSL::Compiler& compiler, SkSL::Program& program, SkSL::OutputStream& out) {
return compiler.toSPIRV(program, out);
});
} else if (outputPath.endsWith(".asm.frag") || outputPath.endsWith(".asm.vert") ||
outputPath.endsWith(".asm.geom")) {
return compileProgram(
SkSL::Compiler::kNone_Flags,
[](SkSL::Compiler& compiler, SkSL::Program& program, SkSL::OutputStream& out) {
// Compile program to SPIR-V assembly in a string-stream.
SkSL::StringStream assembly;
@ -362,33 +360,30 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
});
} else if (outputPath.endsWith(".glsl")) {
return compileProgram(
SkSL::Compiler::kNone_Flags,
[](SkSL::Compiler& compiler, SkSL::Program& program, SkSL::OutputStream& out) {
return compiler.toGLSL(program, out);
});
} else if (outputPath.endsWith(".metal")) {
return compileProgram(
SkSL::Compiler::kNone_Flags,
[](SkSL::Compiler& compiler, SkSL::Program& program, SkSL::OutputStream& out) {
return compiler.toMetal(program, out);
});
} else if (outputPath.endsWith(".h")) {
settings.fReplaceSettings = false;
settings.fPermitInvalidStaticTests = true;
return compileProgram(
SkSL::Compiler::kPermitInvalidStaticTests_Flag,
[&](SkSL::Compiler& compiler, SkSL::Program& program, SkSL::OutputStream& out) {
return compiler.toH(program, base_name(inputPath.c_str(), "Gr", ".fp"), out);
});
} else if (outputPath.endsWith(".cpp")) {
settings.fReplaceSettings = false;
settings.fPermitInvalidStaticTests = true;
return compileProgram(
SkSL::Compiler::kPermitInvalidStaticTests_Flag,
[&](SkSL::Compiler& compiler, SkSL::Program& program, SkSL::OutputStream& out) {
return compiler.toCPP(program, base_name(inputPath.c_str(), "Gr", ".fp"), out);
});
} else if (outputPath.endsWith(".skvm")) {
return compileProgram(
SkSL::Compiler::kNone_Flags,
[](SkSL::Compiler&, SkSL::Program& program, SkSL::OutputStream& out) {
skvm::Builder builder{skvm::Features{}};
if (!SkSL::testingOnly_ProgramToSkVMShader(program, &builder)) {
@ -400,7 +395,7 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
return true;
});
} else if (outputPath.endsWith(".stage")) {
return compileProgram(SkSL::Compiler::kNone_Flags,
return compileProgram(
[](SkSL::Compiler&, SkSL::Program& program, SkSL::OutputStream& out) {
class Callbacks : public SkSL::PipelineStage::Callbacks {
public:

View File

@ -151,6 +151,10 @@ struct Program {
bool fValidateSPIRV = true;
// If true, any synthetic uniforms must use push constant syntax
bool fUsePushConstants = false;
// Permits static if/switch statements to be used with non-constant tests. This is used when
// producing H and CPP code; the static tests don't have to have constant values *yet*, but
// the generated code will contain a static test which then does have to be a constant.
bool fPermitInvalidStaticTests = false;
};
struct Inputs {