blob: 4cdec81838536807d11b8f1cb088cfebfaeafd5c [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>
Brian Osman010ce6a2020-10-19 16:34:10 -040014#include "src/sksl/SkSLAnalysis.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/sksl/SkSLContext.h"
John Stiles7b463002020-08-31 17:29:21 -040016#include "src/sksl/SkSLInliner.h"
Ethan Nicholas55a63af2021-05-18 10:12:58 -040017#include "src/sksl/SkSLParsedModule.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/sksl/ir/SkSLProgram.h"
19#include "src/sksl/ir/SkSLSymbolTable.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070020
Brian Osman2e29ab52019-09-20 12:19:11 -040021#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
22#include "src/gpu/GrShaderVar.h"
23#endif
24
Ethan Nicholas762466e2017-06-29 10:03:38 -040025#define SK_FRAGCOLOR_BUILTIN 10001
Ethan Nicholaseab2baa2018-04-13 15:16:27 -040026#define SK_LASTFRAGCOLOR_BUILTIN 10008
Brian Osman7353dc52020-02-07 13:37:12 -050027#define SK_MAIN_COORDS_BUILTIN 10009
Brian Osman577c6062021-04-12 17:17:19 -040028#define SK_INPUT_COLOR_BUILTIN 10010
John Stiles50d0d092021-06-09 17:24:31 -040029#define SK_DEST_COLOR_BUILTIN 10011
Ethan Nicholas762466e2017-06-29 10:03:38 -040030#define SK_FRAGCOORD_BUILTIN 15
Chris Dalton49d14e92018-07-27 12:38:35 -060031#define SK_CLOCKWISE_BUILTIN 17
Ethan Nicholas9eded2c2018-03-22 10:10:44 -040032#define SK_VERTEXID_BUILTIN 42
33#define SK_INSTANCEID_BUILTIN 43
Ethan Nicholascc305772017-10-13 16:17:45 -040034#define SK_POSITION_BUILTIN 0
ethannicholas5961bc92016-10-12 06:39:56 -070035
John Stilese6150002020-10-05 12:03:53 -040036class SkBitSet;
Ethan Nicholasba9a04f2020-11-06 09:28:04 -050037class SkSLCompileBench;
John Stilese6150002020-10-05 12:03:53 -040038
ethannicholasb3058bd2016-07-01 08:22:01 -070039namespace SkSL {
40
Ethan Nicholas95046142021-01-07 10:57:27 -050041namespace dsl {
Ethan Nicholas4f3e6a22021-06-15 09:17:05 -040042 class DSLCore;
Ethan Nicholas95046142021-01-07 10:57:27 -050043 class DSLWriter;
44}
45
Brian Osmanbe0b3b72021-01-06 14:27:35 -050046class ExternalFunction;
Brian Osman4fca9952021-01-28 15:04:51 -050047class FunctionDeclaration;
ethannicholasb3058bd2016-07-01 08:22:01 -070048class IRGenerator;
Brian Osman010ce6a2020-10-19 16:34:10 -040049class ProgramUsage;
ethannicholasb3058bd2016-07-01 08:22:01 -070050
Brian Osman3d87e9f2020-10-08 11:50:22 -040051struct LoadedModule {
John Stilesdbd4e6f2021-02-16 13:29:15 -050052 ProgramKind fKind;
Brian Osman3d87e9f2020-10-08 11:50:22 -040053 std::shared_ptr<SymbolTable> fSymbols;
54 std::vector<std::unique_ptr<ProgramElement>> fElements;
55};
56
ethannicholasb3058bd2016-07-01 08:22:01 -070057/**
58 * Main compiler entry point. This is a traditional compiler design which first parses the .sksl
Ethan Nicholas941e7e22016-12-12 15:33:30 -050059 * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to
ethannicholasb3058bd2016-07-01 08:22:01 -070060 * produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce
61 * compiled output.
ethannicholas5961bc92016-10-12 06:39:56 -070062 *
63 * See the README for information about SkSL.
ethannicholasb3058bd2016-07-01 08:22:01 -070064 */
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -040065class SK_API Compiler {
ethannicholasb3058bd2016-07-01 08:22:01 -070066public:
Brian Salomon3e2fe2b2021-06-02 09:16:30 -040067 static constexpr const char FRAGCOLOR_NAME[] = "sk_FragColor";
John Stilese67bd132021-03-19 18:39:25 -040068 static constexpr const char RTADJUST_NAME[] = "sk_RTAdjust";
69 static constexpr const char PERVERTEX_NAME[] = "sk_PerVertex";
Ethan Nicholas549c6b82021-06-25 12:31:44 -040070 static constexpr const char POISON_TAG[] = "<POISON>";
Robert Phillipsfe8da172018-01-24 14:52:02 +000071
Brian Salomon3e2fe2b2021-06-02 09:16:30 -040072 /**
73 * Gets a float4 that adjusts the position from Skia device coords to normalized device coords,
74 * used to populate sk_RTAdjust. Assuming the transformed position, pos, is a homogeneous
75 * float4, the vec, v, is applied as such:
76 * float4((pos.xy * v.xz) + sk_Position.ww * v.yw, 0, pos.w);
77 */
78 static std::array<float, 4> GetRTAdjustVector(SkISize rtDims, bool flipY) {
79 std::array<float, 4> result;
80 result[0] = 2.f/rtDims.width();
81 result[2] = 2.f/rtDims.height();
82 result[1] = -1.f;
83 result[3] = -1.f;
84 if (flipY) {
85 result[2] = -result[2];
86 result[3] = -result[3];
87 }
88 return result;
89 }
90
Brian Salomond8d85b92021-07-07 09:41:17 -040091 /**
92 * Uniform values by the compiler to implement origin-neutral dFdy, sk_Clockwise, and
93 * sk_FragCoord.
94 */
95 static std::array<float, 2> GetRTFlipVector(int rtHeight, bool flipY) {
96 std::array<float, 2> result;
97 result[0] = flipY ? rtHeight : 0.f;
98 result[1] = flipY ? -1.f : 1.f;
99 return result;
100 }
101
Ethan Nicholascdeae8c2020-10-22 14:39:46 -0400102 struct OptimizationContext {
103 // nodes we have already reported errors for and should not error on again
104 std::unordered_set<const IRNode*> fSilences;
105 // true if we have updated the CFG during this pass
106 bool fUpdated = false;
107 // true if we need to completely regenerate the CFG
108 bool fNeedsRescan = false;
Brian Osman010ce6a2020-10-19 16:34:10 -0400109 // Metadata about function and variable usage within the program
110 ProgramUsage* fUsage = nullptr;
Ethan Nicholas5b9b0db2021-01-21 13:12:01 -0500111 // Nodes which we can't throw away until the end of optimization
112 StatementArray fOwnedStatements;
Ethan Nicholascdeae8c2020-10-22 14:39:46 -0400113 };
114
John Stilesd6a5f4492021-02-11 15:46:11 -0500115 Compiler(const ShaderCapsClass* caps);
ethannicholasb3058bd2016-07-01 08:22:01 -0700116
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400117 ~Compiler();
ethannicholasb3058bd2016-07-01 08:22:01 -0700118
Brian Osman14003822019-04-10 11:47:26 -0400119 Compiler(const Compiler&) = delete;
120 Compiler& operator=(const Compiler&) = delete;
121
Ethan Nicholas91164d12019-05-15 15:29:54 -0400122 /**
John Stiles2ee4d7a2021-03-30 10:30:47 -0400123 * Allows optimization settings to be unilaterally overridden. This is meant to allow tools like
124 * Viewer or Nanobench to override the compiler's ProgramSettings and ShaderCaps for debugging.
125 */
126 enum class OverrideFlag {
127 kDefault,
128 kOff,
129 kOn,
130 };
131 static void EnableOptimizer(OverrideFlag flag) { sOptimizer = flag; }
132 static void EnableInliner(OverrideFlag flag) { sInliner = flag; }
133
134 /**
Ethan Nicholas55a63af2021-05-18 10:12:58 -0400135 * If fExternalFunctions is supplied in the settings, those values are registered in the symbol
136 * table of the Program, but ownership is *not* transferred. It is up to the caller to keep them
137 * alive.
Ethan Nicholas91164d12019-05-15 15:29:54 -0400138 */
Brian Osman32d53552020-09-23 13:55:20 -0400139 std::unique_ptr<Program> convertProgram(
John Stilesdbd4e6f2021-02-16 13:29:15 -0500140 ProgramKind kind,
Brian Osman32d53552020-09-23 13:55:20 -0400141 String text,
Ethan Nicholas55a63af2021-05-18 10:12:58 -0400142 Program::Settings settings);
ethannicholasb3058bd2016-07-01 08:22:01 -0700143
Ethan Nicholas00543112018-07-31 09:44:36 -0400144 bool toSPIRV(Program& program, OutputStream& out);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500145
Ethan Nicholas00543112018-07-31 09:44:36 -0400146 bool toSPIRV(Program& program, String* out);
ethannicholasb3058bd2016-07-01 08:22:01 -0700147
Ethan Nicholas00543112018-07-31 09:44:36 -0400148 bool toGLSL(Program& program, OutputStream& out);
Ethan Nicholascc305772017-10-13 16:17:45 -0400149
Ethan Nicholas00543112018-07-31 09:44:36 -0400150 bool toGLSL(Program& program, String* out);
Timothy Liangb8eeb802018-07-23 16:46:16 -0400151
Brian Osmanc0243912020-02-19 15:35:26 -0500152 bool toHLSL(Program& program, String* out);
153
Ethan Nicholas00543112018-07-31 09:44:36 -0400154 bool toMetal(Program& program, OutputStream& out);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400155
Ethan Nicholas00543112018-07-31 09:44:36 -0400156 bool toMetal(Program& program, String* out);
157
Ethan Nicholas32724122021-09-07 13:49:07 -0400158 void handleError(skstd::string_view msg, PositionInfo pos);
ethannicholasb3058bd2016-07-01 08:22:01 -0700159
Ethan Nicholas95046142021-01-07 10:57:27 -0500160 String errorText(bool showCount = true);
ethannicholasb3058bd2016-07-01 08:22:01 -0700161
Ethan Nicholas39f6da42021-08-23 13:10:07 -0400162 ErrorReporter& errorReporter() { return *fContext->fErrors; }
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400163
Ethan Nicholas39f6da42021-08-23 13:10:07 -0400164 int errorCount() const { return fContext->fErrors->errorCount(); }
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400165
ethannicholasb3058bd2016-07-01 08:22:01 -0700166 void writeErrorCount();
167
Ethan Nicholas55478662021-08-10 17:14:26 -0400168 void resetErrors() {
169 fErrorText.clear();
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400170 this->errorReporter().resetErrorCount();
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500171 }
172
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400173 Context& context() {
174 return *fContext;
175 }
176
Brian Osman3d87e9f2020-10-08 11:50:22 -0400177 // When SKSL_STANDALONE, fPath is used. (fData, fSize) will be (nullptr, 0)
178 // When !SKSL_STANDALONE, fData and fSize are used. fPath will be nullptr.
179 struct ModuleData {
180 const char* fPath;
181
182 const uint8_t* fData;
183 size_t fSize;
184 };
185
186 static ModuleData MakeModulePath(const char* path) {
187 return ModuleData{path, /*fData=*/nullptr, /*fSize=*/0};
188 }
189 static ModuleData MakeModuleData(const uint8_t* data, size_t size) {
190 return ModuleData{/*fPath=*/nullptr, data, size};
191 }
192
John Stilesa935c3f2021-02-25 10:35:49 -0500193 LoadedModule loadModule(ProgramKind kind, ModuleData data, std::shared_ptr<SymbolTable> base,
194 bool dehydrate);
John Stilesdbd4e6f2021-02-16 13:29:15 -0500195 ParsedModule parseModule(ProgramKind kind, ModuleData data, const ParsedModule& base);
Ethan Nicholas8da1e652019-05-24 11:01:59 -0400196
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500197 IRGenerator& irGenerator() {
198 return *fIRGenerator;
199 }
200
John Stilesdbd4e6f2021-02-16 13:29:15 -0500201 const ParsedModule& moduleForProgramKind(ProgramKind kind);
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500202
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400203private:
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400204 class CompilerErrorReporter : public ErrorReporter {
205 public:
206 CompilerErrorReporter(Compiler* compiler)
207 : fCompiler(*compiler) {}
208
Ethan Nicholas32724122021-09-07 13:49:07 -0400209 void handleError(skstd::string_view msg, PositionInfo pos) override {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400210 fCompiler.handleError(msg, pos);
211 }
212
213 private:
214 Compiler& fCompiler;
215 };
216
Brian Osman56269982020-11-20 12:38:07 -0500217 const ParsedModule& loadGPUModule();
218 const ParsedModule& loadFragmentModule();
219 const ParsedModule& loadVertexModule();
Brian Osmanb06301e2020-11-06 11:45:36 -0500220 const ParsedModule& loadPublicModule();
Brian Osmancbb60bd2021-04-12 09:49:20 -0400221 const ParsedModule& loadRuntimeShaderModule();
Brian Osman88cda172020-10-09 12:05:16 -0400222
John Stilesb624b722021-08-13 12:16:13 -0400223 std::shared_ptr<SymbolTable> makeRootSymbolTable();
224 std::shared_ptr<SymbolTable> makePrivateSymbolTable(std::shared_ptr<SymbolTable> parent);
225
John Stiles0bfeae62021-03-11 09:09:42 -0500226 /** Optimize every function in the program. */
Ethan Nicholas34b19c52020-09-14 11:33:47 -0400227 bool optimize(Program& program);
228
John Stiles2ecc5952021-09-01 14:41:36 -0400229 /** Performs final checks to confirm that a fully-assembled/optimized is valid. */
230 bool finalize(Program& program);
231
John Stiles0bfeae62021-03-11 09:09:42 -0500232 /** Optimize the module. */
Brian Osman0006ad02020-11-18 15:38:39 -0500233 bool optimize(LoadedModule& module);
234
John Stiles3ff77f42021-09-06 22:17:58 -0400235 /** Flattens out function calls when it is safe to do so. */
236 bool runInliner(const std::vector<std::unique_ptr<ProgramElement>>& elements,
237 std::shared_ptr<SymbolTable> symbols,
238 ProgramUsage* usage);
239
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400240 CompilerErrorReporter fErrorReporter;
Brian Osman0006ad02020-11-18 15:38:39 -0500241 std::shared_ptr<Context> fContext;
Brian Osmand7e76592020-11-02 12:26:22 -0500242
Brian Osmancbb60bd2021-04-12 09:49:20 -0400243 ParsedModule fRootModule; // Core types
Brian Osmanb06301e2020-11-06 11:45:36 -0500244
Brian Osmancbb60bd2021-04-12 09:49:20 -0400245 ParsedModule fPrivateModule; // [Root] + Internal types
246 ParsedModule fGPUModule; // [Private] + GPU intrinsics, helper functions
247 ParsedModule fVertexModule; // [GPU] + Vertex stage decls
248 ParsedModule fFragmentModule; // [GPU] + Fragment stage decls
Brian Osmanb06301e2020-11-06 11:45:36 -0500249
Brian Osmancbb60bd2021-04-12 09:49:20 -0400250 ParsedModule fPublicModule; // [Root] + Public features
Brian Osmana8b897b2021-08-30 16:40:44 -0400251 ParsedModule fRuntimeShaderModule; // [Public] + Runtime shader decls
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400252
Ethan Nicholas041fd0a2020-10-07 16:42:04 -0400253 // holds ModifiersPools belonging to the core includes for lifetime purposes
John Stilesa47b3512021-05-04 16:15:00 -0400254 ModifiersPool fCoreModifiers;
Ethan Nicholas041fd0a2020-10-07 16:42:04 -0400255
John Stiles2dda4b62021-09-16 13:18:10 -0400256 Mangler fMangler;
John Stiles7b463002020-08-31 17:29:21 -0400257 Inliner fInliner;
John Stiles656427a2020-08-27 15:26:26 -0400258 std::unique_ptr<IRGenerator> fIRGenerator;
ethannicholasb3058bd2016-07-01 08:22:01 -0700259
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400260 String fErrorText;
Brian Osman88cda172020-10-09 12:05:16 -0400261
John Stiles2ee4d7a2021-03-30 10:30:47 -0400262 static OverrideFlag sOptimizer;
263 static OverrideFlag sInliner;
264
Brian Osman88cda172020-10-09 12:05:16 -0400265 friend class AutoSource;
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500266 friend class ::SkSLCompileBench;
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -0400267 friend class DSLParser;
Ethan Nicholasc8452722021-10-07 10:47:32 -0400268 friend class ThreadContext;
Ethan Nicholas4f3e6a22021-06-15 09:17:05 -0400269 friend class dsl::DSLCore;
ethannicholasb3058bd2016-07-01 08:22:01 -0700270};
271
John Stilesa6841be2020-08-06 14:11:56 -0400272} // namespace SkSL
ethannicholasb3058bd2016-07-01 08:22:01 -0700273
274#endif