Home | History | Annotate | Download | only in builders
      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 "GrSKSLPrettyPrint.h"
     10 #include "SkAutoMalloc.h"
     11 #include "SkSLCompiler.h"
     12 #include "SkSLGLSLCodeGenerator.h"
     13 #include "SkTraceEvent.h"
     14 #include "gl/GrGLGpu.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_lines_with_numbers(const char* source,
     24                                             std::function<void(const char*)> println) {
     25     SkTArray<SkString> lines;
     26     SkStrSplit(source, "\n", kStrict_SkStrSplitMode, &lines);
     27     for (int i = 0; i < lines.count(); ++i) {
     28         SkString& line = lines[i];
     29         line.prependf("%4i\t", i + 1);
     30         println(line.c_str());
     31     }
     32 }
     33 
     34 // Prints shaders one line at the time. This ensures they don't get truncated by the adb log.
     35 static void print_shaders_line_by_line(const char** skslStrings, int* lengths,
     36                                      int count, const SkSL::String& glsl,
     37                                      std::function<void(const char*)> println = [](const char* ln) {
     38                                          SkDebugf("%s\n", ln);
     39                                      }) {
     40     SkString sksl = GrSKSLPrettyPrint::PrettyPrint(skslStrings, lengths, count, false);
     41     println("SKSL:");
     42     print_source_lines_with_numbers(sksl.c_str(), println);
     43     if (!glsl.isEmpty()) {
     44         println("GLSL:");
     45         print_source_lines_with_numbers(glsl.c_str(), println);
     46     }
     47 }
     48 
     49 std::unique_ptr<SkSL::Program> translate_to_glsl(const GrGLContext& context, GrGLenum type,
     50                                                  const char** skslStrings, int* lengths, int count,
     51                                                  const SkSL::Program::Settings& settings,
     52                                                  SkSL::String* glsl) {
     53     SkString sksl;
     54 #ifdef SK_DEBUG
     55     sksl = GrSKSLPrettyPrint::PrettyPrint(skslStrings, lengths, count, false);
     56 #else
     57     for (int i = 0; i < count; i++) {
     58         sksl.append(skslStrings[i], lengths[i]);
     59     }
     60 #endif
     61     SkSL::Compiler* compiler = context.compiler();
     62     std::unique_ptr<SkSL::Program> program;
     63     SkSL::Program::Kind programKind;
     64     switch (type) {
     65         case GR_GL_VERTEX_SHADER:   programKind = SkSL::Program::kVertex_Kind;   break;
     66         case GR_GL_FRAGMENT_SHADER: programKind = SkSL::Program::kFragment_Kind; break;
     67         case GR_GL_GEOMETRY_SHADER: programKind = SkSL::Program::kGeometry_Kind; break;
     68     }
     69     program = compiler->convertProgram(programKind, sksl, settings);
     70     if (!program || !compiler->toGLSL(*program, glsl)) {
     71         SkDebugf("SKSL compilation error\n----------------------\n");
     72         print_shaders_line_by_line(skslStrings, lengths, count, *glsl);
     73         SkDebugf("\nErrors:\n%s\n", compiler->errorText().c_str());
     74         SkDEBUGFAIL("SKSL compilation failed!\n");
     75         return nullptr;
     76     }
     77     return program;
     78 }
     79 
     80 GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
     81                                     GrGLuint programId,
     82                                     GrGLenum type,
     83                                     const char** skslStrings,
     84                                     int* lengths,
     85                                     int count,
     86                                     GrGpu::Stats* stats,
     87                                     const SkSL::Program::Settings& settings,
     88                                     SkSL::Program::Inputs* outInputs) {
     89     const GrGLInterface* gli = glCtx.interface();
     90 
     91     SkSL::String glsl;
     92     auto program = translate_to_glsl(glCtx, type, skslStrings, lengths, count, settings, &glsl);
     93     if (!program) {
     94         return 0;
     95     }
     96 
     97     // Specify GLSL source to the driver.
     98     GrGLuint shaderId;
     99     GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
    100     if (0 == shaderId) {
    101         return 0;
    102     }
    103     const char* glslChars = glsl.c_str();
    104     GrGLint glslLength = (GrGLint) glsl.size();
    105     GR_GL_CALL(gli, ShaderSource(shaderId, 1, &glslChars, &glslLength));
    106 
    107     // Trace event for shader preceding driver compilation
    108     bool traceShader;
    109     TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), &traceShader);
    110     if (traceShader) {
    111         SkString shaderDebugString;
    112         print_shaders_line_by_line(skslStrings, lengths, count, glsl, [&](const char* ln) {
    113             shaderDebugString.append(ln);
    114             shaderDebugString.append("\n");
    115         });
    116         TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLShader",
    117                              TRACE_EVENT_SCOPE_THREAD, "shader",
    118                              TRACE_STR_COPY(shaderDebugString.c_str()));
    119     }
    120 
    121     stats->incShaderCompilations();
    122     GR_GL_CALL(gli, CompileShader(shaderId));
    123 
    124     // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds.
    125     bool checkCompiled = kChromium_GrGLDriver != glCtx.driver();
    126 #ifdef SK_DEBUG
    127     checkCompiled = true;
    128 #endif
    129     if (checkCompiled) {
    130         GrGLint compiled = GR_GL_INIT_ZERO;
    131         GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
    132 
    133         if (!compiled) {
    134             SkDebugf("GLSL compilation error\n----------------------\n");
    135             print_shaders_line_by_line(skslStrings, lengths, count, glsl);
    136             GrGLint infoLen = GR_GL_INIT_ZERO;
    137             GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
    138             SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
    139             if (infoLen > 0) {
    140                 // retrieve length even though we don't need it to workaround bug in Chromium cmd
    141                 // buffer param validation.
    142                 GrGLsizei length = GR_GL_INIT_ZERO;
    143                 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
    144                 SkDebugf("Errors:\n%s\n", (const char*) log.get());
    145             }
    146             SkDEBUGFAIL("GLSL compilation failed!");
    147             GR_GL_CALL(gli, DeleteShader(shaderId));
    148             return 0;
    149         }
    150     }
    151 
    152     if (c_PrintShaders) {
    153         const char* typeName = "Unknown";
    154         switch (type) {
    155             case GR_GL_VERTEX_SHADER: typeName = "Vertex"; break;
    156             case GR_GL_GEOMETRY_SHADER: typeName = "Geometry"; break;
    157             case GR_GL_FRAGMENT_SHADER: typeName = "Fragment"; break;
    158         }
    159         SkDebugf("---- %s shader ----------------------------------------------------\n", typeName);
    160         print_shaders_line_by_line(skslStrings, lengths, count, glsl);
    161     }
    162 
    163     // Attach the shader, but defer deletion until after we have linked the program.
    164     // This works around a bug in the Android emulator's GLES2 wrapper which
    165     // will immediately delete the shader object and free its memory even though it's
    166     // attached to a program, which then causes glLinkProgram to fail.
    167     GR_GL_CALL(gli, AttachShader(programId, shaderId));
    168     *outInputs = program->fInputs;
    169     return shaderId;
    170 }
    171 
    172 void GrGLPrintShader(const GrGLContext& context, GrGLenum type, const char** skslStrings,
    173                      int* lengths, int count, const SkSL::Program::Settings& settings) {
    174     SkSL::String glsl;
    175     if (translate_to_glsl(context, type, skslStrings, lengths, count, settings, &glsl)) {
    176         print_shaders_line_by_line(skslStrings, lengths, count, glsl);
    177     }
    178 }
    179