Line data Source code
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 :
25 0 : 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 0 : const GrGLInterface* gli = glCtx.interface();
35 :
36 : GrGLuint shaderId;
37 0 : GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
38 0 : if (0 == shaderId) {
39 0 : return 0;
40 : }
41 :
42 0 : SkString sksl;
43 : #ifdef SK_DEBUG
44 0 : 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 0 : SkSL::String glsl;
52 0 : if (type == GR_GL_VERTEX_SHADER || type == GR_GL_FRAGMENT_SHADER) {
53 0 : SkSL::Compiler& compiler = *glCtx.compiler();
54 0 : std::unique_ptr<SkSL::Program> program;
55 0 : program = compiler.convertProgram(
56 : type == GR_GL_VERTEX_SHADER ? SkSL::Program::kVertex_Kind
57 : : SkSL::Program::kFragment_Kind,
58 : sksl,
59 0 : settings);
60 0 : if (!program || !compiler.toGLSL(*program, &glsl)) {
61 0 : SkDebugf("SKSL compilation error\n----------------------\n");
62 0 : SkDebugf("SKSL:\n");
63 0 : print_source_with_line_numbers(sksl);
64 0 : SkDebugf("\nErrors:\n%s\n", compiler.errorText().c_str());
65 0 : SkDEBUGFAIL("SKSL compilation failed!\n");
66 : }
67 0 : *outInputs = program->fInputs;
68 : } else {
69 : // TODO: geometry shader support in sksl.
70 0 : SkASSERT(type == GR_GL_GEOMETRY_SHADER);
71 0 : glsl = sksl;
72 : }
73 :
74 0 : const char* glslChars = glsl.c_str();
75 0 : GrGLint glslLength = (GrGLint) glsl.size();
76 0 : 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 0 : TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), &traceShader);
81 0 : if (traceShader) {
82 0 : SkString shader = GrGLSLPrettyPrint::PrettyPrintGLSL(strings, lengths, count, false);
83 0 : 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 0 : stats->incShaderCompilations();
88 0 : GR_GL_CALL(gli, CompileShader(shaderId));
89 :
90 : // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds.
91 0 : bool checkCompiled = kChromium_GrGLDriver != glCtx.driver();
92 : #ifdef SK_DEBUG
93 0 : checkCompiled = true;
94 : #endif
95 0 : if (checkCompiled) {
96 0 : GrGLint compiled = GR_GL_INIT_ZERO;
97 0 : GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
98 :
99 0 : if (!compiled) {
100 0 : GrGLint infoLen = GR_GL_INIT_ZERO;
101 0 : GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
102 0 : SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
103 0 : if (infoLen > 0) {
104 : // retrieve length even though we don't need it to workaround bug in Chromium cmd
105 : // buffer param validation.
106 0 : GrGLsizei length = GR_GL_INIT_ZERO;
107 0 : GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
108 0 : SkDebugf("GLSL compilation error\n----------------------\n");
109 0 : SkDebugf("SKSL:\n");
110 0 : print_source_with_line_numbers(sksl);
111 0 : SkDebugf("GLSL:\n");
112 0 : print_source_with_line_numbers(glsl);
113 0 : SkDebugf("Errors:\n%s\n", (const char*) log.get());
114 : }
115 0 : SkDEBUGFAIL("GLSL compilation failed!");
116 0 : GR_GL_CALL(gli, DeleteShader(shaderId));
117 0 : 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 0 : GR_GL_CALL(gli, AttachShader(programId, shaderId));
137 :
138 0 : return shaderId;
139 : }
140 :
141 0 : static void print_source_with_line_numbers(const SkString& source) {
142 0 : SkTArray<SkString> lines;
143 0 : SkStrSplit(source.c_str(), "\n", kStrict_SkStrSplitMode, &lines);
144 0 : 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 0 : SkDebugf("%4i\t%s\n", line + 1, lines[line].c_str());
147 : }
148 0 : }
|