blob: a9dfe2f7257c793eb8b48bd93e1669cc306811f8 [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/SkSLContext.h"
John Stiles7b463002020-08-31 17:29:21 -040017#include "src/sksl/SkSLInliner.h"
Ethan Nicholas55a63af2021-05-18 10:12:58 -040018#include "src/sksl/SkSLParsedModule.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "src/sksl/ir/SkSLProgram.h"
20#include "src/sksl/ir/SkSLSymbolTable.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070021
Brian Osman2e29ab52019-09-20 12:19:11 -040022#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
23#include "src/gpu/GrShaderVar.h"
24#endif
25
Ethan Nicholas762466e2017-06-29 10:03:38 -040026#define SK_FRAGCOLOR_BUILTIN 10001
Ethan Nicholaseab2baa2018-04-13 15:16:27 -040027#define SK_LASTFRAGCOLOR_BUILTIN 10008
Brian Osman7353dc52020-02-07 13:37:12 -050028#define SK_MAIN_COORDS_BUILTIN 10009
Brian Osman577c6062021-04-12 17:17:19 -040029#define SK_INPUT_COLOR_BUILTIN 10010
John Stiles50d0d092021-06-09 17:24:31 -040030#define SK_DEST_COLOR_BUILTIN 10011
Ethan Nicholas762466e2017-06-29 10:03:38 -040031#define SK_FRAGCOORD_BUILTIN 15
Chris Dalton49d14e92018-07-27 12:38:35 -060032#define SK_CLOCKWISE_BUILTIN 17
Ethan Nicholas9eded2c2018-03-22 10:10:44 -040033#define SK_VERTEXID_BUILTIN 42
34#define SK_INSTANCEID_BUILTIN 43
Ethan Nicholascc305772017-10-13 16:17:45 -040035#define SK_POSITION_BUILTIN 0
ethannicholas5961bc92016-10-12 06:39:56 -070036
John Stilese6150002020-10-05 12:03:53 -040037class SkBitSet;
Ethan Nicholasba9a04f2020-11-06 09:28:04 -050038class SkSLCompileBench;
John Stilese6150002020-10-05 12:03:53 -040039
ethannicholasb3058bd2016-07-01 08:22:01 -070040namespace SkSL {
41
Ethan Nicholas95046142021-01-07 10:57:27 -050042namespace dsl {
Ethan Nicholas4f3e6a22021-06-15 09:17:05 -040043 class DSLCore;
Ethan Nicholas95046142021-01-07 10:57:27 -050044 class DSLWriter;
45}
46
Brian Osmanbe0b3b72021-01-06 14:27:35 -050047class ExternalFunction;
Brian Osman4fca9952021-01-28 15:04:51 -050048class FunctionDeclaration;
ethannicholasb3058bd2016-07-01 08:22:01 -070049class IRGenerator;
Brian Osman2b469eb2020-09-21 11:32:10 -040050class IRIntrinsicMap;
Brian Osman010ce6a2020-10-19 16:34:10 -040051class ProgramUsage;
ethannicholasb3058bd2016-07-01 08:22:01 -070052
Brian Osman3d87e9f2020-10-08 11:50:22 -040053struct LoadedModule {
John Stilesdbd4e6f2021-02-16 13:29:15 -050054 ProgramKind fKind;
Brian Osman3d87e9f2020-10-08 11:50:22 -040055 std::shared_ptr<SymbolTable> fSymbols;
56 std::vector<std::unique_ptr<ProgramElement>> fElements;
57};
58
ethannicholasb3058bd2016-07-01 08:22:01 -070059/**
60 * Main compiler entry point. This is a traditional compiler design which first parses the .sksl
Ethan Nicholas941e7e22016-12-12 15:33:30 -050061 * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to
ethannicholasb3058bd2016-07-01 08:22:01 -070062 * produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce
63 * compiled output.
ethannicholas5961bc92016-10-12 06:39:56 -070064 *
65 * See the README for information about SkSL.
ethannicholasb3058bd2016-07-01 08:22:01 -070066 */
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -040067class SK_API Compiler {
ethannicholasb3058bd2016-07-01 08:22:01 -070068public:
Brian Salomon3e2fe2b2021-06-02 09:16:30 -040069 static constexpr const char FRAGCOLOR_NAME[] = "sk_FragColor";
John Stilese67bd132021-03-19 18:39:25 -040070 static constexpr const char RTADJUST_NAME[] = "sk_RTAdjust";
71 static constexpr const char PERVERTEX_NAME[] = "sk_PerVertex";
Ethan Nicholas549c6b82021-06-25 12:31:44 -040072 static constexpr const char POISON_TAG[] = "<POISON>";
Robert Phillipsfe8da172018-01-24 14:52:02 +000073
Brian Salomon3e2fe2b2021-06-02 09:16:30 -040074 /**
75 * Gets a float4 that adjusts the position from Skia device coords to normalized device coords,
76 * used to populate sk_RTAdjust. Assuming the transformed position, pos, is a homogeneous
77 * float4, the vec, v, is applied as such:
78 * float4((pos.xy * v.xz) + sk_Position.ww * v.yw, 0, pos.w);
79 */
80 static std::array<float, 4> GetRTAdjustVector(SkISize rtDims, bool flipY) {
81 std::array<float, 4> result;
82 result[0] = 2.f/rtDims.width();
83 result[2] = 2.f/rtDims.height();
84 result[1] = -1.f;
85 result[3] = -1.f;
86 if (flipY) {
87 result[2] = -result[2];
88 result[3] = -result[3];
89 }
90 return result;
91 }
92
Brian Salomond8d85b92021-07-07 09:41:17 -040093 /**
94 * Uniform values by the compiler to implement origin-neutral dFdy, sk_Clockwise, and
95 * sk_FragCoord.
96 */
97 static std::array<float, 2> GetRTFlipVector(int rtHeight, bool flipY) {
98 std::array<float, 2> result;
99 result[0] = flipY ? rtHeight : 0.f;
100 result[1] = flipY ? -1.f : 1.f;
101 return result;
102 }
103
Ethan Nicholascdeae8c2020-10-22 14:39:46 -0400104 struct OptimizationContext {
105 // nodes we have already reported errors for and should not error on again
106 std::unordered_set<const IRNode*> fSilences;
107 // true if we have updated the CFG during this pass
108 bool fUpdated = false;
109 // true if we need to completely regenerate the CFG
110 bool fNeedsRescan = false;
Brian Osman010ce6a2020-10-19 16:34:10 -0400111 // Metadata about function and variable usage within the program
112 ProgramUsage* fUsage = nullptr;
Ethan Nicholas5b9b0db2021-01-21 13:12:01 -0500113 // Nodes which we can't throw away until the end of optimization
114 StatementArray fOwnedStatements;
Ethan Nicholascdeae8c2020-10-22 14:39:46 -0400115 };
116
John Stilesd6a5f4492021-02-11 15:46:11 -0500117 Compiler(const ShaderCapsClass* caps);
ethannicholasb3058bd2016-07-01 08:22:01 -0700118
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400119 ~Compiler();
ethannicholasb3058bd2016-07-01 08:22:01 -0700120
Brian Osman14003822019-04-10 11:47:26 -0400121 Compiler(const Compiler&) = delete;
122 Compiler& operator=(const Compiler&) = delete;
123
Ethan Nicholas91164d12019-05-15 15:29:54 -0400124 /**
John Stiles2ee4d7a2021-03-30 10:30:47 -0400125 * Allows optimization settings to be unilaterally overridden. This is meant to allow tools like
126 * Viewer or Nanobench to override the compiler's ProgramSettings and ShaderCaps for debugging.
127 */
128 enum class OverrideFlag {
129 kDefault,
130 kOff,
131 kOn,
132 };
133 static void EnableOptimizer(OverrideFlag flag) { sOptimizer = flag; }
134 static void EnableInliner(OverrideFlag flag) { sInliner = flag; }
135
136 /**
Ethan Nicholas55a63af2021-05-18 10:12:58 -0400137 * If fExternalFunctions is supplied in the settings, those values are registered in the symbol
138 * table of the Program, but ownership is *not* transferred. It is up to the caller to keep them
139 * alive.
Ethan Nicholas91164d12019-05-15 15:29:54 -0400140 */
Brian Osman32d53552020-09-23 13:55:20 -0400141 std::unique_ptr<Program> convertProgram(
John Stilesdbd4e6f2021-02-16 13:29:15 -0500142 ProgramKind kind,
Brian Osman32d53552020-09-23 13:55:20 -0400143 String text,
Ethan Nicholas55a63af2021-05-18 10:12:58 -0400144 Program::Settings settings);
ethannicholasb3058bd2016-07-01 08:22:01 -0700145
Ethan Nicholas00543112018-07-31 09:44:36 -0400146 bool toSPIRV(Program& program, OutputStream& out);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500147
Ethan Nicholas00543112018-07-31 09:44:36 -0400148 bool toSPIRV(Program& program, String* out);
ethannicholasb3058bd2016-07-01 08:22:01 -0700149
Ethan Nicholas00543112018-07-31 09:44:36 -0400150 bool toGLSL(Program& program, OutputStream& out);
Ethan Nicholascc305772017-10-13 16:17:45 -0400151
Ethan Nicholas00543112018-07-31 09:44:36 -0400152 bool toGLSL(Program& program, String* out);
Timothy Liangb8eeb802018-07-23 16:46:16 -0400153
Brian Osmanc0243912020-02-19 15:35:26 -0500154 bool toHLSL(Program& program, String* out);
155
Ethan Nicholas00543112018-07-31 09:44:36 -0400156 bool toMetal(Program& program, OutputStream& out);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400157
Ethan Nicholas00543112018-07-31 09:44:36 -0400158 bool toMetal(Program& program, String* out);
159
Ethan Nicholas32724122021-09-07 13:49:07 -0400160 void handleError(skstd::string_view msg, PositionInfo pos);
ethannicholasb3058bd2016-07-01 08:22:01 -0700161
Ethan Nicholas95046142021-01-07 10:57:27 -0500162 String errorText(bool showCount = true);
ethannicholasb3058bd2016-07-01 08:22:01 -0700163
Ethan Nicholas39f6da42021-08-23 13:10:07 -0400164 ErrorReporter& errorReporter() { return *fContext->fErrors; }
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400165
Ethan Nicholas39f6da42021-08-23 13:10:07 -0400166 int errorCount() const { return fContext->fErrors->errorCount(); }
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400167
ethannicholasb3058bd2016-07-01 08:22:01 -0700168 void writeErrorCount();
169
Ethan Nicholas55478662021-08-10 17:14:26 -0400170 void resetErrors() {
171 fErrorText.clear();
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400172 this->errorReporter().resetErrorCount();
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500173 }
174
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400175 Context& context() {
176 return *fContext;
177 }
178
Brian Osman3d87e9f2020-10-08 11:50:22 -0400179 // When SKSL_STANDALONE, fPath is used. (fData, fSize) will be (nullptr, 0)
180 // When !SKSL_STANDALONE, fData and fSize are used. fPath will be nullptr.
181 struct ModuleData {
182 const char* fPath;
183
184 const uint8_t* fData;
185 size_t fSize;
186 };
187
188 static ModuleData MakeModulePath(const char* path) {
189 return ModuleData{path, /*fData=*/nullptr, /*fSize=*/0};
190 }
191 static ModuleData MakeModuleData(const uint8_t* data, size_t size) {
192 return ModuleData{/*fPath=*/nullptr, data, size};
193 }
194
John Stilesa935c3f2021-02-25 10:35:49 -0500195 LoadedModule loadModule(ProgramKind kind, ModuleData data, std::shared_ptr<SymbolTable> base,
196 bool dehydrate);
John Stilesdbd4e6f2021-02-16 13:29:15 -0500197 ParsedModule parseModule(ProgramKind kind, ModuleData data, const ParsedModule& base);
Ethan Nicholas8da1e652019-05-24 11:01:59 -0400198
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500199 IRGenerator& irGenerator() {
200 return *fIRGenerator;
201 }
202
John Stilesdbd4e6f2021-02-16 13:29:15 -0500203 const ParsedModule& moduleForProgramKind(ProgramKind kind);
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500204
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400205private:
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400206 class CompilerErrorReporter : public ErrorReporter {
207 public:
208 CompilerErrorReporter(Compiler* compiler)
209 : fCompiler(*compiler) {}
210
Ethan Nicholas32724122021-09-07 13:49:07 -0400211 void handleError(skstd::string_view msg, PositionInfo pos) override {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400212 fCompiler.handleError(msg, pos);
213 }
214
215 private:
216 Compiler& fCompiler;
217 };
218
Brian Osman56269982020-11-20 12:38:07 -0500219 const ParsedModule& loadGPUModule();
220 const ParsedModule& loadFragmentModule();
221 const ParsedModule& loadVertexModule();
Brian Osmanb06301e2020-11-06 11:45:36 -0500222 const ParsedModule& loadPublicModule();
Brian Osmancbb60bd2021-04-12 09:49:20 -0400223 const ParsedModule& loadRuntimeShaderModule();
Brian Osman88cda172020-10-09 12:05:16 -0400224
John Stilesb624b722021-08-13 12:16:13 -0400225 std::shared_ptr<SymbolTable> makeRootSymbolTable();
226 std::shared_ptr<SymbolTable> makePrivateSymbolTable(std::shared_ptr<SymbolTable> parent);
227
John Stiles0bfeae62021-03-11 09:09:42 -0500228 /** Optimize every function in the program. */
Ethan Nicholas34b19c52020-09-14 11:33:47 -0400229 bool optimize(Program& program);
230
John Stiles2ecc5952021-09-01 14:41:36 -0400231 /** Performs final checks to confirm that a fully-assembled/optimized is valid. */
232 bool finalize(Program& program);
233
John Stiles0bfeae62021-03-11 09:09:42 -0500234 /** Optimize the module. */
Brian Osman0006ad02020-11-18 15:38:39 -0500235 bool optimize(LoadedModule& module);
236
John Stiles0bfeae62021-03-11 09:09:42 -0500237 /** Eliminates unused functions from a Program, according to the stats in ProgramUsage. */
238 bool removeDeadFunctions(Program& program, ProgramUsage* usage);
239
John Stiles26541872021-03-16 12:19:54 -0400240 /** Eliminates unreferenced variables from a Program, according to the stats in ProgramUsage. */
John Stiles0bfeae62021-03-11 09:09:42 -0500241 bool removeDeadGlobalVariables(Program& program, ProgramUsage* usage);
John Stiles26541872021-03-16 12:19:54 -0400242 bool removeDeadLocalVariables(Program& program, ProgramUsage* usage);
John Stiles0bfeae62021-03-11 09:09:42 -0500243
John Stiles25be58e2021-05-20 14:38:40 -0400244 /** Eliminates unreachable statements from a Program. */
245 void removeUnreachableCode(Program& program, ProgramUsage* usage);
246
John Stiles3ff77f42021-09-06 22:17:58 -0400247 /** Flattens out function calls when it is safe to do so. */
248 bool runInliner(const std::vector<std::unique_ptr<ProgramElement>>& elements,
249 std::shared_ptr<SymbolTable> symbols,
250 ProgramUsage* usage);
251
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400252 CompilerErrorReporter fErrorReporter;
Brian Osman0006ad02020-11-18 15:38:39 -0500253 std::shared_ptr<Context> fContext;
Brian Osmand7e76592020-11-02 12:26:22 -0500254
Brian Osmancbb60bd2021-04-12 09:49:20 -0400255 ParsedModule fRootModule; // Core types
Brian Osmanb06301e2020-11-06 11:45:36 -0500256
Brian Osmancbb60bd2021-04-12 09:49:20 -0400257 ParsedModule fPrivateModule; // [Root] + Internal types
258 ParsedModule fGPUModule; // [Private] + GPU intrinsics, helper functions
259 ParsedModule fVertexModule; // [GPU] + Vertex stage decls
260 ParsedModule fFragmentModule; // [GPU] + Fragment stage decls
Brian Osmanb06301e2020-11-06 11:45:36 -0500261
Brian Osmancbb60bd2021-04-12 09:49:20 -0400262 ParsedModule fPublicModule; // [Root] + Public features
Brian Osmana8b897b2021-08-30 16:40:44 -0400263 ParsedModule fRuntimeShaderModule; // [Public] + Runtime shader decls
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400264
Ethan Nicholas041fd0a2020-10-07 16:42:04 -0400265 // holds ModifiersPools belonging to the core includes for lifetime purposes
John Stilesa47b3512021-05-04 16:15:00 -0400266 ModifiersPool fCoreModifiers;
Ethan Nicholas041fd0a2020-10-07 16:42:04 -0400267
John Stiles2dda4b62021-09-16 13:18:10 -0400268 Mangler fMangler;
John Stiles7b463002020-08-31 17:29:21 -0400269 Inliner fInliner;
John Stiles656427a2020-08-27 15:26:26 -0400270 std::unique_ptr<IRGenerator> fIRGenerator;
ethannicholasb3058bd2016-07-01 08:22:01 -0700271
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400272 String fErrorText;
Brian Osman88cda172020-10-09 12:05:16 -0400273
John Stiles2ee4d7a2021-03-30 10:30:47 -0400274 static OverrideFlag sOptimizer;
275 static OverrideFlag sInliner;
276
Brian Osman88cda172020-10-09 12:05:16 -0400277 friend class AutoSource;
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500278 friend class ::SkSLCompileBench;
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -0400279 friend class DSLParser;
Ethan Nicholas4f3e6a22021-06-15 09:17:05 -0400280 friend class dsl::DSLCore;
Ethan Nicholas95046142021-01-07 10:57:27 -0500281 friend class dsl::DSLWriter;
ethannicholasb3058bd2016-07-01 08:22:01 -0700282};
283
John Stilesa6841be2020-08-06 14:11:56 -0400284} // namespace SkSL
ethannicholasb3058bd2016-07-01 08:22:01 -0700285
286#endif