SkSLCompiler.cpp revision 4824cf4c1ef991fe9b0dcd1536e83b37907d3fcf
1/*
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 */
7
8#include "SkSLCompiler.h"
9
10#include <fstream>
11#include <streambuf>
12
13#include "SkSLIRGenerator.h"
14#include "SkSLParser.h"
15#include "SkSLSPIRVCodeGenerator.h"
16#include "ir/SkSLExpression.h"
17#include "ir/SkSLIntLiteral.h"
18#include "ir/SkSLSymbolTable.h"
19#include "ir/SkSLVarDeclaration.h"
20#include "SkMutex.h"
21
22#define STRINGIFY(x) #x
23
24// include the built-in shader symbols as static strings
25
26static std::string SKSL_INCLUDE =
27#include "sksl.include"
28;
29
30static std::string SKSL_VERT_INCLUDE =
31#include "sksl_vert.include"
32;
33
34static std::string SKSL_FRAG_INCLUDE =
35#include "sksl_frag.include"
36;
37
38namespace SkSL {
39
40Compiler::Compiler()
41: fErrorCount(0) {
42    auto types = std::shared_ptr<SymbolTable>(new SymbolTable(*this));
43    auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, *this));
44    fIRGenerator = new IRGenerator(&fContext, symbols, *this);
45    fTypes = types;
46    #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \
47                                                   fContext.f ## t ## _Type.get())
48    ADD_TYPE(Void);
49    ADD_TYPE(Float);
50    ADD_TYPE(Vec2);
51    ADD_TYPE(Vec3);
52    ADD_TYPE(Vec4);
53    ADD_TYPE(Double);
54    ADD_TYPE(DVec2);
55    ADD_TYPE(DVec3);
56    ADD_TYPE(DVec4);
57    ADD_TYPE(Int);
58    ADD_TYPE(IVec2);
59    ADD_TYPE(IVec3);
60    ADD_TYPE(IVec4);
61    ADD_TYPE(UInt);
62    ADD_TYPE(UVec2);
63    ADD_TYPE(UVec3);
64    ADD_TYPE(UVec4);
65    ADD_TYPE(Bool);
66    ADD_TYPE(BVec2);
67    ADD_TYPE(BVec3);
68    ADD_TYPE(BVec4);
69    ADD_TYPE(Mat2x2);
70    types->addWithoutOwnership("mat2x2", fContext.fMat2x2_Type.get());
71    ADD_TYPE(Mat2x3);
72    ADD_TYPE(Mat2x4);
73    ADD_TYPE(Mat3x2);
74    ADD_TYPE(Mat3x3);
75    types->addWithoutOwnership("mat3x3", fContext.fMat3x3_Type.get());
76    ADD_TYPE(Mat3x4);
77    ADD_TYPE(Mat4x2);
78    ADD_TYPE(Mat4x3);
79    ADD_TYPE(Mat4x4);
80    types->addWithoutOwnership("mat4x4", fContext.fMat4x4_Type.get());
81    ADD_TYPE(GenType);
82    ADD_TYPE(GenDType);
83    ADD_TYPE(GenIType);
84    ADD_TYPE(GenUType);
85    ADD_TYPE(GenBType);
86    ADD_TYPE(Mat);
87    ADD_TYPE(Vec);
88    ADD_TYPE(GVec);
89    ADD_TYPE(GVec2);
90    ADD_TYPE(GVec3);
91    ADD_TYPE(GVec4);
92    ADD_TYPE(DVec);
93    ADD_TYPE(IVec);
94    ADD_TYPE(UVec);
95    ADD_TYPE(BVec);
96
97    ADD_TYPE(Sampler1D);
98    ADD_TYPE(Sampler2D);
99    ADD_TYPE(Sampler3D);
100    ADD_TYPE(SamplerCube);
101    ADD_TYPE(Sampler2DRect);
102    ADD_TYPE(Sampler1DArray);
103    ADD_TYPE(Sampler2DArray);
104    ADD_TYPE(SamplerCubeArray);
105    ADD_TYPE(SamplerBuffer);
106    ADD_TYPE(Sampler2DMS);
107    ADD_TYPE(Sampler2DMSArray);
108
109    ADD_TYPE(GSampler1D);
110    ADD_TYPE(GSampler2D);
111    ADD_TYPE(GSampler3D);
112    ADD_TYPE(GSamplerCube);
113    ADD_TYPE(GSampler2DRect);
114    ADD_TYPE(GSampler1DArray);
115    ADD_TYPE(GSampler2DArray);
116    ADD_TYPE(GSamplerCubeArray);
117    ADD_TYPE(GSamplerBuffer);
118    ADD_TYPE(GSampler2DMS);
119    ADD_TYPE(GSampler2DMSArray);
120
121    ADD_TYPE(Sampler1DShadow);
122    ADD_TYPE(Sampler2DShadow);
123    ADD_TYPE(SamplerCubeShadow);
124    ADD_TYPE(Sampler2DRectShadow);
125    ADD_TYPE(Sampler1DArrayShadow);
126    ADD_TYPE(Sampler2DArrayShadow);
127    ADD_TYPE(SamplerCubeArrayShadow);
128    ADD_TYPE(GSampler2DArrayShadow);
129    ADD_TYPE(GSamplerCubeArrayShadow);
130
131    std::vector<std::unique_ptr<ProgramElement>> ignored;
132    this->internalConvertProgram(SKSL_INCLUDE, &ignored);
133    ASSERT(!fErrorCount);
134}
135
136Compiler::~Compiler() {
137    delete fIRGenerator;
138}
139
140void Compiler::internalConvertProgram(std::string text,
141                                      std::vector<std::unique_ptr<ProgramElement>>* result) {
142    Parser parser(text, *fTypes, *this);
143    std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
144    if (fErrorCount) {
145        return;
146    }
147    for (size_t i = 0; i < parsed.size(); i++) {
148        ASTDeclaration& decl = *parsed[i];
149        switch (decl.fKind) {
150            case ASTDeclaration::kVar_Kind: {
151                std::unique_ptr<VarDeclarations> s = fIRGenerator->convertVarDeclarations(
152                                                                         (ASTVarDeclarations&) decl,
153                                                                         Variable::kGlobal_Storage);
154                if (s) {
155                    result->push_back(std::move(s));
156                }
157                break;
158            }
159            case ASTDeclaration::kFunction_Kind: {
160                std::unique_ptr<FunctionDefinition> f = fIRGenerator->convertFunction(
161                                                                               (ASTFunction&) decl);
162                if (f) {
163                    result->push_back(std::move(f));
164                }
165                break;
166            }
167            case ASTDeclaration::kInterfaceBlock_Kind: {
168                std::unique_ptr<InterfaceBlock> i = fIRGenerator->convertInterfaceBlock(
169                                                                         (ASTInterfaceBlock&) decl);
170                if (i) {
171                    result->push_back(std::move(i));
172                }
173                break;
174            }
175            case ASTDeclaration::kExtension_Kind: {
176                std::unique_ptr<Extension> e = fIRGenerator->convertExtension((ASTExtension&) decl);
177                if (e) {
178                    result->push_back(std::move(e));
179                }
180                break;
181            }
182            default:
183                ABORT("unsupported declaration: %s\n", decl.description().c_str());
184        }
185    }
186}
187
188std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, std::string text) {
189    fErrorText = "";
190    fErrorCount = 0;
191    fIRGenerator->pushSymbolTable();
192    std::vector<std::unique_ptr<ProgramElement>> elements;
193    switch (kind) {
194        case Program::kVertex_Kind:
195            this->internalConvertProgram(SKSL_VERT_INCLUDE, &elements);
196            break;
197        case Program::kFragment_Kind:
198            this->internalConvertProgram(SKSL_FRAG_INCLUDE, &elements);
199            break;
200    }
201    this->internalConvertProgram(text, &elements);
202    auto result = std::unique_ptr<Program>(new Program(kind, std::move(elements),
203                                                       fIRGenerator->fSymbolTable));;
204    fIRGenerator->popSymbolTable();
205    this->writeErrorCount();
206    return result;
207}
208
209void Compiler::error(Position position, std::string msg) {
210    fErrorCount++;
211    fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
212}
213
214std::string Compiler::errorText() {
215    std::string result = fErrorText;
216    return result;
217}
218
219void Compiler::writeErrorCount() {
220    if (fErrorCount) {
221        fErrorText += to_string(fErrorCount) + " error";
222        if (fErrorCount > 1) {
223            fErrorText += "s";
224        }
225        fErrorText += "\n";
226    }
227}
228
229bool Compiler::toSPIRV(Program::Kind kind, const std::string& text, std::ostream& out) {
230    auto program = this->convertProgram(kind, text);
231    if (fErrorCount == 0) {
232        SkSL::SPIRVCodeGenerator cg(&fContext);
233        cg.generateCode(*program.get(), out);
234        ASSERT(!out.rdstate());
235    }
236    return fErrorCount == 0;
237}
238
239bool Compiler::toSPIRV(Program::Kind kind, const std::string& text, std::string* out) {
240    std::stringstream buffer;
241    bool result = this->toSPIRV(kind, text, buffer);
242    if (result) {
243        *out = buffer.str();
244    }
245    return result;
246}
247
248bool Compiler::toGLSL(Program::Kind kind, const std::string& text, GLCaps caps,
249                      std::ostream& out) {
250    auto program = this->convertProgram(kind, text);
251    if (fErrorCount == 0) {
252        SkSL::GLSLCodeGenerator cg(&fContext, caps);
253        cg.generateCode(*program.get(), out);
254        ASSERT(!out.rdstate());
255    }
256    return fErrorCount == 0;
257}
258
259bool Compiler::toGLSL(Program::Kind kind, const std::string& text, GLCaps caps,
260                      std::string* out) {
261    std::stringstream buffer;
262    bool result = this->toGLSL(kind, text, caps, buffer);
263    if (result) {
264        *out = buffer.str();
265    }
266    return result;
267}
268
269} // namespace
270