blob: 473414e34e4b850e250890691652e18d11cf431b [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/core/SkAutoMalloc.h"
Brian Osmanac9be9d2019-05-01 10:29:34 -04009#include "src/gpu/GrShaderUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/gpu/gl/GrGLGpu.h"
11#include "src/gpu/gl/builders/GrGLShaderStringBuilder.h"
12#include "src/sksl/SkSLCompiler.h"
13#include "src/sksl/SkSLGLSLCodeGenerator.h"
14#include "src/sksl/ir/SkSLProgram.h"
joshualitt30ba4362014-08-21 20:18:45 -070015
halcanary4e44efe2016-08-04 10:47:16 -070016// Print the source code for all shaders generated.
Brian Salomon06ab3832017-12-04 16:45:30 -050017static const bool gPrintSKSL = false;
18static const bool gPrintGLSL = false;
joshualitt30ba4362014-08-21 20:18:45 -070019
Brian Osmanac9be9d2019-05-01 10:29:34 -040020void print_shader_banner(SkSL::Program::Kind programKind) {
Brian Salomon06ab3832017-12-04 16:45:30 -050021 const char* typeName = "Unknown";
Brian Osmanac9be9d2019-05-01 10:29:34 -040022 switch (programKind) {
23 case SkSL::Program::kVertex_Kind: typeName = "Vertex"; break;
24 case SkSL::Program::kGeometry_Kind: typeName = "Geometry"; break;
25 case SkSL::Program::kFragment_Kind: typeName = "Fragment"; break;
26 default: break;
Brian Salomon06ab3832017-12-04 16:45:30 -050027 }
28 SkDebugf("---- %s shader ----------------------------------------------------\n", typeName);
29}
30
Brian Osmanac9be9d2019-05-01 10:29:34 -040031std::unique_ptr<SkSL::Program> GrSkSLtoGLSL(const GrGLContext& context,
32 SkSL::Program::Kind programKind,
Brian Osman6c431d52019-04-15 16:31:54 -040033 const SkSL::String& sksl,
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040034 const SkSL::Program::Settings& settings,
35 SkSL::String* glsl) {
Ethan Nicholas068acd52017-05-26 14:53:23 -040036 SkSL::Compiler* compiler = context.compiler();
37 std::unique_ptr<SkSL::Program> program;
Ethan Nicholas068acd52017-05-26 14:53:23 -040038 program = compiler->convertProgram(programKind, sksl, settings);
39 if (!program || !compiler->toGLSL(*program, glsl)) {
40 SkDebugf("SKSL compilation error\n----------------------\n");
Brian Osmanac9be9d2019-05-01 10:29:34 -040041 GrShaderUtils::PrintLineByLine("SKSL:", sksl);
Ethan Nicholas068acd52017-05-26 14:53:23 -040042 SkDebugf("\nErrors:\n%s\n", compiler->errorText().c_str());
43 SkDEBUGFAIL("SKSL compilation failed!\n");
Brian Salomone334c592017-05-15 11:00:58 -040044 return nullptr;
45 }
Brian Osmanac9be9d2019-05-01 10:29:34 -040046
47 if (gPrintSKSL || gPrintGLSL) {
48 print_shader_banner(programKind);
49 if (gPrintSKSL) {
50 GrShaderUtils::PrintLineByLine("SKSL:", sksl);
51 }
52 if (gPrintGLSL) {
53 GrShaderUtils::PrintLineByLine("GLSL:", *glsl);
54 }
Brian Salomon06ab3832017-12-04 16:45:30 -050055 }
Brian Osmanac9be9d2019-05-01 10:29:34 -040056
Ethan Nicholas068acd52017-05-26 14:53:23 -040057 return program;
Brian Salomone334c592017-05-15 11:00:58 -040058}
ethannicholas5961bc92016-10-12 06:39:56 -070059
joshualitt30ba4362014-08-21 20:18:45 -070060GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
61 GrGLuint programId,
62 GrGLenum type,
Brian Osmanac9be9d2019-05-01 10:29:34 -040063 const SkSL::String& glsl,
Brian Osman8518f2e2019-05-01 14:13:41 -040064 GrGpu::Stats* stats,
65 bool assertOnFailure) {
joshualitt30ba4362014-08-21 20:18:45 -070066 const GrGLInterface* gli = glCtx.interface();
67
Brian Salomone334c592017-05-15 11:00:58 -040068 // Specify GLSL source to the driver.
robertphillips754f4e92014-09-18 13:52:08 -070069 GrGLuint shaderId;
70 GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
71 if (0 == shaderId) {
72 return 0;
73 }
Brian Osmanac9be9d2019-05-01 10:29:34 -040074 const GrGLchar* source = glsl.c_str();
75 GrGLint sourceLength = glsl.size();
76 GR_GL_CALL(gli, ShaderSource(shaderId, 1, &source, &sourceLength));
joshualitt43466a12015-02-13 17:18:27 -080077
mtkleinb9eb4ac2015-02-02 18:26:03 -080078 stats->incShaderCompilations();
robertphillips754f4e92014-09-18 13:52:08 -070079 GR_GL_CALL(gli, CompileShader(shaderId));
joshualitt30ba4362014-08-21 20:18:45 -070080
robertphillips754f4e92014-09-18 13:52:08 -070081 // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds.
cdalton1acea862015-06-02 13:05:52 -070082 bool checkCompiled = kChromium_GrGLDriver != glCtx.driver();
robertphillips754f4e92014-09-18 13:52:08 -070083#ifdef SK_DEBUG
84 checkCompiled = true;
85#endif
86 if (checkCompiled) {
87 GrGLint compiled = GR_GL_INIT_ZERO;
88 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
joshualitt30ba4362014-08-21 20:18:45 -070089
robertphillips754f4e92014-09-18 13:52:08 -070090 if (!compiled) {
Brian Salomone334c592017-05-15 11:00:58 -040091 SkDebugf("GLSL compilation error\n----------------------\n");
Brian Osmanac9be9d2019-05-01 10:29:34 -040092 GrShaderUtils::PrintLineByLine("GLSL:", glsl);
robertphillips754f4e92014-09-18 13:52:08 -070093 GrGLint infoLen = GR_GL_INIT_ZERO;
94 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
95 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
96 if (infoLen > 0) {
97 // retrieve length even though we don't need it to workaround bug in Chromium cmd
98 // buffer param validation.
99 GrGLsizei length = GR_GL_INIT_ZERO;
joshualitt43466a12015-02-13 17:18:27 -0800100 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
ethannicholas5961bc92016-10-12 06:39:56 -0700101 SkDebugf("Errors:\n%s\n", (const char*) log.get());
robertphillips754f4e92014-09-18 13:52:08 -0700102 }
Brian Salomon020dbe72018-02-22 15:03:17 -0500103 // In Chrome we may have failed due to context-loss. So we should just continue along
104 // wihthout asserting until the GrContext gets abandoned.
Brian Osman8518f2e2019-05-01 14:13:41 -0400105 if (assertOnFailure && kChromium_GrGLDriver != glCtx.driver()) {
Brian Salomon020dbe72018-02-22 15:03:17 -0500106 SkDEBUGFAIL("GLSL compilation failed!");
107 }
robertphillips754f4e92014-09-18 13:52:08 -0700108 GR_GL_CALL(gli, DeleteShader(shaderId));
109 return 0;
110 }
111 }
joshualitt30ba4362014-08-21 20:18:45 -0700112
robertphillips754f4e92014-09-18 13:52:08 -0700113 // Attach the shader, but defer deletion until after we have linked the program.
114 // This works around a bug in the Android emulator's GLES2 wrapper which
115 // will immediately delete the shader object and free its memory even though it's
116 // attached to a program, which then causes glLinkProgram to fail.
117 GR_GL_CALL(gli, AttachShader(programId, shaderId));
robertphillips754f4e92014-09-18 13:52:08 -0700118 return shaderId;
joshualitt30ba4362014-08-21 20:18:45 -0700119}
csmartdaltonb3772dc2016-07-13 08:47:54 -0700120
Brian Osmanac9be9d2019-05-01 10:29:34 -0400121void GrGLPrintShader(const GrGLContext& context, SkSL::Program::Kind programKind,
122 const SkSL::String& sksl, const SkSL::Program::Settings& settings) {
123 print_shader_banner(programKind);
124 GrShaderUtils::PrintLineByLine("SKSL:", sksl);
Brian Salomone334c592017-05-15 11:00:58 -0400125 SkSL::String glsl;
Brian Osmanac9be9d2019-05-01 10:29:34 -0400126 if (GrSkSLtoGLSL(context, programKind, sksl, settings, &glsl)) {
127 GrShaderUtils::PrintLineByLine("GLSL:", glsl);
csmartdaltonb3772dc2016-07-13 08:47:54 -0700128 }
129}