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