blob: b0859020facf1fdf806e4647365ea3a9bcec2664 [file] [log] [blame]
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_COMPILER
#define SKSL_COMPILER
#include <set>
#include <unordered_set>
#include <vector>
#include "src/sksl/SkSLASTFile.h"
#include "src/sksl/SkSLAnalysis.h"
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLErrorReporter.h"
#include "src/sksl/SkSLInliner.h"
#include "src/sksl/ir/SkSLProgram.h"
#include "src/sksl/ir/SkSLSymbolTable.h"
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
#include "src/gpu/GrShaderVar.h"
#endif
#define SK_FRAGCOLOR_BUILTIN 10001
#define SK_IN_BUILTIN 10002
#define SK_OUT_BUILTIN 10007
#define SK_LASTFRAGCOLOR_BUILTIN 10008
#define SK_MAIN_COORDS_BUILTIN 10009
#define SK_INPUT_COLOR_BUILTIN 10010
#define SK_FRAGCOORD_BUILTIN 15
#define SK_CLOCKWISE_BUILTIN 17
#define SK_VERTEXID_BUILTIN 42
#define SK_INSTANCEID_BUILTIN 43
#define SK_INVOCATIONID_BUILTIN 8
#define SK_POSITION_BUILTIN 0
class SkBitSet;
class SkSLCompileBench;
namespace SkSL {
namespace dsl {
class DSLWriter;
}
class ExternalFunction;
class FunctionDeclaration;
class IRGenerator;
class IRIntrinsicMap;
class ProgramUsage;
struct LoadedModule {
ProgramKind fKind;
std::shared_ptr<SymbolTable> fSymbols;
std::vector<std::unique_ptr<ProgramElement>> fElements;
};
struct ParsedModule {
std::shared_ptr<SymbolTable> fSymbols;
std::shared_ptr<IRIntrinsicMap> fIntrinsics;
};
/**
* Main compiler entry point. This is a traditional compiler design which first parses the .sksl
* file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to
* produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce
* compiled output.
*
* See the README for information about SkSL.
*/
class SK_API Compiler : public ErrorReporter {
public:
static constexpr const char FRAGCOLOR_NAME[] = "sk_FragColor";
static constexpr const char RTADJUST_NAME[] = "sk_RTAdjust";
static constexpr const char PERVERTEX_NAME[] = "sk_PerVertex";
struct OptimizationContext {
// nodes we have already reported errors for and should not error on again
std::unordered_set<const IRNode*> fSilences;
// true if we have updated the CFG during this pass
bool fUpdated = false;
// true if we need to completely regenerate the CFG
bool fNeedsRescan = false;
// Metadata about function and variable usage within the program
ProgramUsage* fUsage = nullptr;
// Nodes which we can't throw away until the end of optimization
StatementArray fOwnedStatements;
};
Compiler(const ShaderCapsClass* caps);
~Compiler() override;
Compiler(const Compiler&) = delete;
Compiler& operator=(const Compiler&) = delete;
/**
* Allows optimization settings to be unilaterally overridden. This is meant to allow tools like
* Viewer or Nanobench to override the compiler's ProgramSettings and ShaderCaps for debugging.
*/
enum class OverrideFlag {
kDefault,
kOff,
kOn,
};
static void EnableOptimizer(OverrideFlag flag) { sOptimizer = flag; }
static void EnableInliner(OverrideFlag flag) { sInliner = flag; }
/**
* If externalFunctions is supplied, those values are registered in the symbol table of the
* Program, but ownership is *not* transferred. It is up to the caller to keep them alive.
*/
std::unique_ptr<Program> convertProgram(
ProgramKind kind,
String text,
const Program::Settings& settings,
const std::vector<std::unique_ptr<ExternalFunction>>* externalFunctions = nullptr);
bool toSPIRV(Program& program, OutputStream& out);
bool toSPIRV(Program& program, String* out);
bool toGLSL(Program& program, OutputStream& out);
bool toGLSL(Program& program, String* out);
bool toHLSL(Program& program, String* out);
bool toMetal(Program& program, OutputStream& out);
bool toMetal(Program& program, String* out);
#if defined(SKSL_STANDALONE) || GR_TEST_UTILS
bool toCPP(Program& program, String name, OutputStream& out);
bool toDSLCPP(Program& program, String name, OutputStream& out);
bool toH(Program& program, String name, OutputStream& out);
#endif
void error(int offset, String msg) override;
String errorText(bool showCount = true);
void writeErrorCount();
int errorCount() override {
return fErrorCount;
}
void setErrorCount(int c) override;
Context& context() {
return *fContext;
}
// When SKSL_STANDALONE, fPath is used. (fData, fSize) will be (nullptr, 0)
// When !SKSL_STANDALONE, fData and fSize are used. fPath will be nullptr.
struct ModuleData {
const char* fPath;
const uint8_t* fData;
size_t fSize;
};
static ModuleData MakeModulePath(const char* path) {
return ModuleData{path, /*fData=*/nullptr, /*fSize=*/0};
}
static ModuleData MakeModuleData(const uint8_t* data, size_t size) {
return ModuleData{/*fPath=*/nullptr, data, size};
}
LoadedModule loadModule(ProgramKind kind, ModuleData data, std::shared_ptr<SymbolTable> base,
bool dehydrate);
ParsedModule parseModule(ProgramKind kind, ModuleData data, const ParsedModule& base);
IRGenerator& irGenerator() {
return *fIRGenerator;
}
const ParsedModule& moduleForProgramKind(ProgramKind kind);
private:
const ParsedModule& loadGPUModule();
const ParsedModule& loadFragmentModule();
const ParsedModule& loadVertexModule();
const ParsedModule& loadFPModule();
const ParsedModule& loadGeometryModule();
const ParsedModule& loadPublicModule();
const ParsedModule& loadRuntimeColorFilterModule();
const ParsedModule& loadRuntimeShaderModule();
/** Verifies that @if and @switch statements were actually optimized away. */
void verifyStaticTests(const Program& program);
/** Optimize every function in the program. */
bool optimize(Program& program);
/** Optimize the module. */
bool optimize(LoadedModule& module);
/** Eliminates unused functions from a Program, according to the stats in ProgramUsage. */
bool removeDeadFunctions(Program& program, ProgramUsage* usage);
/** Eliminates unreferenced variables from a Program, according to the stats in ProgramUsage. */
bool removeDeadGlobalVariables(Program& program, ProgramUsage* usage);
bool removeDeadLocalVariables(Program& program, ProgramUsage* usage);
Position position(int offset);
std::shared_ptr<Context> fContext;
std::shared_ptr<SymbolTable> fRootSymbolTable;
std::shared_ptr<SymbolTable> fPrivateSymbolTable;
ParsedModule fRootModule; // Core types
ParsedModule fPrivateModule; // [Root] + Internal types
ParsedModule fGPUModule; // [Private] + GPU intrinsics, helper functions
ParsedModule fVertexModule; // [GPU] + Vertex stage decls
ParsedModule fFragmentModule; // [GPU] + Fragment stage decls
ParsedModule fGeometryModule; // [GPU] + Geometry stage decls
ParsedModule fFPModule; // [GPU] + FP features
ParsedModule fPublicModule; // [Root] + Public features
ParsedModule fRuntimeColorFilterModule; // [Public] + Runtime shader decls
ParsedModule fRuntimeShaderModule; // [Public] + Runtime color filter decls
// holds ModifiersPools belonging to the core includes for lifetime purposes
ModifiersPool fCoreModifiers;
Inliner fInliner;
std::unique_ptr<IRGenerator> fIRGenerator;
const String* fSource = nullptr;
int fErrorCount = 0;
String fErrorText;
std::vector<size_t> fErrorTextLength;
static OverrideFlag sOptimizer;
static OverrideFlag sInliner;
friend class AutoSource;
friend class ::SkSLCompileBench;
friend class dsl::DSLWriter;
};
} // namespace SkSL
#endif