130ba436f04e61d4505fb854d5fc56079636e0788joshualitt/* 230ba436f04e61d4505fb854d5fc56079636e0788joshualitt * Copyright 2014 Google Inc. 330ba436f04e61d4505fb854d5fc56079636e0788joshualitt * 430ba436f04e61d4505fb854d5fc56079636e0788joshualitt * Use of this source code is governed by a BSD-style license that can be 530ba436f04e61d4505fb854d5fc56079636e0788joshualitt * found in the LICENSE file. 630ba436f04e61d4505fb854d5fc56079636e0788joshualitt */ 730ba436f04e61d4505fb854d5fc56079636e0788joshualitt 830ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "GrGLShaderStringBuilder.h" 9e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon#include "GrSKSLPrettyPrint.h" 1095e3c058ef633782f7549e9e1c2727d60dbc8ee5Hal Canary#include "SkAutoMalloc.h" 11c456b73fef9589bbdc5eb83eaa83e53c357bb3daKevin Lubick#include "SkSLCompiler.h" 12c456b73fef9589bbdc5eb83eaa83e53c357bb3daKevin Lubick#include "SkSLGLSLCodeGenerator.h" 1395e3c058ef633782f7549e9e1c2727d60dbc8ee5Hal Canary#include "SkTraceEvent.h" 1495e3c058ef633782f7549e9e1c2727d60dbc8ee5Hal Canary#include "gl/GrGLGpu.h" 155961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas#include "ir/SkSLProgram.h" 1630ba436f04e61d4505fb854d5fc56079636e0788joshualitt 1730ba436f04e61d4505fb854d5fc56079636e0788joshualitt#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) 1830ba436f04e61d4505fb854d5fc56079636e0788joshualitt#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X) 1930ba436f04e61d4505fb854d5fc56079636e0788joshualitt 204e44efe50474d4eebcb30b762e784b3ef2126750halcanary// Print the source code for all shaders generated. 2106ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomonstatic const bool gPrintSKSL = false; 2206ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomonstatic const bool gPrintGLSL = false; 2330ba436f04e61d4505fb854d5fc56079636e0788joshualitt 247bd55c2149cf70a2bf17743ecdfe74332daa276cChris Daltonstatic void print_source_lines_with_numbers(const char* source, 257bd55c2149cf70a2bf17743ecdfe74332daa276cChris Dalton std::function<void(const char*)> println) { 26e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon SkTArray<SkString> lines; 27e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon SkStrSplit(source, "\n", kStrict_SkStrSplitMode, &lines); 287bd55c2149cf70a2bf17743ecdfe74332daa276cChris Dalton for (int i = 0; i < lines.count(); ++i) { 297bd55c2149cf70a2bf17743ecdfe74332daa276cChris Dalton SkString& line = lines[i]; 307bd55c2149cf70a2bf17743ecdfe74332daa276cChris Dalton line.prependf("%4i\t", i + 1); 317bd55c2149cf70a2bf17743ecdfe74332daa276cChris Dalton println(line.c_str()); 32e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon } 33e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon} 3430ba436f04e61d4505fb854d5fc56079636e0788joshualitt 357bd55c2149cf70a2bf17743ecdfe74332daa276cChris Dalton// Prints shaders one line at the time. This ensures they don't get truncated by the adb log. 36d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholasstatic void print_sksl_line_by_line(const char** skslStrings, int* lengths, int count, 37d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas std::function<void(const char*)> println = [](const char* ln) { 38d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas SkDebugf("%s\n", ln); 39d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas }) { 4093ba0a4fc85f04bc1be9429983df1e57473b49a7Brian Osman SkSL::String sksl = GrSKSLPrettyPrint::PrettyPrint(skslStrings, lengths, count, false); 417bd55c2149cf70a2bf17743ecdfe74332daa276cChris Dalton println("SKSL:"); 427bd55c2149cf70a2bf17743ecdfe74332daa276cChris Dalton print_source_lines_with_numbers(sksl.c_str(), println); 43e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon} 4430ba436f04e61d4505fb854d5fc56079636e0788joshualitt 45d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholasstatic void print_glsl_line_by_line(const SkSL::String& glsl, 46d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas std::function<void(const char*)> println = [](const char* ln) { 47d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas SkDebugf("%s\n", ln); 48d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas }) { 49d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas println("GLSL:"); 50d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas print_source_lines_with_numbers(glsl.c_str(), println); 51d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas} 52d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas 5306ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomonvoid print_shader_banner(GrGLenum type) { 5406ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon const char* typeName = "Unknown"; 5506ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon switch (type) { 5606ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon case GR_GL_VERTEX_SHADER: typeName = "Vertex"; break; 5706ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon case GR_GL_GEOMETRY_SHADER: typeName = "Geometry"; break; 5806ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon case GR_GL_FRAGMENT_SHADER: typeName = "Fragment"; break; 5906ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon } 6006ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon SkDebugf("---- %s shader ----------------------------------------------------\n", typeName); 6106ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon} 6206ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon 63d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholasstd::unique_ptr<SkSL::Program> GrSkSLtoGLSL(const GrGLContext& context, GrGLenum type, 64d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas const char** skslStrings, int* lengths, int count, 65d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas const SkSL::Program::Settings& settings, 66d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas SkSL::String* glsl) { 67d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas // Trace event for shader preceding driver compilation 68d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas bool traceShader; 69d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas TRACE_EVENT_CATEGORY_GROUP_ENABLED("skia.gpu", &traceShader); 70d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas if (traceShader) { 71d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas SkString shaderDebugString; 72d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas print_sksl_line_by_line(skslStrings, lengths, count, [&](const char* ln) { 73d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas shaderDebugString.append(ln); 74d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas shaderDebugString.append("\n"); 75d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas }); 76d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas TRACE_EVENT_INSTANT1("skia.gpu", "skia_gpu::GLShader", 77d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas TRACE_EVENT_SCOPE_THREAD, "shader", 78d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas TRACE_STR_COPY(shaderDebugString.c_str())); 79d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas } 80d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas 8193ba0a4fc85f04bc1be9429983df1e57473b49a7Brian Osman SkSL::String sksl; 82754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips#ifdef SK_DEBUG 83e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon sksl = GrSKSLPrettyPrint::PrettyPrint(skslStrings, lengths, count, false); 84754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips#else 855961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas for (int i = 0; i < count; i++) { 86e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon sksl.append(skslStrings[i], lengths[i]); 875961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 88754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips#endif 89068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas SkSL::Compiler* compiler = context.compiler(); 90068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas std::unique_ptr<SkSL::Program> program; 91068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas SkSL::Program::Kind programKind; 92068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas switch (type) { 93068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas case GR_GL_VERTEX_SHADER: programKind = SkSL::Program::kVertex_Kind; break; 94068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas case GR_GL_FRAGMENT_SHADER: programKind = SkSL::Program::kFragment_Kind; break; 95068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas case GR_GL_GEOMETRY_SHADER: programKind = SkSL::Program::kGeometry_Kind; break; 96898d5b20348784fdf65f0decf96fc5d40d99bd95Ethan Nicholas default: SK_ABORT("unsupported shader kind"); 97068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas } 98068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas program = compiler->convertProgram(programKind, sksl, settings); 99068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas if (!program || !compiler->toGLSL(*program, glsl)) { 100068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas SkDebugf("SKSL compilation error\n----------------------\n"); 101d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas print_sksl_line_by_line(skslStrings, lengths, count); 102068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas SkDebugf("\nErrors:\n%s\n", compiler->errorText().c_str()); 103068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas SkDEBUGFAIL("SKSL compilation failed!\n"); 104e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon return nullptr; 105276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton } 10606ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon if (gPrintSKSL) { 10706ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon print_shader_banner(type); 10806ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon print_sksl_line_by_line(skslStrings, lengths, count); 10906ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon } 110068acd5cf930212510c69f7909c8b999be7965e2Ethan Nicholas return program; 111e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon} 1125961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas 113e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian SalomonGrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, 114e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon GrGLuint programId, 115e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon GrGLenum type, 116d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas const char* glsl, 117d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas int glslLength, 118e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon GrGpu::Stats* stats, 119d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas const SkSL::Program::Settings& settings) { 120e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon const GrGLInterface* gli = glCtx.interface(); 121e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon 122e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon // Specify GLSL source to the driver. 123e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon GrGLuint shaderId; 124e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); 125e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon if (0 == shaderId) { 126e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon return 0; 127e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon } 128d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas GR_GL_CALL(gli, ShaderSource(shaderId, 1, &glsl, &glslLength)); 12943466a1ade066f96823dbc7963767da3973afd91joshualitt 130b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein stats->incShaderCompilations(); 131754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips GR_GL_CALL(gli, CompileShader(shaderId)); 13230ba436f04e61d4505fb854d5fc56079636e0788joshualitt 133754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. 1341acea86914797bc33856ff62b5cdfbe82c58dd67cdalton bool checkCompiled = kChromium_GrGLDriver != glCtx.driver(); 135754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips#ifdef SK_DEBUG 136754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips checkCompiled = true; 137754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips#endif 138754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips if (checkCompiled) { 139754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips GrGLint compiled = GR_GL_INIT_ZERO; 140754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); 14130ba436f04e61d4505fb854d5fc56079636e0788joshualitt 142754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips if (!compiled) { 143e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon SkDebugf("GLSL compilation error\n----------------------\n"); 144d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas print_glsl_line_by_line(glsl); 145754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips GrGLint infoLen = GR_GL_INIT_ZERO; 146754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); 147754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 148754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips if (infoLen > 0) { 149754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips // retrieve length even though we don't need it to workaround bug in Chromium cmd 150754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips // buffer param validation. 151754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips GrGLsizei length = GR_GL_INIT_ZERO; 15243466a1ade066f96823dbc7963767da3973afd91joshualitt GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get())); 1535961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas SkDebugf("Errors:\n%s\n", (const char*) log.get()); 154754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips } 155020dbe7917f7616bfbdff9128124e0c09d3f0f2dBrian Salomon // In Chrome we may have failed due to context-loss. So we should just continue along 156020dbe7917f7616bfbdff9128124e0c09d3f0f2dBrian Salomon // wihthout asserting until the GrContext gets abandoned. 157020dbe7917f7616bfbdff9128124e0c09d3f0f2dBrian Salomon if (kChromium_GrGLDriver != glCtx.driver()) { 158020dbe7917f7616bfbdff9128124e0c09d3f0f2dBrian Salomon SkDEBUGFAIL("GLSL compilation failed!"); 159020dbe7917f7616bfbdff9128124e0c09d3f0f2dBrian Salomon } 160754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips GR_GL_CALL(gli, DeleteShader(shaderId)); 161754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips return 0; 162754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips } 163754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips } 16430ba436f04e61d4505fb854d5fc56079636e0788joshualitt 16506ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon if (gPrintGLSL) { 16606ab3836f779dbcbcd067a9261300616ff7cc594Brian Salomon print_shader_banner(type); 167d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas print_glsl_line_by_line(glsl); 168754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips } 16930ba436f04e61d4505fb854d5fc56079636e0788joshualitt 170754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips // Attach the shader, but defer deletion until after we have linked the program. 171754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips // This works around a bug in the Android emulator's GLES2 wrapper which 172754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips // will immediately delete the shader object and free its memory even though it's 173754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips // attached to a program, which then causes glLinkProgram to fail. 174754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips GR_GL_CALL(gli, AttachShader(programId, shaderId)); 175754f4e98d94d7c9ed76cd128cf983f9323a1885brobertphillips return shaderId; 17630ba436f04e61d4505fb854d5fc56079636e0788joshualitt} 177b3772dcb306241f53fe10ba62117ed67f89f24b2csmartdalton 178e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomonvoid GrGLPrintShader(const GrGLContext& context, GrGLenum type, const char** skslStrings, 179e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon int* lengths, int count, const SkSL::Program::Settings& settings) { 180d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas print_sksl_line_by_line(skslStrings, lengths, count); 181e334c596546c7ec79f2b0e55b3a1c2839a94f352Brian Salomon SkSL::String glsl; 182d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas if (GrSkSLtoGLSL(context, type, skslStrings, lengths, count, settings, &glsl)) { 183d1b2eec0d0f95977b52669025cb25038618c0335Ethan Nicholas print_glsl_line_by_line(glsl); 184b3772dcb306241f53fe10ba62117ed67f89f24b2csmartdalton } 185b3772dcb306241f53fe10ba62117ed67f89f24b2csmartdalton} 186