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:
Ethan Nicholas 2020-11-05 11:27:31 -05:00 committed by Skia Commit-Bot
parent 64596c5c2b
commit a2d6b31f66
7 changed files with 130 additions and 26 deletions

View File

@ -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 = &caps;
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)

View File

@ -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

View File

@ -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) {

View File

@ -2993,7 +2993,7 @@ IRGenerator::IRBundle IRGenerator::convertProgram(
}
Parser parser(text, length, *fSymbolTable, fErrors);
fFile = parser.file();
fFile = parser.compilationUnit();
if (fErrors.errorCount()) {
return {};
}

View File

@ -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);

View File

@ -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;

View File

@ -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);