blob: 003f1549085b858aeb434bb535f97b3cc5f02e1c [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 */
Mike Klein6ad99092016-10-26 10:35:22 -04007
ethannicholasb3058bd2016-07-01 08:22:01 -07008#include "SkSLCompiler.h"
9
ethannicholas5961bc92016-10-12 06:39:56 -070010#include "ast/SkSLASTPrecision.h"
ethannicholas22f939e2016-10-13 13:25:34 -070011#include "SkSLCFGGenerator.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070012#include "SkSLIRGenerator.h"
13#include "SkSLParser.h"
14#include "SkSLSPIRVCodeGenerator.h"
15#include "ir/SkSLExpression.h"
16#include "ir/SkSLIntLiteral.h"
ethannicholas5961bc92016-10-12 06:39:56 -070017#include "ir/SkSLModifiersDeclaration.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070018#include "ir/SkSLSymbolTable.h"
ethannicholasddb37d62016-10-20 09:54:00 -070019#include "ir/SkSLUnresolvedFunction.h"
ethannicholas22f939e2016-10-13 13:25:34 -070020#include "ir/SkSLVarDeclarations.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070021#include "SkMutex.h"
22
23#define STRINGIFY(x) #x
24
25// include the built-in shader symbols as static strings
26
ethannicholas5961bc92016-10-12 06:39:56 -070027static const char* SKSL_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070028#include "sksl.include"
29;
30
ethannicholas5961bc92016-10-12 06:39:56 -070031static const char* SKSL_VERT_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070032#include "sksl_vert.include"
33;
34
ethannicholas5961bc92016-10-12 06:39:56 -070035static const char* SKSL_FRAG_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070036#include "sksl_frag.include"
37;
38
39namespace SkSL {
40
Mike Klein6ad99092016-10-26 10:35:22 -040041Compiler::Compiler()
ethannicholasb3058bd2016-07-01 08:22:01 -070042: fErrorCount(0) {
43 auto types = std::shared_ptr<SymbolTable>(new SymbolTable(*this));
44 auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, *this));
ethannicholasd598f792016-07-25 10:08:54 -070045 fIRGenerator = new IRGenerator(&fContext, symbols, *this);
ethannicholasb3058bd2016-07-01 08:22:01 -070046 fTypes = types;
ethannicholasd598f792016-07-25 10:08:54 -070047 #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \
48 fContext.f ## t ## _Type.get())
ethannicholasb3058bd2016-07-01 08:22:01 -070049 ADD_TYPE(Void);
50 ADD_TYPE(Float);
51 ADD_TYPE(Vec2);
52 ADD_TYPE(Vec3);
53 ADD_TYPE(Vec4);
54 ADD_TYPE(Double);
55 ADD_TYPE(DVec2);
56 ADD_TYPE(DVec3);
57 ADD_TYPE(DVec4);
58 ADD_TYPE(Int);
59 ADD_TYPE(IVec2);
60 ADD_TYPE(IVec3);
61 ADD_TYPE(IVec4);
62 ADD_TYPE(UInt);
63 ADD_TYPE(UVec2);
64 ADD_TYPE(UVec3);
65 ADD_TYPE(UVec4);
66 ADD_TYPE(Bool);
67 ADD_TYPE(BVec2);
68 ADD_TYPE(BVec3);
69 ADD_TYPE(BVec4);
70 ADD_TYPE(Mat2x2);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050071 types->addWithoutOwnership(SkString("mat2x2"), fContext.fMat2x2_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070072 ADD_TYPE(Mat2x3);
73 ADD_TYPE(Mat2x4);
74 ADD_TYPE(Mat3x2);
75 ADD_TYPE(Mat3x3);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050076 types->addWithoutOwnership(SkString("mat3x3"), fContext.fMat3x3_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070077 ADD_TYPE(Mat3x4);
78 ADD_TYPE(Mat4x2);
79 ADD_TYPE(Mat4x3);
80 ADD_TYPE(Mat4x4);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050081 types->addWithoutOwnership(SkString("mat4x4"), fContext.fMat4x4_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070082 ADD_TYPE(GenType);
83 ADD_TYPE(GenDType);
84 ADD_TYPE(GenIType);
85 ADD_TYPE(GenUType);
86 ADD_TYPE(GenBType);
87 ADD_TYPE(Mat);
88 ADD_TYPE(Vec);
89 ADD_TYPE(GVec);
90 ADD_TYPE(GVec2);
91 ADD_TYPE(GVec3);
92 ADD_TYPE(GVec4);
93 ADD_TYPE(DVec);
94 ADD_TYPE(IVec);
95 ADD_TYPE(UVec);
96 ADD_TYPE(BVec);
97
98 ADD_TYPE(Sampler1D);
99 ADD_TYPE(Sampler2D);
100 ADD_TYPE(Sampler3D);
ethannicholas5961bc92016-10-12 06:39:56 -0700101 ADD_TYPE(SamplerExternalOES);
ethannicholasb3058bd2016-07-01 08:22:01 -0700102 ADD_TYPE(SamplerCube);
103 ADD_TYPE(Sampler2DRect);
104 ADD_TYPE(Sampler1DArray);
105 ADD_TYPE(Sampler2DArray);
106 ADD_TYPE(SamplerCubeArray);
107 ADD_TYPE(SamplerBuffer);
108 ADD_TYPE(Sampler2DMS);
109 ADD_TYPE(Sampler2DMSArray);
110
Brian Salomonbf7b6202016-11-11 16:08:03 -0500111 ADD_TYPE(ISampler2D);
112
Brian Salomon2a51de82016-11-16 12:06:01 -0500113 ADD_TYPE(Image2D);
114 ADD_TYPE(IImage2D);
115
Greg Daniel64773e62016-11-22 09:44:03 -0500116 ADD_TYPE(SubpassInput);
117 ADD_TYPE(SubpassInputMS);
118
ethannicholasb3058bd2016-07-01 08:22:01 -0700119 ADD_TYPE(GSampler1D);
120 ADD_TYPE(GSampler2D);
121 ADD_TYPE(GSampler3D);
122 ADD_TYPE(GSamplerCube);
123 ADD_TYPE(GSampler2DRect);
124 ADD_TYPE(GSampler1DArray);
125 ADD_TYPE(GSampler2DArray);
126 ADD_TYPE(GSamplerCubeArray);
127 ADD_TYPE(GSamplerBuffer);
128 ADD_TYPE(GSampler2DMS);
129 ADD_TYPE(GSampler2DMSArray);
130
131 ADD_TYPE(Sampler1DShadow);
132 ADD_TYPE(Sampler2DShadow);
133 ADD_TYPE(SamplerCubeShadow);
134 ADD_TYPE(Sampler2DRectShadow);
135 ADD_TYPE(Sampler1DArrayShadow);
136 ADD_TYPE(Sampler2DArrayShadow);
137 ADD_TYPE(SamplerCubeArrayShadow);
138 ADD_TYPE(GSampler2DArrayShadow);
139 ADD_TYPE(GSamplerCubeArrayShadow);
140
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500141 SkString skCapsName("sk_Caps");
142 Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
143 *fContext.fSkCaps_Type, Variable::kGlobal_Storage);
144 fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
145
ethannicholas5961bc92016-10-12 06:39:56 -0700146 Modifiers::Flag ignored1;
147 std::vector<std::unique_ptr<ProgramElement>> ignored2;
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500148 this->internalConvertProgram(SkString(SKSL_INCLUDE), &ignored1, &ignored2);
ethannicholasddb37d62016-10-20 09:54:00 -0700149 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholasb3058bd2016-07-01 08:22:01 -0700150 ASSERT(!fErrorCount);
151}
152
153Compiler::~Compiler() {
154 delete fIRGenerator;
155}
156
ethannicholas22f939e2016-10-13 13:25:34 -0700157// add the definition created by assigning to the lvalue to the definition set
158void Compiler::addDefinition(const Expression* lvalue, const Expression* expr,
159 std::unordered_map<const Variable*, const Expression*>* definitions) {
160 switch (lvalue->fKind) {
161 case Expression::kVariableReference_Kind: {
162 const Variable& var = ((VariableReference*) lvalue)->fVariable;
163 if (var.fStorage == Variable::kLocal_Storage) {
164 (*definitions)[&var] = expr;
165 }
166 break;
167 }
168 case Expression::kSwizzle_Kind:
169 // We consider the variable written to as long as at least some of its components have
170 // been written to. This will lead to some false negatives (we won't catch it if you
171 // write to foo.x and then read foo.y), but being stricter could lead to false positives
Mike Klein6ad99092016-10-26 10:35:22 -0400172 // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
173 // but since we pass foo as a whole it is flagged as an error) unless we perform a much
ethannicholas22f939e2016-10-13 13:25:34 -0700174 // more complicated whole-program analysis. This is probably good enough.
Mike Klein6ad99092016-10-26 10:35:22 -0400175 this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
176 fContext.fDefined_Expression.get(),
ethannicholas22f939e2016-10-13 13:25:34 -0700177 definitions);
178 break;
179 case Expression::kIndex_Kind:
180 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400181 this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
182 fContext.fDefined_Expression.get(),
ethannicholas22f939e2016-10-13 13:25:34 -0700183 definitions);
184 break;
185 case Expression::kFieldAccess_Kind:
186 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400187 this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
188 fContext.fDefined_Expression.get(),
ethannicholas22f939e2016-10-13 13:25:34 -0700189 definitions);
190 break;
191 default:
192 // not an lvalue, can't happen
193 ASSERT(false);
194 }
195}
196
197// add local variables defined by this node to the set
Mike Klein6ad99092016-10-26 10:35:22 -0400198void Compiler::addDefinitions(const BasicBlock::Node& node,
ethannicholas22f939e2016-10-13 13:25:34 -0700199 std::unordered_map<const Variable*, const Expression*>* definitions) {
200 switch (node.fKind) {
201 case BasicBlock::Node::kExpression_Kind: {
202 const Expression* expr = (Expression*) node.fNode;
203 if (expr->fKind == Expression::kBinary_Kind) {
204 const BinaryExpression* b = (BinaryExpression*) expr;
205 if (b->fOperator == Token::EQ) {
206 this->addDefinition(b->fLeft.get(), b->fRight.get(), definitions);
207 }
208 }
209 break;
210 }
211 case BasicBlock::Node::kStatement_Kind: {
212 const Statement* stmt = (Statement*) node.fNode;
213 if (stmt->fKind == Statement::kVarDeclarations_Kind) {
214 const VarDeclarationsStatement* vd = (VarDeclarationsStatement*) stmt;
215 for (const VarDeclaration& decl : vd->fDeclaration->fVars) {
216 if (decl.fValue) {
217 (*definitions)[decl.fVar] = decl.fValue.get();
218 }
219 }
220 }
221 break;
222 }
223 }
224}
225
226void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
227 BasicBlock& block = cfg->fBlocks[blockId];
228
229 // compute definitions after this block
230 std::unordered_map<const Variable*, const Expression*> after = block.fBefore;
231 for (const BasicBlock::Node& n : block.fNodes) {
232 this->addDefinitions(n, &after);
233 }
234
235 // propagate definitions to exits
236 for (BlockId exitId : block.fExits) {
237 BasicBlock& exit = cfg->fBlocks[exitId];
238 for (const auto& pair : after) {
239 const Expression* e1 = pair.second;
240 if (exit.fBefore.find(pair.first) == exit.fBefore.end()) {
241 exit.fBefore[pair.first] = e1;
242 } else {
243 const Expression* e2 = exit.fBefore[pair.first];
244 if (e1 != e2) {
245 // definition has changed, merge and add exit block to worklist
246 workList->insert(exitId);
247 if (!e1 || !e2) {
248 exit.fBefore[pair.first] = nullptr;
249 } else {
250 exit.fBefore[pair.first] = fContext.fDefined_Expression.get();
251 }
252 }
253 }
254 }
255 }
256}
257
258// returns a map which maps all local variables in the function to null, indicating that their value
259// is initially unknown
260static std::unordered_map<const Variable*, const Expression*> compute_start_state(const CFG& cfg) {
261 std::unordered_map<const Variable*, const Expression*> result;
Mike Klein6ad99092016-10-26 10:35:22 -0400262 for (const auto& block : cfg.fBlocks) {
263 for (const auto& node : block.fNodes) {
ethannicholas22f939e2016-10-13 13:25:34 -0700264 if (node.fKind == BasicBlock::Node::kStatement_Kind) {
265 const Statement* s = (Statement*) node.fNode;
266 if (s->fKind == Statement::kVarDeclarations_Kind) {
267 const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
268 for (const VarDeclaration& decl : vd->fDeclaration->fVars) {
269 result[decl.fVar] = nullptr;
Mike Klein6ad99092016-10-26 10:35:22 -0400270 }
ethannicholas22f939e2016-10-13 13:25:34 -0700271 }
272 }
273 }
274 }
275 return result;
276}
277
278void Compiler::scanCFG(const FunctionDefinition& f) {
279 CFG cfg = CFGGenerator().getCFG(f);
280
281 // compute the data flow
282 cfg.fBlocks[cfg.fStart].fBefore = compute_start_state(cfg);
283 std::set<BlockId> workList;
284 for (BlockId i = 0; i < cfg.fBlocks.size(); i++) {
285 workList.insert(i);
286 }
287 while (workList.size()) {
288 BlockId next = *workList.begin();
289 workList.erase(workList.begin());
290 this->scanCFG(&cfg, next, &workList);
291 }
292
293 // check for unreachable code
294 for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
Mike Klein6ad99092016-10-26 10:35:22 -0400295 if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
ethannicholas22f939e2016-10-13 13:25:34 -0700296 cfg.fBlocks[i].fNodes.size()) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500297 this->error(cfg.fBlocks[i].fNodes[0].fNode->fPosition, SkString("unreachable"));
ethannicholas22f939e2016-10-13 13:25:34 -0700298 }
299 }
300 if (fErrorCount) {
301 return;
302 }
303
304 // check for undefined variables
305 for (const BasicBlock& b : cfg.fBlocks) {
306 std::unordered_map<const Variable*, const Expression*> definitions = b.fBefore;
307 for (const BasicBlock::Node& n : b.fNodes) {
308 if (n.fKind == BasicBlock::Node::kExpression_Kind) {
309 const Expression* expr = (const Expression*) n.fNode;
310 if (expr->fKind == Expression::kVariableReference_Kind) {
311 const Variable& var = ((VariableReference*) expr)->fVariable;
Mike Klein6ad99092016-10-26 10:35:22 -0400312 if (var.fStorage == Variable::kLocal_Storage &&
ethannicholas22f939e2016-10-13 13:25:34 -0700313 !definitions[&var]) {
314 this->error(expr->fPosition,
315 "'" + var.fName + "' has not been assigned");
Mike Klein6ad99092016-10-26 10:35:22 -0400316 }
ethannicholas22f939e2016-10-13 13:25:34 -0700317 }
318 }
319 this->addDefinitions(n, &definitions);
320 }
321 }
322
323 // check for missing return
324 if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
325 if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500326 this->error(f.fPosition, SkString("function can exit without returning a value"));
ethannicholas22f939e2016-10-13 13:25:34 -0700327 }
328 }
329}
330
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500331void Compiler::internalConvertProgram(SkString text,
ethannicholas5961bc92016-10-12 06:39:56 -0700332 Modifiers::Flag* defaultPrecision,
ethannicholasb3058bd2016-07-01 08:22:01 -0700333 std::vector<std::unique_ptr<ProgramElement>>* result) {
334 Parser parser(text, *fTypes, *this);
335 std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
336 if (fErrorCount) {
337 return;
338 }
ethannicholas5961bc92016-10-12 06:39:56 -0700339 *defaultPrecision = Modifiers::kHighp_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700340 for (size_t i = 0; i < parsed.size(); i++) {
341 ASTDeclaration& decl = *parsed[i];
342 switch (decl.fKind) {
343 case ASTDeclaration::kVar_Kind: {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700344 std::unique_ptr<VarDeclarations> s = fIRGenerator->convertVarDeclarations(
Mike Klein6ad99092016-10-26 10:35:22 -0400345 (ASTVarDeclarations&) decl,
ethannicholasb3058bd2016-07-01 08:22:01 -0700346 Variable::kGlobal_Storage);
347 if (s) {
348 result->push_back(std::move(s));
349 }
350 break;
351 }
352 case ASTDeclaration::kFunction_Kind: {
353 std::unique_ptr<FunctionDefinition> f = fIRGenerator->convertFunction(
354 (ASTFunction&) decl);
ethannicholas22f939e2016-10-13 13:25:34 -0700355 if (!fErrorCount && f) {
356 this->scanCFG(*f);
ethannicholasb3058bd2016-07-01 08:22:01 -0700357 result->push_back(std::move(f));
358 }
359 break;
360 }
ethannicholas5961bc92016-10-12 06:39:56 -0700361 case ASTDeclaration::kModifiers_Kind: {
362 std::unique_ptr<ModifiersDeclaration> f = fIRGenerator->convertModifiersDeclaration(
363 (ASTModifiersDeclaration&) decl);
364 if (f) {
365 result->push_back(std::move(f));
366 }
367 break;
368 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700369 case ASTDeclaration::kInterfaceBlock_Kind: {
370 std::unique_ptr<InterfaceBlock> i = fIRGenerator->convertInterfaceBlock(
371 (ASTInterfaceBlock&) decl);
372 if (i) {
373 result->push_back(std::move(i));
374 }
375 break;
376 }
377 case ASTDeclaration::kExtension_Kind: {
378 std::unique_ptr<Extension> e = fIRGenerator->convertExtension((ASTExtension&) decl);
379 if (e) {
380 result->push_back(std::move(e));
381 }
382 break;
383 }
ethannicholas5961bc92016-10-12 06:39:56 -0700384 case ASTDeclaration::kPrecision_Kind: {
385 *defaultPrecision = ((ASTPrecision&) decl).fPrecision;
386 break;
387 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700388 default:
389 ABORT("unsupported declaration: %s\n", decl.description().c_str());
390 }
391 }
392}
393
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500394std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString text,
395 std::unordered_map<SkString, CapValue> caps) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700396 fErrorText = "";
397 fErrorCount = 0;
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500398 fIRGenerator->start(&caps);
ethannicholasd598f792016-07-25 10:08:54 -0700399 std::vector<std::unique_ptr<ProgramElement>> elements;
ethannicholas5961bc92016-10-12 06:39:56 -0700400 Modifiers::Flag ignored;
ethannicholasb3058bd2016-07-01 08:22:01 -0700401 switch (kind) {
402 case Program::kVertex_Kind:
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500403 this->internalConvertProgram(SkString(SKSL_VERT_INCLUDE), &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -0700404 break;
405 case Program::kFragment_Kind:
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500406 this->internalConvertProgram(SkString(SKSL_FRAG_INCLUDE), &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -0700407 break;
408 }
ethannicholasddb37d62016-10-20 09:54:00 -0700409 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholas5961bc92016-10-12 06:39:56 -0700410 Modifiers::Flag defaultPrecision;
411 this->internalConvertProgram(text, &defaultPrecision, &elements);
Mike Klein6ad99092016-10-26 10:35:22 -0400412 auto result = std::unique_ptr<Program>(new Program(kind, defaultPrecision, std::move(elements),
ethannicholasddb37d62016-10-20 09:54:00 -0700413 fIRGenerator->fSymbolTable));
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500414 fIRGenerator->finish();
ethannicholasb3058bd2016-07-01 08:22:01 -0700415 this->writeErrorCount();
ethannicholasd598f792016-07-25 10:08:54 -0700416 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700417}
418
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500419void Compiler::error(Position position, SkString msg) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700420 fErrorCount++;
421 fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
422}
423
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500424SkString Compiler::errorText() {
425 SkString result = fErrorText;
ethannicholasb3058bd2016-07-01 08:22:01 -0700426 return result;
427}
428
429void Compiler::writeErrorCount() {
430 if (fErrorCount) {
431 fErrorText += to_string(fErrorCount) + " error";
432 if (fErrorCount > 1) {
433 fErrorText += "s";
434 }
435 fErrorText += "\n";
436 }
437}
438
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500439bool Compiler::toSPIRV(Program::Kind kind, const SkString& text, SkWStream& out) {
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500440 std::unordered_map<SkString, CapValue> capsMap;
441 auto program = this->convertProgram(kind, text, capsMap);
ethannicholasb3058bd2016-07-01 08:22:01 -0700442 if (fErrorCount == 0) {
ethannicholasd598f792016-07-25 10:08:54 -0700443 SkSL::SPIRVCodeGenerator cg(&fContext);
ethannicholasb3058bd2016-07-01 08:22:01 -0700444 cg.generateCode(*program.get(), out);
ethannicholasb3058bd2016-07-01 08:22:01 -0700445 }
446 return fErrorCount == 0;
447}
448
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500449bool Compiler::toSPIRV(Program::Kind kind, const SkString& text, SkString* out) {
450 SkDynamicMemoryWStream buffer;
ethannicholasb3058bd2016-07-01 08:22:01 -0700451 bool result = this->toSPIRV(kind, text, buffer);
452 if (result) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500453 sk_sp<SkData> data(buffer.detachAsData());
454 *out = SkString((const char*) data->data(), data->size());
ethannicholasb3058bd2016-07-01 08:22:01 -0700455 }
ethannicholasf789b382016-08-03 12:43:36 -0700456 return result;
457}
458
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500459static void fill_caps(const GrGLSLCaps& caps, std::unordered_map<SkString, CapValue>* capsMap) {
460#define CAP(name) capsMap->insert(std::make_pair(SkString(#name), CapValue(caps.name())));
461 CAP(fbFetchSupport);
462 CAP(fbFetchNeedsCustomOutput);
463 CAP(bindlessTextureSupport);
464 CAP(dropsTileOnZeroDivide);
465 CAP(flatInterpolationSupport);
466 CAP(noperspectiveInterpolationSupport);
467 CAP(multisampleInterpolationSupport);
468 CAP(sampleVariablesSupport);
469 CAP(sampleMaskOverrideCoverageSupport);
470 CAP(externalTextureSupport);
471 CAP(texelFetchSupport);
472 CAP(imageLoadStoreSupport);
473 CAP(mustEnableAdvBlendEqs);
474 CAP(mustEnableSpecificAdvBlendEqs);
475 CAP(mustDeclareFragmentShaderOutput);
476 CAP(canUseAnyFunctionInShader);
477#undef CAP
478}
479
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500480bool Compiler::toGLSL(Program::Kind kind, const SkString& text, const GrGLSLCaps& caps,
481 SkWStream& out) {
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500482 std::unordered_map<SkString, CapValue> capsMap;
483 fill_caps(caps, &capsMap);
484 auto program = this->convertProgram(kind, text, capsMap);
ethannicholasf789b382016-08-03 12:43:36 -0700485 if (fErrorCount == 0) {
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500486 SkSL::GLSLCodeGenerator cg(&fContext, &caps);
ethannicholasf789b382016-08-03 12:43:36 -0700487 cg.generateCode(*program.get(), out);
ethannicholasf789b382016-08-03 12:43:36 -0700488 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700489 return fErrorCount == 0;
490}
491
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500492bool Compiler::toGLSL(Program::Kind kind, const SkString& text, const GrGLSLCaps& caps,
493 SkString* out) {
494 SkDynamicMemoryWStream buffer;
ethannicholasf789b382016-08-03 12:43:36 -0700495 bool result = this->toGLSL(kind, text, caps, buffer);
496 if (result) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500497 sk_sp<SkData> data(buffer.detachAsData());
498 *out = SkString((const char*) data->data(), data->size());
ethannicholasf789b382016-08-03 12:43:36 -0700499 }
500 return result;
501}
502
ethannicholasb3058bd2016-07-01 08:22:01 -0700503} // namespace