• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
21 static const bool gPrintSKSL = false;
22 static const bool gPrintGLSL = false;
23 
print_source_lines_with_numbers(const char * source,std::function<void (const char *)> println)24 static 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.
print_sksl_line_by_line(const char ** skslStrings,int * lengths,int count,std::function<void (const char *)> println=[](const char * ln){})36 static 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 
print_glsl_line_by_line(const SkSL::String & glsl,std::function<void (const char *)> println=[](const char * ln){})45 static 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 
print_shader_banner(GrGLenum type)53 void 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 
GrSkSLtoGLSL(const GrGLContext & context,GrGLenum type,const char ** skslStrings,int * lengths,int count,const SkSL::Program::Settings & settings,SkSL::String * glsl)63 std::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 
GrGLCompileAndAttachShader(const GrGLContext & glCtx,GrGLuint programId,GrGLenum type,const char * glsl,int glslLength,GrGpu::Stats * stats,const SkSL::Program::Settings & settings)113 GrGLuint 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             // In Chrome we may have failed due to context-loss. So we should just continue along
156             // wihthout asserting until the GrContext gets abandoned.
157             if (kChromium_GrGLDriver != glCtx.driver()) {
158                 SkDEBUGFAIL("GLSL compilation failed!");
159             }
160             GR_GL_CALL(gli, DeleteShader(shaderId));
161             return 0;
162         }
163     }
164 
165     if (gPrintGLSL) {
166         print_shader_banner(type);
167         print_glsl_line_by_line(glsl);
168     }
169 
170     // Attach the shader, but defer deletion until after we have linked the program.
171     // This works around a bug in the Android emulator's GLES2 wrapper which
172     // will immediately delete the shader object and free its memory even though it's
173     // attached to a program, which then causes glLinkProgram to fail.
174     GR_GL_CALL(gli, AttachShader(programId, shaderId));
175     return shaderId;
176 }
177 
GrGLPrintShader(const GrGLContext & context,GrGLenum type,const char ** skslStrings,int * lengths,int count,const SkSL::Program::Settings & settings)178 void GrGLPrintShader(const GrGLContext& context, GrGLenum type, const char** skslStrings,
179                      int* lengths, int count, const SkSL::Program::Settings& settings) {
180     print_sksl_line_by_line(skslStrings, lengths, count);
181     SkSL::String glsl;
182     if (GrSkSLtoGLSL(context, type, skslStrings, lengths, count, settings, &glsl)) {
183         print_glsl_line_by_line(glsl);
184     }
185 }
186