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 "src/base/SkAutoMalloc.h"
9 #include "src/core/SkTraceEvent.h"
10 #include "src/gpu/ganesh/gl/GrGLGpu.h"
11 #include "src/gpu/ganesh/gl/builders/GrGLShaderStringBuilder.h"
12 #include "src/sksl/SkSLCompiler.h"
13 #include "src/sksl/SkSLProgramSettings.h"
14 #include "src/sksl/codegen/SkSLGLSLCodeGenerator.h"
15 #include "src/sksl/ir/SkSLProgram.h"
16 #include "src/utils/SkShaderUtils.h"
17
18 // Print the source code for all shaders generated.
19 static const bool gPrintSKSL = false;
20 static const bool gPrintGLSL = false;
21
GrSkSLtoGLSL(const GrGLGpu * gpu,SkSL::ProgramKind programKind,const std::string & sksl,const SkSL::ProgramSettings & settings,std::string * glsl,GrContextOptions::ShaderErrorHandler * errorHandler)22 std::unique_ptr<SkSL::Program> GrSkSLtoGLSL(const GrGLGpu* gpu,
23 SkSL::ProgramKind programKind,
24 const std::string& sksl,
25 const SkSL::ProgramSettings& settings,
26 std::string* glsl,
27 GrContextOptions::ShaderErrorHandler* errorHandler) {
28 SkSL::Compiler* compiler = gpu->shaderCompiler();
29 std::unique_ptr<SkSL::Program> program;
30 #ifdef SK_DEBUG
31 std::string src = SkShaderUtils::PrettyPrint(sksl);
32 #else
33 const std::string& src = sksl;
34 #endif
35 program = compiler->convertProgram(programKind, src, settings);
36 if (!program || !compiler->toGLSL(*program, glsl)) {
37 errorHandler->compileError(src.c_str(), compiler->errorText().c_str());
38 return nullptr;
39 }
40
41 if (gPrintSKSL || gPrintGLSL) {
42 SkShaderUtils::PrintShaderBanner(programKind);
43 if (gPrintSKSL) {
44 SkDebugf("SKSL:\n");
45 SkShaderUtils::PrintLineByLine(SkShaderUtils::PrettyPrint(sksl));
46 }
47 if (gPrintGLSL) {
48 SkDebugf("GLSL:\n");
49 SkShaderUtils::PrintLineByLine(SkShaderUtils::PrettyPrint(*glsl));
50 }
51 }
52
53 return program;
54 }
55
GrGLCompileAndAttachShader(const GrGLContext & glCtx,GrGLuint programId,GrGLenum type,const std::string & glsl,GrThreadSafePipelineBuilder::Stats * stats,GrContextOptions::ShaderErrorHandler * errorHandler)56 GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
57 GrGLuint programId,
58 GrGLenum type,
59 const std::string& glsl,
60 GrThreadSafePipelineBuilder::Stats* stats,
61 GrContextOptions::ShaderErrorHandler* errorHandler) {
62 TRACE_EVENT0_ALWAYS("skia.shaders", "driver_compile_shader");
63 const GrGLInterface* gli = glCtx.glInterface();
64
65 // Specify GLSL source to the driver.
66 GrGLuint shaderId;
67 GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
68 if (0 == shaderId) {
69 return 0;
70 }
71 const GrGLchar* source = glsl.c_str();
72 GrGLint sourceLength = SkToInt(glsl.size());
73 GR_GL_CALL(gli, ShaderSource(shaderId, 1, &source, &sourceLength));
74
75 stats->incShaderCompilations();
76 GR_GL_CALL(gli, CompileShader(shaderId));
77
78 {
79 ATRACE_ANDROID_FRAMEWORK("checkCompiled");
80 GrGLint compiled = GR_GL_INIT_ZERO;
81 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
82
83 if (!compiled) {
84 GrGLint infoLen = GR_GL_INIT_ZERO;
85 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
86 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
87 if (infoLen > 0) {
88 // retrieve length even though we don't need it to workaround bug in Chromium cmd
89 // buffer param validation.
90 GrGLsizei length = GR_GL_INIT_ZERO;
91 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
92 }
93 errorHandler->compileError(glsl.c_str(), infoLen > 0 ? (const char*)log.get() : "");
94 GR_GL_CALL(gli, DeleteShader(shaderId));
95 return 0;
96 }
97 }
98
99 // Attach the shader, but defer deletion until after we have linked the program.
100 // This works around a bug in the Android emulator's GLES2 wrapper which
101 // will immediately delete the shader object and free its memory even though it's
102 // attached to a program, which then causes glLinkProgram to fail.
103 GR_GL_CALL(gli, AttachShader(programId, shaderId));
104 return shaderId;
105 }
106
GrGLCheckLinkStatus(const GrGLGpu * gpu,GrGLuint programID,GrContextOptions::ShaderErrorHandler * errorHandler,const std::string * sksl[kGrShaderTypeCount],const std::string glsl[kGrShaderTypeCount])107 bool GrGLCheckLinkStatus(const GrGLGpu* gpu,
108 GrGLuint programID,
109 GrContextOptions::ShaderErrorHandler* errorHandler,
110 const std::string* sksl[kGrShaderTypeCount],
111 const std::string glsl[kGrShaderTypeCount]) {
112 const GrGLInterface* gli = gpu->glInterface();
113
114 GrGLint linked = GR_GL_INIT_ZERO;
115 GR_GL_CALL(gli, GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
116 if (!linked && errorHandler) {
117 std::string allShaders;
118 if (sksl) {
119 SkSL::String::appendf(&allShaders, "// Vertex SKSL\n%s\n"
120 "// Fragment SKSL\n%s\n",
121 sksl[kVertex_GrShaderType]->c_str(),
122 sksl[kFragment_GrShaderType]->c_str());
123 }
124 if (glsl) {
125 SkSL::String::appendf(&allShaders, "// Vertex GLSL\n%s\n"
126 "// Fragment GLSL\n%s\n",
127 glsl[kVertex_GrShaderType].c_str(),
128 glsl[kFragment_GrShaderType].c_str());
129 }
130 GrGLint infoLen = GR_GL_INIT_ZERO;
131 GR_GL_CALL(gli, GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
132 SkAutoMalloc log(infoLen+1);
133 if (infoLen > 0) {
134 // retrieve length even though we don't need it to workaround
135 // bug in chrome cmd buffer param validation.
136 GrGLsizei length = GR_GL_INIT_ZERO;
137 GR_GL_CALL(gli, GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get()));
138 }
139 const char* errorMsg = (infoLen > 0) ? (const char*)log.get()
140 : "link failed but did not provide an info log";
141 errorHandler->compileError(allShaders.c_str(), errorMsg);
142 }
143 return SkToBool(linked);
144 }
145