blob: 0b4b249f8cc1ce13162df443ea77375de1b385eb [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
Ethan Nicholas0df1b042017-03-31 13:56:23 -04007
ethannicholasb3058bd2016-07-01 08:22:01 -07008#ifndef SKSL_COMPILER
9#define SKSL_COMPILER
10
ethannicholas22f939e2016-10-13 13:25:34 -070011#include <set>
Ethan Nicholascb670962017-04-20 19:31:52 -040012#include <unordered_set>
ethannicholasb3058bd2016-07-01 08:22:01 -070013#include <vector>
Ethan Nicholasdb80f692019-11-22 14:06:12 -050014#include "src/sksl/SkSLASTFile.h"
Brian Osman010ce6a2020-10-19 16:34:10 -040015#include "src/sksl/SkSLAnalysis.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/sksl/SkSLCFGGenerator.h"
17#include "src/sksl/SkSLContext.h"
18#include "src/sksl/SkSLErrorReporter.h"
John Stiles7b463002020-08-31 17:29:21 -040019#include "src/sksl/SkSLInliner.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/sksl/SkSLLexer.h"
21#include "src/sksl/ir/SkSLProgram.h"
22#include "src/sksl/ir/SkSLSymbolTable.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070023
Brian Osman2e29ab52019-09-20 12:19:11 -040024#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
25#include "src/gpu/GrShaderVar.h"
26#endif
27
Ethan Nicholas762466e2017-06-29 10:03:38 -040028#define SK_FRAGCOLOR_BUILTIN 10001
29#define SK_IN_BUILTIN 10002
Ethan Nicholas16c11962018-03-16 12:20:54 -040030#define SK_OUT_BUILTIN 10007
Ethan Nicholaseab2baa2018-04-13 15:16:27 -040031#define SK_LASTFRAGCOLOR_BUILTIN 10008
Brian Osman7353dc52020-02-07 13:37:12 -050032#define SK_MAIN_COORDS_BUILTIN 10009
Ethan Nicholascd700e92018-08-24 16:43:57 -040033#define SK_WIDTH_BUILTIN 10011
34#define SK_HEIGHT_BUILTIN 10012
Ethan Nicholas762466e2017-06-29 10:03:38 -040035#define SK_FRAGCOORD_BUILTIN 15
Chris Dalton49d14e92018-07-27 12:38:35 -060036#define SK_CLOCKWISE_BUILTIN 17
Chris Daltonb0fd4b12019-10-29 13:41:22 -060037#define SK_SAMPLEMASK_BUILTIN 20
Ethan Nicholas9eded2c2018-03-22 10:10:44 -040038#define SK_VERTEXID_BUILTIN 42
39#define SK_INSTANCEID_BUILTIN 43
Ethan Nicholas762466e2017-06-29 10:03:38 -040040#define SK_INVOCATIONID_BUILTIN 8
Ethan Nicholascc305772017-10-13 16:17:45 -040041#define SK_POSITION_BUILTIN 0
ethannicholas5961bc92016-10-12 06:39:56 -070042
John Stilese6150002020-10-05 12:03:53 -040043class SkBitSet;
Ethan Nicholasba9a04f2020-11-06 09:28:04 -050044class SkSLCompileBench;
John Stilese6150002020-10-05 12:03:53 -040045
ethannicholasb3058bd2016-07-01 08:22:01 -070046namespace SkSL {
47
Ethan Nicholas95046142021-01-07 10:57:27 -050048namespace dsl {
49 class DSLWriter;
50}
51
Brian Osmanbe0b3b72021-01-06 14:27:35 -050052class ExternalFunction;
ethannicholasb3058bd2016-07-01 08:22:01 -070053class IRGenerator;
Brian Osman2b469eb2020-09-21 11:32:10 -040054class IRIntrinsicMap;
Brian Osman107c6662019-12-30 15:02:30 -050055struct PipelineStageArgs;
Brian Osman010ce6a2020-10-19 16:34:10 -040056class ProgramUsage;
ethannicholasb3058bd2016-07-01 08:22:01 -070057
Brian Osman3d87e9f2020-10-08 11:50:22 -040058struct LoadedModule {
Brian Osman0006ad02020-11-18 15:38:39 -050059 Program::Kind fKind;
Brian Osman3d87e9f2020-10-08 11:50:22 -040060 std::shared_ptr<SymbolTable> fSymbols;
61 std::vector<std::unique_ptr<ProgramElement>> fElements;
62};
63
64struct ParsedModule {
65 std::shared_ptr<SymbolTable> fSymbols;
66 std::shared_ptr<IRIntrinsicMap> fIntrinsics;
67};
68
ethannicholasb3058bd2016-07-01 08:22:01 -070069/**
70 * Main compiler entry point. This is a traditional compiler design which first parses the .sksl
Ethan Nicholas941e7e22016-12-12 15:33:30 -050071 * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to
ethannicholasb3058bd2016-07-01 08:22:01 -070072 * produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce
73 * compiled output.
ethannicholas5961bc92016-10-12 06:39:56 -070074 *
75 * See the README for information about SkSL.
ethannicholasb3058bd2016-07-01 08:22:01 -070076 */
Ethan Nicholas4100b7c2019-03-12 11:50:48 -040077class SK_API Compiler : public ErrorReporter {
ethannicholasb3058bd2016-07-01 08:22:01 -070078public:
Robert Phillipsfe8da172018-01-24 14:52:02 +000079 static constexpr const char* RTADJUST_NAME = "sk_RTAdjust";
80 static constexpr const char* PERVERTEX_NAME = "sk_PerVertex";
81
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -040082 enum Flags {
83 kNone_Flags = 0,
84 // permits static if/switch statements to be used with non-constant tests. This is used when
85 // producing H and CPP code; the static tests don't have to have constant values *yet*, but
86 // the generated code will contain a static test which then does have to be a constant.
87 kPermitInvalidStaticTests_Flag = 1,
88 };
89
Brian Osmanac9d3f62020-06-25 11:07:30 -040090 // An invalid (otherwise unused) character to mark where FormatArgs are inserted
91 static constexpr char kFormatArgPlaceholder = '\001';
92 static constexpr const char* kFormatArgPlaceholderStr = "\001";
93
Ethan Nicholasce008112018-08-30 09:19:50 -040094 struct FormatArg {
95 enum class Kind {
Brian Osman7353dc52020-02-07 13:37:12 -050096 kCoords,
Ethan Nicholasce008112018-08-30 09:19:50 -040097 kUniform,
Brian Osman2e29ab52019-09-20 12:19:11 -040098 kChildProcessor,
Brian Osmanbe1b8372020-06-18 13:40:26 -040099 kChildProcessorWithMatrix,
Brian Osman2e29ab52019-09-20 12:19:11 -0400100 kFunctionName
Ethan Nicholasce008112018-08-30 09:19:50 -0400101 };
102
103 FormatArg(Kind kind)
104 : fKind(kind) {}
105
106 FormatArg(Kind kind, int index)
107 : fKind(kind)
108 , fIndex(index) {}
109
110 Kind fKind;
Ethan Nicholasce008112018-08-30 09:19:50 -0400111 int fIndex;
Brian Osman87e3bef2020-01-27 16:21:34 -0500112 String fCoords;
Ethan Nicholas00543112018-07-31 09:44:36 -0400113 };
114
Ethan Nicholascdeae8c2020-10-22 14:39:46 -0400115 struct OptimizationContext {
116 // nodes we have already reported errors for and should not error on again
117 std::unordered_set<const IRNode*> fSilences;
118 // true if we have updated the CFG during this pass
119 bool fUpdated = false;
120 // true if we need to completely regenerate the CFG
121 bool fNeedsRescan = false;
Brian Osman010ce6a2020-10-19 16:34:10 -0400122 // Metadata about function and variable usage within the program
123 ProgramUsage* fUsage = nullptr;
Ethan Nicholas5b9b0db2021-01-21 13:12:01 -0500124 // Nodes which we can't throw away until the end of optimization
125 StatementArray fOwnedStatements;
Ethan Nicholascdeae8c2020-10-22 14:39:46 -0400126 };
127
Brian Osman2e29ab52019-09-20 12:19:11 -0400128#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
129 /**
130 * Represents the arguments to GrGLSLShaderBuilder::emitFunction.
131 */
132 struct GLSLFunction {
133 GrSLType fReturnType;
134 SkString fName;
135 std::vector<GrShaderVar> fParameters;
Brian Osmanac9d3f62020-06-25 11:07:30 -0400136 String fBody;
Ethan Nicholasfc671ad2019-11-21 11:14:11 -0500137 std::vector<Compiler::FormatArg> fFormatArgs;
Brian Osman2e29ab52019-09-20 12:19:11 -0400138 };
139#endif
140
Brian Osmand7e76592020-11-02 12:26:22 -0500141 Compiler(const ShaderCapsClass* caps, Flags flags = kNone_Flags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700142
Brian Salomond3b65972017-03-22 12:05:03 -0400143 ~Compiler() override;
ethannicholasb3058bd2016-07-01 08:22:01 -0700144
Brian Osman14003822019-04-10 11:47:26 -0400145 Compiler(const Compiler&) = delete;
146 Compiler& operator=(const Compiler&) = delete;
147
Ethan Nicholas91164d12019-05-15 15:29:54 -0400148 /**
Brian Osmanbe0b3b72021-01-06 14:27:35 -0500149 * If externalFunctions is supplied, those values are registered in the symbol table of the
Brian Osman32d53552020-09-23 13:55:20 -0400150 * Program, but ownership is *not* transferred. It is up to the caller to keep them alive.
Ethan Nicholas91164d12019-05-15 15:29:54 -0400151 */
Brian Osman32d53552020-09-23 13:55:20 -0400152 std::unique_ptr<Program> convertProgram(
153 Program::Kind kind,
154 String text,
155 const Program::Settings& settings,
Brian Osmanbe0b3b72021-01-06 14:27:35 -0500156 const std::vector<std::unique_ptr<ExternalFunction>>* externalFunctions = nullptr);
ethannicholasb3058bd2016-07-01 08:22:01 -0700157
Ethan Nicholas00543112018-07-31 09:44:36 -0400158 bool toSPIRV(Program& program, OutputStream& out);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500159
Ethan Nicholas00543112018-07-31 09:44:36 -0400160 bool toSPIRV(Program& program, String* out);
ethannicholasb3058bd2016-07-01 08:22:01 -0700161
Ethan Nicholas00543112018-07-31 09:44:36 -0400162 bool toGLSL(Program& program, OutputStream& out);
Ethan Nicholascc305772017-10-13 16:17:45 -0400163
Ethan Nicholas00543112018-07-31 09:44:36 -0400164 bool toGLSL(Program& program, String* out);
Timothy Liangb8eeb802018-07-23 16:46:16 -0400165
Brian Osmanc0243912020-02-19 15:35:26 -0500166 bool toHLSL(Program& program, String* out);
167
Ethan Nicholas00543112018-07-31 09:44:36 -0400168 bool toMetal(Program& program, OutputStream& out);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400169
Ethan Nicholas00543112018-07-31 09:44:36 -0400170 bool toMetal(Program& program, String* out);
171
Greg Daniela28ea672020-09-25 11:12:56 -0400172#if defined(SKSL_STANDALONE) || GR_TEST_UTILS
Ethan Nicholas00543112018-07-31 09:44:36 -0400173 bool toCPP(Program& program, String name, OutputStream& out);
174
175 bool toH(Program& program, String name, OutputStream& out);
Ethan Nicholas2a479a52020-08-18 16:29:45 -0400176#endif
Ethan Nicholas00543112018-07-31 09:44:36 -0400177
Brian Osman2e29ab52019-09-20 12:19:11 -0400178#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
Brian Osmana4b91692020-08-10 14:26:16 -0400179 bool toPipelineStage(Program& program, PipelineStageArgs* outArgs);
Brian Osman2e29ab52019-09-20 12:19:11 -0400180#endif
Ethan Nicholas762466e2017-06-29 10:03:38 -0400181
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700182 void error(int offset, String msg) override;
ethannicholasb3058bd2016-07-01 08:22:01 -0700183
Ethan Nicholas95046142021-01-07 10:57:27 -0500184 String errorText(bool showCount = true);
ethannicholasb3058bd2016-07-01 08:22:01 -0700185
186 void writeErrorCount();
187
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500188 int errorCount() override {
189 return fErrorCount;
190 }
191
John Stiles8d3642e2021-01-22 09:50:04 -0500192 void setErrorCount(int c) override;
193
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400194 Context& context() {
195 return *fContext;
196 }
197
Brian Osman401a0092020-09-10 14:47:24 -0400198 static const char* OperatorName(Token::Kind op);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700199
Brian Osman401a0092020-09-10 14:47:24 -0400200 // Returns true if op is '=' or any compound assignment operator ('+=', '-=', etc.)
201 static bool IsAssignment(Token::Kind op);
202
203 // Given a compound assignment operator, returns the non-assignment version of the operator
204 // (e.g. '+=' becomes '+')
205 static Token::Kind RemoveAssignment(Token::Kind op);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700206
Brian Osman3d87e9f2020-10-08 11:50:22 -0400207 // When SKSL_STANDALONE, fPath is used. (fData, fSize) will be (nullptr, 0)
208 // When !SKSL_STANDALONE, fData and fSize are used. fPath will be nullptr.
209 struct ModuleData {
210 const char* fPath;
211
212 const uint8_t* fData;
213 size_t fSize;
214 };
215
216 static ModuleData MakeModulePath(const char* path) {
217 return ModuleData{path, /*fData=*/nullptr, /*fSize=*/0};
218 }
219 static ModuleData MakeModuleData(const uint8_t* data, size_t size) {
220 return ModuleData{/*fPath=*/nullptr, data, size};
221 }
222
223 LoadedModule loadModule(Program::Kind kind, ModuleData data, std::shared_ptr<SymbolTable> base);
224 ParsedModule parseModule(Program::Kind kind, ModuleData data, const ParsedModule& base);
Ethan Nicholas8da1e652019-05-24 11:01:59 -0400225
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500226 IRGenerator& irGenerator() {
227 return *fIRGenerator;
228 }
229
230 const ParsedModule& moduleForProgramKind(Program::Kind kind);
231
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400232private:
Brian Osman56269982020-11-20 12:38:07 -0500233 const ParsedModule& loadGPUModule();
234 const ParsedModule& loadFragmentModule();
235 const ParsedModule& loadVertexModule();
Brian Osman88cda172020-10-09 12:05:16 -0400236 const ParsedModule& loadFPModule();
237 const ParsedModule& loadGeometryModule();
Brian Osmanb06301e2020-11-06 11:45:36 -0500238 const ParsedModule& loadPublicModule();
Brian Osman91946752020-12-21 13:20:40 -0500239 const ParsedModule& loadRuntimeEffectModule();
Brian Osman88cda172020-10-09 12:05:16 -0400240
Ethan Nicholas86a43402017-01-19 13:32:00 -0500241 void addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
242 DefinitionMap* definitions);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500243 void addDefinitions(const BasicBlock::Node& node, DefinitionMap* definitions);
ethannicholas22f939e2016-10-13 13:25:34 -0700244
John Stilese6150002020-10-05 12:03:53 -0400245 void scanCFG(CFG* cfg, BlockId block, SkBitSet* processedSet);
Ethan Nicholascb670962017-04-20 19:31:52 -0400246 void computeDataFlow(CFG* cfg);
247
248 /**
249 * Simplifies the expression pointed to by iter (in both the IR and CFG structures), if
250 * possible.
251 */
252 void simplifyExpression(DefinitionMap& definitions,
253 BasicBlock& b,
254 std::vector<BasicBlock::Node>::iterator* iter,
Ethan Nicholascdeae8c2020-10-22 14:39:46 -0400255 OptimizationContext* context);
Ethan Nicholascb670962017-04-20 19:31:52 -0400256
257 /**
258 * Simplifies the statement pointed to by iter (in both the IR and CFG structures), if
259 * possible.
260 */
261 void simplifyStatement(DefinitionMap& definitions,
262 BasicBlock& b,
263 std::vector<BasicBlock::Node>::iterator* iter,
Ethan Nicholascdeae8c2020-10-22 14:39:46 -0400264 OptimizationContext* context);
Ethan Nicholascb670962017-04-20 19:31:52 -0400265
John Stiles0cc193a2020-09-09 09:39:34 -0400266 /**
267 * Optimizes a function based on control flow analysis. Returns true if changes were made.
268 */
Brian Osman010ce6a2020-10-19 16:34:10 -0400269 bool scanCFG(FunctionDefinition& f, ProgramUsage* usage);
ethannicholasb3058bd2016-07-01 08:22:01 -0700270
Ethan Nicholas34b19c52020-09-14 11:33:47 -0400271 /**
272 * Optimize every function in the program.
273 */
274 bool optimize(Program& program);
275
Brian Osman0006ad02020-11-18 15:38:39 -0500276 bool optimize(LoadedModule& module);
277
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700278 Position position(int offset);
279
Brian Osman0006ad02020-11-18 15:38:39 -0500280 std::shared_ptr<Context> fContext;
Brian Osmand7e76592020-11-02 12:26:22 -0500281 const ShaderCapsClass* fCaps = nullptr;
282
Brian Osmaneac49832020-09-18 11:49:22 -0400283 std::shared_ptr<SymbolTable> fRootSymbolTable;
Brian Osmanb06301e2020-11-06 11:45:36 -0500284 std::shared_ptr<SymbolTable> fPrivateSymbolTable;
Brian Osman2b469eb2020-09-21 11:32:10 -0400285
Brian Osman91946752020-12-21 13:20:40 -0500286 ParsedModule fRootModule; // Core types
Brian Osmanb06301e2020-11-06 11:45:36 -0500287
Brian Osman91946752020-12-21 13:20:40 -0500288 ParsedModule fPrivateModule; // [Root] + Internal types
289 ParsedModule fGPUModule; // [Private] + GPU intrinsics, helper functions
290 ParsedModule fVertexModule; // [GPU] + Vertex stage decls
291 ParsedModule fFragmentModule; // [GPU] + Fragment stage decls
292 ParsedModule fGeometryModule; // [GPU] + Geometry stage decls
293 ParsedModule fFPModule; // [GPU] + FP features
Brian Osmanb06301e2020-11-06 11:45:36 -0500294
Brian Osman91946752020-12-21 13:20:40 -0500295 ParsedModule fPublicModule; // [Root] + Public features
Brian Osman91946752020-12-21 13:20:40 -0500296 ParsedModule fRuntimeEffectModule; // [Public] + Runtime effect decls
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400297
Ethan Nicholas041fd0a2020-10-07 16:42:04 -0400298 // holds ModifiersPools belonging to the core includes for lifetime purposes
299 std::vector<std::unique_ptr<ModifiersPool>> fModifiers;
300
John Stiles7b463002020-08-31 17:29:21 -0400301 Inliner fInliner;
John Stiles656427a2020-08-27 15:26:26 -0400302 std::unique_ptr<IRGenerator> fIRGenerator;
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -0400303 int fFlags;
ethannicholasb3058bd2016-07-01 08:22:01 -0700304
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700305 const String* fSource;
ethannicholasb3058bd2016-07-01 08:22:01 -0700306 int fErrorCount;
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400307 String fErrorText;
John Stiles8d3642e2021-01-22 09:50:04 -0500308 std::vector<size_t> fErrorTextLength;
Brian Osman88cda172020-10-09 12:05:16 -0400309
310 friend class AutoSource;
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500311 friend class ::SkSLCompileBench;
Ethan Nicholas95046142021-01-07 10:57:27 -0500312 friend class dsl::DSLWriter;
ethannicholasb3058bd2016-07-01 08:22:01 -0700313};
314
Brian Osman107c6662019-12-30 15:02:30 -0500315#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
316struct PipelineStageArgs {
317 String fCode;
318 std::vector<Compiler::FormatArg> fFormatArgs;
319 std::vector<Compiler::GLSLFunction> fFunctions;
320};
321#endif
322
John Stilesa6841be2020-08-06 14:11:56 -0400323} // namespace SkSL
ethannicholasb3058bd2016-07-01 08:22:01 -0700324
325#endif