• 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 "SkAutoMalloc.h"
10 #include "SkSLCompiler.h"
11 #include "SkSLGLSLCodeGenerator.h"
12 #include "SkTraceEvent.h"
13 #include "gl/GrGLGpu.h"
14 #include "gl/GrGLSLPrettyPrint.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 c_PrintShaders{false};
22 
23 static void print_source_with_line_numbers(const SkString&);
24 
GrGLCompileAndAttachShader(const GrGLContext & glCtx,GrGLuint programId,GrGLenum type,const char ** strings,int * lengths,int count,GrGpu::Stats * stats,const SkSL::Program::Settings & settings,SkSL::Program::Inputs * outInputs)25 GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
26                                     GrGLuint programId,
27                                     GrGLenum type,
28                                     const char** strings,
29                                     int* lengths,
30                                     int count,
31                                     GrGpu::Stats* stats,
32                                     const SkSL::Program::Settings& settings,
33                                     SkSL::Program::Inputs* outInputs) {
34     const GrGLInterface* gli = glCtx.interface();
35 
36     GrGLuint shaderId;
37     GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
38     if (0 == shaderId) {
39         return 0;
40     }
41 
42     SkString sksl;
43 #ifdef SK_DEBUG
44     sksl = GrGLSLPrettyPrint::PrettyPrintGLSL(strings, lengths, count, false);
45 #else
46     for (int i = 0; i < count; i++) {
47         sksl.append(strings[i], lengths[i]);
48     }
49 #endif
50 
51     SkString glsl;
52     if (type == GR_GL_VERTEX_SHADER || type == GR_GL_FRAGMENT_SHADER) {
53         SkSL::Compiler& compiler = *glCtx.compiler();
54         std::unique_ptr<SkSL::Program> program;
55         program = compiler.convertProgram(
56                                         type == GR_GL_VERTEX_SHADER ? SkSL::Program::kVertex_Kind
57                                                                     : SkSL::Program::kFragment_Kind,
58                                         sksl,
59                                         settings);
60         if (!program || !compiler.toGLSL(*program, &glsl)) {
61             SkDebugf("SKSL compilation error\n----------------------\n");
62             SkDebugf("SKSL:\n");
63             print_source_with_line_numbers(sksl);
64             SkDebugf("\nErrors:\n%s\n", compiler.errorText().c_str());
65             SkDEBUGFAIL("SKSL compilation failed!\n");
66         }
67         *outInputs = program->fInputs;
68     } else {
69         // TODO: geometry shader support in sksl.
70         SkASSERT(type == GR_GL_GEOMETRY_SHADER);
71         glsl = sksl;
72     }
73 
74     const char* glslChars = glsl.c_str();
75     GrGLint glslLength = (GrGLint) glsl.size();
76     GR_GL_CALL(gli, ShaderSource(shaderId, 1, &glslChars, &glslLength));
77 
78     // If tracing is enabled in chrome then we pretty print
79     bool traceShader;
80     TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), &traceShader);
81     if (traceShader) {
82         SkString shader = GrGLSLPrettyPrint::PrettyPrintGLSL(strings, lengths, count, false);
83         TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLShader",
84                              TRACE_EVENT_SCOPE_THREAD, "shader", TRACE_STR_COPY(shader.c_str()));
85     }
86 
87     stats->incShaderCompilations();
88     GR_GL_CALL(gli, CompileShader(shaderId));
89 
90     // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds.
91     bool checkCompiled = kChromium_GrGLDriver != glCtx.driver();
92 #ifdef SK_DEBUG
93     checkCompiled = true;
94 #endif
95     if (checkCompiled) {
96         GrGLint compiled = GR_GL_INIT_ZERO;
97         GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
98 
99         if (!compiled) {
100             GrGLint infoLen = GR_GL_INIT_ZERO;
101             GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
102             SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
103             if (infoLen > 0) {
104                 // retrieve length even though we don't need it to workaround bug in Chromium cmd
105                 // buffer param validation.
106                 GrGLsizei length = GR_GL_INIT_ZERO;
107                 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
108                 SkDebugf("GLSL compilation error\n----------------------\n");
109                 SkDebugf("SKSL:\n");
110                 print_source_with_line_numbers(sksl);
111                 SkDebugf("GLSL:\n");
112                 print_source_with_line_numbers(glsl);
113                 SkDebugf("Errors:\n%s\n", (const char*) log.get());
114             }
115             SkDEBUGFAIL("GLSL compilation failed!");
116             GR_GL_CALL(gli, DeleteShader(shaderId));
117             return 0;
118         }
119     }
120 
121     if (c_PrintShaders) {
122         const char* typeName = "Unknown";
123         switch (type) {
124             case GR_GL_VERTEX_SHADER: typeName = "Vertex"; break;
125             case GR_GL_GEOMETRY_SHADER: typeName = "Geometry"; break;
126             case GR_GL_FRAGMENT_SHADER: typeName = "Fragment"; break;
127         }
128         SkDebugf("---- %s shader ----------------------------------------------------\n", typeName);
129         print_source_with_line_numbers(sksl);
130     }
131 
132     // Attach the shader, but defer deletion until after we have linked the program.
133     // This works around a bug in the Android emulator's GLES2 wrapper which
134     // will immediately delete the shader object and free its memory even though it's
135     // attached to a program, which then causes glLinkProgram to fail.
136     GR_GL_CALL(gli, AttachShader(programId, shaderId));
137 
138     return shaderId;
139 }
140 
print_source_with_line_numbers(const SkString & source)141 static void print_source_with_line_numbers(const SkString& source) {
142     SkTArray<SkString> lines;
143     SkStrSplit(source.c_str(), "\n", kStrict_SkStrSplitMode, &lines);
144     for (int line = 0; line < lines.count(); ++line) {
145         // Print the shader one line at the time so it doesn't get truncated by the adb log.
146         SkDebugf("%4i\t%s\n", line + 1, lines[line].c_str());
147     }
148 }
149