blob: b26ce894f0246b35dbf6a0ecfcb266a89eedda43 [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
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"
joshualittdd219872015-02-12 14:48:42 -08009#include "gl/GrGLGpu.h"
joshualitt30ba4362014-08-21 20:18:45 -070010#include "gl/GrGLSLPrettyPrint.h"
joshualitt30ba4362014-08-21 20:18:45 -070011#include "SkTraceEvent.h"
ethannicholasdcfe6db2016-10-10 10:09:00 -070012#include "SkSLCompiler.h"
13#include "SkSLGLSLCodeGenerator.h"
14#include "ir/SkSLProgram.h"
joshualitt30ba4362014-08-21 20:18:45 -070015
16#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
17#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
18
halcanary4e44efe2016-08-04 10:47:16 -070019// Print the source code for all shaders generated.
20static const bool c_PrintShaders{false};
joshualitt30ba4362014-08-21 20:18:45 -070021
csmartdaltonb3772dc2016-07-13 08:47:54 -070022static void print_shader_source(const char** strings, int* lengths, int count);
23
ethannicholasdcfe6db2016-10-10 10:09:00 -070024SkSL::GLCaps GrGLSkSLCapsForContext(const GrGLContext& context) {
25 GrGLStandard standard = context.standard();
26 const GrGLCaps* caps = context.caps();
27 const GrGLSLCaps* glslCaps = caps->glslCaps();
28 SkSL::GLCaps result;
29 switch (standard) {
30 case kGL_GrGLStandard:
31 result.fStandard = SkSL::GLCaps::kGL_Standard;
32 break;
33 case kGLES_GrGLStandard:
34 result.fStandard = SkSL::GLCaps::kGLES_Standard;
35 break;
36 default:
37 SkASSERT(false);
38 result.fStandard = SkSL::GLCaps::kGL_Standard;
39 }
40
41 switch (glslCaps->generation()) {
42 case k110_GrGLSLGeneration:
43 if (kGLES_GrGLStandard == standard) {
44 // ES2's shader language is based on GLSL 1.20 but is version 1.00 of the ES
45 // language
46 result.fVersion = 100;
47 } else {
48 SkASSERT(kGL_GrGLStandard == standard);
49 result.fVersion = 110;
50 }
51 break;
52 case k130_GrGLSLGeneration:
53 SkASSERT(kGL_GrGLStandard == standard);
54 result.fVersion = 130;
55 break;
56 case k140_GrGLSLGeneration:
57 SkASSERT(kGL_GrGLStandard == standard);
58 result.fVersion = 140;
59 break;
60 case k150_GrGLSLGeneration:
61 SkASSERT(kGL_GrGLStandard == standard);
62 result.fVersion = 150;
63 break;
64 case k330_GrGLSLGeneration:
65 if (kGLES_GrGLStandard == standard) {
66 result.fVersion = 300;
67 } else {
68 SkASSERT(kGL_GrGLStandard == standard);
69 result.fVersion = 330;
70 }
71 break;
72 case k400_GrGLSLGeneration:
73 SkASSERT(kGL_GrGLStandard == standard);
74 result.fVersion = 400;
75 break;
76 case k310es_GrGLSLGeneration:
77 SkASSERT(kGLES_GrGLStandard == standard);
78 result.fVersion = 310;
79 break;
80 case k320es_GrGLSLGeneration:
81 SkASSERT(kGLES_GrGLStandard == standard);
82 result.fVersion = 320;
83 break;
84 }
85 result.fIsCoreProfile = caps->isCoreProfile();
86 result.fUsesPrecisionModifiers = glslCaps->usesPrecisionModifiers();
87 result.fMustDeclareFragmentShaderOutput = glslCaps->mustDeclareFragmentShaderOutput();
88 result.fCanUseMinAndAbsTogether = glslCaps->canUseMinAndAbsTogether();
89 return result;
90}
91
92static void dump_string(std::string s) {
93 // on Android, SkDebugf only displays the first 1K characters of output, which results in
94 // incomplete shader source code. Print each line individually to avoid this problem.
95 size_t index = 0;
96 for (;;) {
97 size_t next = s.find("\n", index);
98 if (next == std::string::npos) {
99 SkDebugf("%s", s.substr(index).c_str());
100 break;
101 } else {
102 SkDebugf("%s", s.substr(index, next - index + 1).c_str());
103 index = next + 1;
104 }
105 }
106}
107
joshualitt30ba4362014-08-21 20:18:45 -0700108GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
109 GrGLuint programId,
110 GrGLenum type,
joshualitt43466a12015-02-13 17:18:27 -0800111 const char** strings,
112 int* lengths,
113 int count,
mtkleinb9eb4ac2015-02-02 18:26:03 -0800114 GrGpu::Stats* stats) {
joshualitt30ba4362014-08-21 20:18:45 -0700115 const GrGLInterface* gli = glCtx.interface();
116
robertphillips754f4e92014-09-18 13:52:08 -0700117 GrGLuint shaderId;
118 GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
119 if (0 == shaderId) {
120 return 0;
121 }
joshualitt30ba4362014-08-21 20:18:45 -0700122
ethannicholasdcfe6db2016-10-10 10:09:00 -0700123 std::string sksl;
robertphillips754f4e92014-09-18 13:52:08 -0700124#ifdef SK_DEBUG
joshualitt43466a12015-02-13 17:18:27 -0800125 SkString prettySource = GrGLSLPrettyPrint::PrettyPrintGLSL(strings, lengths, count, false);
ethannicholasdcfe6db2016-10-10 10:09:00 -0700126 sksl = std::string(prettySource.c_str());
joshualitt43466a12015-02-13 17:18:27 -0800127#else
ethannicholasdcfe6db2016-10-10 10:09:00 -0700128 for (int i = 0; i < count; i++) {
129 sksl.append(strings[i], lengths[i]);
130 }
joshualitt43466a12015-02-13 17:18:27 -0800131#endif
132
ethannicholasdcfe6db2016-10-10 10:09:00 -0700133 std::string glsl;
134 SkSL::Compiler& compiler = *glCtx.compiler();
135 SkSL::GLCaps caps = GrGLSkSLCapsForContext(glCtx);
136 SkASSERT(type == GR_GL_VERTEX_SHADER || type == GR_GL_FRAGMENT_SHADER);
137 SkDEBUGCODE(bool result = )compiler.toGLSL(type == GR_GL_VERTEX_SHADER
138 ? SkSL::Program::kVertex_Kind
139 : SkSL::Program::kFragment_Kind,
140 std::string(sksl.c_str()),
141 caps,
142 &glsl);
143#ifdef SK_DEBUG
144 if (!result) {
145 SkDebugf("SKSL compilation error\n----------------------\n");
146 SkDebugf("SKSL:\n");
147 dump_string(sksl);
148 SkDebugf("\nErrors:\n%s\n", compiler.errorText().c_str());
149 SkDEBUGFAIL("SKSL compilation failed!\n");
150 }
151#endif
152
153 const char* glslChars = glsl.c_str();
154 GrGLint glslLength = (GrGLint) glsl.length();
155 GR_GL_CALL(gli, ShaderSource(shaderId, 1, &glslChars, &glslLength));
156
joshualitt43466a12015-02-13 17:18:27 -0800157 // If tracing is enabled in chrome then we pretty print
158 bool traceShader;
159 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), &traceShader);
160 if (traceShader) {
161 SkString shader = GrGLSLPrettyPrint::PrettyPrintGLSL(strings, lengths, count, false);
162 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLShader",
163 TRACE_EVENT_SCOPE_THREAD, "shader", TRACE_STR_COPY(shader.c_str()));
164 }
165
mtkleinb9eb4ac2015-02-02 18:26:03 -0800166 stats->incShaderCompilations();
robertphillips754f4e92014-09-18 13:52:08 -0700167 GR_GL_CALL(gli, CompileShader(shaderId));
joshualitt30ba4362014-08-21 20:18:45 -0700168
robertphillips754f4e92014-09-18 13:52:08 -0700169 // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds.
cdalton1acea862015-06-02 13:05:52 -0700170 bool checkCompiled = kChromium_GrGLDriver != glCtx.driver();
robertphillips754f4e92014-09-18 13:52:08 -0700171#ifdef SK_DEBUG
172 checkCompiled = true;
173#endif
174 if (checkCompiled) {
175 GrGLint compiled = GR_GL_INIT_ZERO;
176 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
joshualitt30ba4362014-08-21 20:18:45 -0700177
robertphillips754f4e92014-09-18 13:52:08 -0700178 if (!compiled) {
179 GrGLint infoLen = GR_GL_INIT_ZERO;
180 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
181 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
182 if (infoLen > 0) {
183 // retrieve length even though we don't need it to workaround bug in Chromium cmd
184 // buffer param validation.
185 GrGLsizei length = GR_GL_INIT_ZERO;
joshualitt43466a12015-02-13 17:18:27 -0800186 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
ethannicholasdcfe6db2016-10-10 10:09:00 -0700187 SkDebugf("GLSL compilation error\n----------------------\n");
188 SkDebugf("SKSL:\n");
189 dump_string(sksl);
190 SkDebugf("GLSL:\n");
191 dump_string(glsl);
192 SkDebugf("Errors:\n%s\n", (const char*) log.get());
robertphillips754f4e92014-09-18 13:52:08 -0700193 }
ethannicholasdcfe6db2016-10-10 10:09:00 -0700194 SkDEBUGFAIL("GLSL compilation failed!");
robertphillips754f4e92014-09-18 13:52:08 -0700195 GR_GL_CALL(gli, DeleteShader(shaderId));
196 return 0;
197 }
198 }
joshualitt30ba4362014-08-21 20:18:45 -0700199
robertphillips754f4e92014-09-18 13:52:08 -0700200 if (c_PrintShaders) {
csmartdaltonb3772dc2016-07-13 08:47:54 -0700201 print_shader_source(strings, lengths, count);
robertphillips754f4e92014-09-18 13:52:08 -0700202 }
joshualitt30ba4362014-08-21 20:18:45 -0700203
robertphillips754f4e92014-09-18 13:52:08 -0700204 // Attach the shader, but defer deletion until after we have linked the program.
205 // This works around a bug in the Android emulator's GLES2 wrapper which
206 // will immediately delete the shader object and free its memory even though it's
207 // attached to a program, which then causes glLinkProgram to fail.
208 GR_GL_CALL(gli, AttachShader(programId, shaderId));
joshualitt30ba4362014-08-21 20:18:45 -0700209
robertphillips754f4e92014-09-18 13:52:08 -0700210 return shaderId;
joshualitt30ba4362014-08-21 20:18:45 -0700211}
csmartdaltonb3772dc2016-07-13 08:47:54 -0700212
213static void print_shader_source(const char** strings, int* lengths, int count) {
214 const SkString& pretty = GrGLSLPrettyPrint::PrettyPrintGLSL(strings, lengths, count, true);
215 SkTArray<SkString> lines;
216 SkStrSplit(pretty.c_str(), "\n", &lines);
217 for (const SkString& line : lines) {
218 // Print the shader one line at the time so it doesn't get truncated by the adb log.
219 SkDebugf("%s\n", line.c_str());
220 }
221}