Additional SkSL benches
This adds additional benchmarks to give us better insight into how long the various compilation phases take. The four benches per size now cover just parsing, parsing + converting to IR, parsing + converting to IR + optimizing, and finally parsing + converting to IR + optimizing + generating GLSL. Change-Id: I7099a5a9f40ae5031e330dc4e1bb08c2a20ada63 Bug: skia:10805 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/332262 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
64596c5c2b
commit
a2d6b31f66
@ -7,7 +7,12 @@
|
||||
#include "bench/Benchmark.h"
|
||||
#include "bench/ResultsWriter.h"
|
||||
#include "bench/SkSLBench.h"
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "src/gpu/GrCaps.h"
|
||||
#include "src/gpu/GrRecordingContextPriv.h"
|
||||
#include "src/sksl/SkSLCompiler.h"
|
||||
#include "src/sksl/SkSLIRGenerator.h"
|
||||
#include "src/sksl/SkSLParser.h"
|
||||
|
||||
class SkSLCompilerStartupBench : public Benchmark {
|
||||
protected:
|
||||
@ -28,10 +33,78 @@ protected:
|
||||
|
||||
DEF_BENCH(return new SkSLCompilerStartupBench();)
|
||||
|
||||
class SkSLBench : public Benchmark {
|
||||
enum class Output {
|
||||
kNone,
|
||||
kGLSL,
|
||||
kMetal,
|
||||
kSPIRV
|
||||
};
|
||||
|
||||
class SkSLCompileBench : public Benchmark {
|
||||
public:
|
||||
SkSLBench(SkSL::String name, const char* src)
|
||||
: fName("sksl_" + name)
|
||||
static const char* output_string(Output output) {
|
||||
switch (output) {
|
||||
case Output::kNone: return "";
|
||||
case Output::kGLSL: return "glsl_";
|
||||
case Output::kMetal: return "metal_";
|
||||
case Output::kSPIRV: return "spirv_";
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
|
||||
SkSLCompileBench(SkSL::String name, const char* src, bool optimize, Output output)
|
||||
: fName(SkSL::String("sksl_") + (optimize ? "" : "unoptimized_") + output_string(output) +
|
||||
name)
|
||||
, fSrc(src)
|
||||
, fCompiler(/*caps=*/nullptr)
|
||||
, fOutput(output) {
|
||||
fSettings.fOptimize = optimize;
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* onGetName() override {
|
||||
return fName.c_str();
|
||||
}
|
||||
|
||||
bool isSuitableFor(Backend backend) override {
|
||||
return backend == kNonRendering_Backend;
|
||||
}
|
||||
|
||||
void onDraw(int loops, SkCanvas* canvas) override {
|
||||
GrShaderCaps caps((GrContextOptions()));
|
||||
fCompiler.fCaps = ∩︀
|
||||
for (int i = 0; i < loops; i++) {
|
||||
std::unique_ptr<SkSL::Program> program = fCompiler.convertProgram(
|
||||
SkSL::Program::kFragment_Kind,
|
||||
fSrc,
|
||||
fSettings);
|
||||
if (fCompiler.errorCount()) {
|
||||
SK_ABORT("shader compilation failed: %s\n", fCompiler.errorText().c_str());
|
||||
}
|
||||
SkSL::String result;
|
||||
switch (fOutput) {
|
||||
case Output::kNone: break;
|
||||
case Output::kGLSL: SkAssertResult(fCompiler.toGLSL(*program, &result)); break;
|
||||
case Output::kMetal: SkAssertResult(fCompiler.toMetal(*program, &result)); break;
|
||||
case Output::kSPIRV: SkAssertResult(fCompiler.toSPIRV(*program, &result)); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SkSL::String fName;
|
||||
SkSL::String fSrc;
|
||||
SkSL::Compiler fCompiler;
|
||||
SkSL::Program::Settings fSettings;
|
||||
Output fOutput;
|
||||
|
||||
using INHERITED = Benchmark;
|
||||
};
|
||||
|
||||
class SkSLParseBench : public Benchmark {
|
||||
public:
|
||||
SkSLParseBench(SkSL::String name, const char* src)
|
||||
: fName("sksl_parse_" + name)
|
||||
, fSrc(src)
|
||||
, fCompiler(/*caps=*/nullptr) {}
|
||||
|
||||
@ -44,15 +117,21 @@ protected:
|
||||
return backend == kNonRendering_Backend;
|
||||
}
|
||||
|
||||
void onDelayedSetup() override {
|
||||
SkSL::ParsedModule module = fCompiler.moduleForProgramKind(
|
||||
SkSL::Program::Kind::kFragment_Kind);
|
||||
fCompiler.irGenerator().setSymbolTable(module.fSymbols);
|
||||
}
|
||||
|
||||
void onDraw(int loops, SkCanvas*) override {
|
||||
for (int i = 0; i < loops; i++) {
|
||||
std::unique_ptr<SkSL::Program> program = fCompiler.convertProgram(
|
||||
SkSL::Program::kFragment_Kind,
|
||||
fSrc,
|
||||
fSettings);
|
||||
fCompiler.irGenerator().pushSymbolTable();
|
||||
SkSL::Parser parser(fSrc.c_str(), fSrc.length(), *fCompiler.irGenerator().symbolTable(),
|
||||
fCompiler);
|
||||
parser.compilationUnit();
|
||||
fCompiler.irGenerator().popSymbolTable();
|
||||
if (fCompiler.errorCount()) {
|
||||
printf("%s\n", fCompiler.errorText().c_str());
|
||||
SK_ABORT("shader compilation failed");
|
||||
SK_ABORT("shader compilation failed: %s\n", fCompiler.errorText().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,7 +147,16 @@ private:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DEF_BENCH(return new SkSLBench("large", R"(
|
||||
#define COMPILER_BENCH(name, text) \
|
||||
static constexpr char name ## _SRC[] = text; \
|
||||
DEF_BENCH(return new SkSLParseBench(#name, name ## _SRC);) \
|
||||
DEF_BENCH(return new SkSLCompileBench(#name, name ## _SRC, /*optimize=*/false, Output::kNone);) \
|
||||
DEF_BENCH(return new SkSLCompileBench(#name, name ## _SRC, /*optimize=*/true, Output::kNone);) \
|
||||
DEF_BENCH(return new SkSLCompileBench(#name, name ## _SRC, /*optimize=*/true, Output::kGLSL);) \
|
||||
DEF_BENCH(return new SkSLCompileBench(#name, name ## _SRC, /*optimize=*/true, Output::kMetal);) \
|
||||
DEF_BENCH(return new SkSLCompileBench(#name, name ## _SRC, /*optimize=*/true, Output::kSPIRV);)
|
||||
|
||||
COMPILER_BENCH(large, R"(
|
||||
uniform half urange_Stage1;
|
||||
uniform half4 uleftBorderColor_Stage1_c0_c0;
|
||||
uniform half4 urightBorderColor_Stage1_c0_c0;
|
||||
@ -347,9 +435,9 @@ void main()
|
||||
sk_FragColor = output_Stage1 * outputCoverage_Stage0;
|
||||
}
|
||||
}
|
||||
)");)
|
||||
)");
|
||||
|
||||
DEF_BENCH(return new SkSLBench("medium", R"(
|
||||
COMPILER_BENCH(medium, R"(
|
||||
uniform half2 uDstTextureUpperLeft_Stage1;
|
||||
uniform half2 uDstTextureCoordScale_Stage1;
|
||||
uniform sampler2D uDstTextureSampler_Stage1;
|
||||
@ -414,9 +502,9 @@ DEF_BENCH(return new SkSLBench("medium", R"(
|
||||
(half4(1.0) - outputCoverage_Stage0) * _dstColor;
|
||||
}
|
||||
}
|
||||
)"); )
|
||||
)");
|
||||
|
||||
DEF_BENCH(return new SkSLBench("small", R"(
|
||||
COMPILER_BENCH(small, R"(
|
||||
uniform float3x3 umatrix_Stage1_c0_c0;
|
||||
uniform sampler2D uTextureSampler_0_Stage1;
|
||||
noperspective in float2 vTransformedCoords_0_Stage0;
|
||||
@ -453,9 +541,9 @@ DEF_BENCH(return new SkSLBench("small", R"(
|
||||
sk_FragColor = output_Stage1 * outputCoverage_Stage0;
|
||||
}
|
||||
}
|
||||
)"); )
|
||||
)");
|
||||
|
||||
DEF_BENCH(return new SkSLBench("tiny", "void main() { sk_FragColor = half4(1); }"); )
|
||||
COMPILER_BENCH(tiny, "void main() { sk_FragColor = half4(1); }");
|
||||
|
||||
#if defined(SK_BUILD_FOR_UNIX)
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#define SK_POSITION_BUILTIN 0
|
||||
|
||||
class SkBitSet;
|
||||
class SkSLCompileBench;
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
@ -218,14 +219,18 @@ public:
|
||||
LoadedModule loadModule(Program::Kind kind, ModuleData data, std::shared_ptr<SymbolTable> base);
|
||||
ParsedModule parseModule(Program::Kind kind, ModuleData data, const ParsedModule& base);
|
||||
|
||||
IRGenerator& irGenerator() {
|
||||
return *fIRGenerator;
|
||||
}
|
||||
|
||||
const ParsedModule& moduleForProgramKind(Program::Kind kind);
|
||||
|
||||
private:
|
||||
const ParsedModule& loadFPModule();
|
||||
const ParsedModule& loadGeometryModule();
|
||||
const ParsedModule& loadInterpreterModule();
|
||||
const ParsedModule& loadPipelineModule();
|
||||
|
||||
const ParsedModule& moduleForProgramKind(Program::Kind kind);
|
||||
|
||||
void addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
|
||||
DefinitionMap* definitions);
|
||||
void addDefinitions(const BasicBlock::Node& node, DefinitionMap* definitions);
|
||||
@ -289,6 +294,7 @@ private:
|
||||
String fErrorText;
|
||||
|
||||
friend class AutoSource;
|
||||
friend class ::SkSLCompileBench;
|
||||
};
|
||||
|
||||
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
|
||||
|
@ -1485,8 +1485,10 @@ void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
|
||||
}
|
||||
|
||||
void GLSLCodeGenerator::writeHeader() {
|
||||
this->write(fProgram.fCaps->versionDeclString());
|
||||
this->writeLine();
|
||||
if (fProgram.fCaps->versionDeclString()) {
|
||||
this->write(fProgram.fCaps->versionDeclString());
|
||||
this->writeLine();
|
||||
}
|
||||
}
|
||||
|
||||
void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
|
||||
|
@ -2993,7 +2993,7 @@ IRGenerator::IRBundle IRGenerator::convertProgram(
|
||||
}
|
||||
|
||||
Parser parser(text, length, *fSymbolTable, fErrors);
|
||||
fFile = parser.file();
|
||||
fFile = parser.compilationUnit();
|
||||
if (fErrors.errorCount()) {
|
||||
return {};
|
||||
}
|
||||
|
@ -133,6 +133,17 @@ public:
|
||||
|
||||
const Program::Settings* settings() const { return fSettings; }
|
||||
|
||||
std::shared_ptr<SymbolTable>& symbolTable() {
|
||||
return fSymbolTable;
|
||||
}
|
||||
|
||||
void setSymbolTable(std::shared_ptr<SymbolTable>& symbolTable) {
|
||||
fSymbolTable = symbolTable;
|
||||
}
|
||||
|
||||
void pushSymbolTable();
|
||||
void popSymbolTable();
|
||||
|
||||
const Context& fContext;
|
||||
|
||||
private:
|
||||
@ -141,9 +152,6 @@ private:
|
||||
*/
|
||||
std::unique_ptr<ModifiersPool> releaseModifiers();
|
||||
|
||||
void pushSymbolTable();
|
||||
void popSymbolTable();
|
||||
|
||||
void checkModifiers(int offset, const Modifiers& modifiers, int permitted);
|
||||
StatementArray convertVarDeclarations(const ASTNode& decl, Variable::Storage storage);
|
||||
void convertFunction(const ASTNode& f);
|
||||
|
@ -138,7 +138,7 @@ Parser::Parser(const char* text, size_t length, SymbolTable& symbols, ErrorRepor
|
||||
} while (false)
|
||||
|
||||
/* (directive | section | declaration)* END_OF_FILE */
|
||||
std::unique_ptr<ASTFile> Parser::file() {
|
||||
std::unique_ptr<ASTFile> Parser::compilationUnit() {
|
||||
fFile = std::make_unique<ASTFile>();
|
||||
CREATE_NODE(result, 0, ASTNode::Kind::kFile);
|
||||
fFile->fRoot = result;
|
||||
|
@ -91,7 +91,7 @@ public:
|
||||
* Consumes a complete .sksl file and returns the parse tree. Errors are reported via the
|
||||
* ErrorReporter; the return value may contain some declarations even when errors have occurred.
|
||||
*/
|
||||
std::unique_ptr<ASTFile> file();
|
||||
std::unique_ptr<ASTFile> compilationUnit();
|
||||
|
||||
StringFragment text(Token token);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user