• 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 "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