1/*
2 * Copyright 2014 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 "GrGLShaderStringBuilder.h"
9#include "GrSKSLPrettyPrint.h"
10#include "SkAutoMalloc.h"
11#include "SkSLCompiler.h"
12#include "SkSLGLSLCodeGenerator.h"
13#include "SkTraceEvent.h"
14#include "gl/GrGLGpu.h"
15#include "ir/SkSLProgram.h"
16
17#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
18#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
19
20// Print the source code for all shaders generated.
21static const bool gPrintSKSL = false;
22static const bool gPrintGLSL = false;
23
24static void print_source_lines_with_numbers(const char* source,
25                                            std::function<void(const char*)> println) {
26    SkTArray<SkString> lines;
27    SkStrSplit(source, "\n", kStrict_SkStrSplitMode, &lines);
28    for (int i = 0; i < lines.count(); ++i) {
29        SkString& line = lines[i];
30        line.prependf("%4i\t", i + 1);
31        println(line.c_str());
32    }
33}
34
35// Prints shaders one line at the time. This ensures they don't get truncated by the adb log.
36static void print_sksl_line_by_line(const char** skslStrings, int* lengths, int count,
37                                    std::function<void(const char*)> println = [](const char* ln) {
38                                        SkDebugf("%s\n", ln);
39                                    }) {
40    SkSL::String sksl = GrSKSLPrettyPrint::PrettyPrint(skslStrings, lengths, count, false);
41    println("SKSL:");
42    print_source_lines_with_numbers(sksl.c_str(), println);
43}
44
45static void print_glsl_line_by_line(const SkSL::String& glsl,
46                                    std::function<void(const char*)> println = [](const char* ln) {
47                                        SkDebugf("%s\n", ln);
48                                    }) {
49    println("GLSL:");
50    print_source_lines_with_numbers(glsl.c_str(), println);
51}
52
53void print_shader_banner(GrGLenum type) {
54    const char* typeName = "Unknown";
55    switch (type) {
56        case GR_GL_VERTEX_SHADER: typeName = "Vertex"; break;
57        case GR_GL_GEOMETRY_SHADER: typeName = "Geometry"; break;
58        case GR_GL_FRAGMENT_SHADER: typeName = "Fragment"; break;
59    }
60    SkDebugf("---- %s shader ----------------------------------------------------\n", typeName);
61}
62
63std::unique_ptr<SkSL::Program> GrSkSLtoGLSL(const GrGLContext& context, GrGLenum type,
64                                            const char** skslStrings, int* lengths, int count,
65                                            const SkSL::Program::Settings& settings,
66                                            SkSL::String* glsl) {
67    // Trace event for shader preceding driver compilation
68    bool traceShader;
69    TRACE_EVENT_CATEGORY_GROUP_ENABLED("skia.gpu", &traceShader);
70    if (traceShader) {
71        SkString shaderDebugString;
72        print_sksl_line_by_line(skslStrings, lengths, count, [&](const char* ln) {
73            shaderDebugString.append(ln);
74            shaderDebugString.append("\n");
75        });
76        TRACE_EVENT_INSTANT1("skia.gpu", "skia_gpu::GLShader",
77                             TRACE_EVENT_SCOPE_THREAD, "shader",
78                             TRACE_STR_COPY(shaderDebugString.c_str()));
79    }
80
81    SkSL::String sksl;
82#ifdef SK_DEBUG
83    sksl = GrSKSLPrettyPrint::PrettyPrint(skslStrings, lengths, count, false);
84#else
85    for (int i = 0; i < count; i++) {
86        sksl.append(skslStrings[i], lengths[i]);
87    }
88#endif
89    SkSL::Compiler* compiler = context.compiler();
90    std::unique_ptr<SkSL::Program> program;
91    SkSL::Program::Kind programKind;
92    switch (type) {
93        case GR_GL_VERTEX_SHADER:   programKind = SkSL::Program::kVertex_Kind;   break;
94        case GR_GL_FRAGMENT_SHADER: programKind = SkSL::Program::kFragment_Kind; break;
95        case GR_GL_GEOMETRY_SHADER: programKind = SkSL::Program::kGeometry_Kind; break;
96        default: SK_ABORT("unsupported shader kind");
97    }
98    program = compiler->convertProgram(programKind, sksl, settings);
99    if (!program || !compiler->toGLSL(*program, glsl)) {
100        SkDebugf("SKSL compilation error\n----------------------\n");
101        print_sksl_line_by_line(skslStrings, lengths, count);
102        SkDebugf("\nErrors:\n%s\n", compiler->errorText().c_str());
103        SkDEBUGFAIL("SKSL compilation failed!\n");
104        return nullptr;
105    }
106    if (gPrintSKSL) {
107        print_shader_banner(type);
108        print_sksl_line_by_line(skslStrings, lengths, count);
109    }
110    return program;
111}
112
113GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
114                                    GrGLuint programId,
115                                    GrGLenum type,
116                                    const char* glsl,
117                                    int glslLength,
118                                    GrGpu::Stats* stats,
119                                    const SkSL::Program::Settings& settings) {
120    const GrGLInterface* gli = glCtx.interface();
121
122    // Specify GLSL source to the driver.
123    GrGLuint shaderId;
124    GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
125    if (0 == shaderId) {
126        return 0;
127    }
128    GR_GL_CALL(gli, ShaderSource(shaderId, 1, &glsl, &glslLength));
129
130    stats->incShaderCompilations();
131    GR_GL_CALL(gli, CompileShader(shaderId));
132
133    // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds.
134    bool checkCompiled = kChromium_GrGLDriver != glCtx.driver();
135#ifdef SK_DEBUG
136    checkCompiled = true;
137#endif
138    if (checkCompiled) {
139        GrGLint compiled = GR_GL_INIT_ZERO;
140        GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
141
142        if (!compiled) {
143            SkDebugf("GLSL compilation error\n----------------------\n");
144            print_glsl_line_by_line(glsl);
145            GrGLint infoLen = GR_GL_INIT_ZERO;
146            GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
147            SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
148            if (infoLen > 0) {
149                // retrieve length even though we don't need it to workaround bug in Chromium cmd
150                // buffer param validation.
151                GrGLsizei length = GR_GL_INIT_ZERO;
152                GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
153                SkDebugf("Errors:\n%s\n", (const char*) log.get());
154            }
155            SkDEBUGFAIL("GLSL compilation failed!");
156            GR_GL_CALL(gli, DeleteShader(shaderId));
157            return 0;
158        }
159    }
160
161    if (gPrintGLSL) {
162        print_shader_banner(type);
163        print_glsl_line_by_line(glsl);
164    }
165
166    // Attach the shader, but defer deletion until after we have linked the program.
167    // This works around a bug in the Android emulator's GLES2 wrapper which
168    // will immediately delete the shader object and free its memory even though it's
169    // attached to a program, which then causes glLinkProgram to fail.
170    GR_GL_CALL(gli, AttachShader(programId, shaderId));
171    return shaderId;
172}
173
174void GrGLPrintShader(const GrGLContext& context, GrGLenum type, const char** skslStrings,
175                     int* lengths, int count, const SkSL::Program::Settings& settings) {
176    print_sksl_line_by_line(skslStrings, lengths, count);
177    SkSL::String glsl;
178    if (GrSkSLtoGLSL(context, type, skslStrings, lengths, count, settings, &glsl)) {
179        print_glsl_line_by_line(glsl);
180    }
181}
182