Hook up ShaderErrorHandler in the Metal backend.

Also cleans up dumping of shader code to use GrShaderUtils.

Change-Id: I4d2a13e1a54284d7da0242b74cebb3900921fc35
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/337077
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/GrShaderUtils.cpp b/src/gpu/GrShaderUtils.cpp
index 56661a8..ea77eb1 100644
--- a/src/gpu/GrShaderUtils.cpp
+++ b/src/gpu/GrShaderUtils.cpp
@@ -214,4 +214,15 @@
     return &gHandler;
 }
 
+void PrintShaderBanner(SkSL::Program::Kind programKind) {
+    const char* typeName = "Unknown";
+    switch (programKind) {
+        case SkSL::Program::kVertex_Kind:   typeName = "Vertex";   break;
+        case SkSL::Program::kGeometry_Kind: typeName = "Geometry"; break;
+        case SkSL::Program::kFragment_Kind: typeName = "Fragment"; break;
+        default: break;
+    }
+    SkDebugf("---- %s shader ----------------------------------------------------\n", typeName);
+}
+
 }  // namespace GrShaderUtils
diff --git a/src/gpu/GrShaderUtils.h b/src/gpu/GrShaderUtils.h
index b9995ce..c41906f 100644
--- a/src/gpu/GrShaderUtils.h
+++ b/src/gpu/GrShaderUtils.h
@@ -11,6 +11,7 @@
 #include "include/core/SkTypes.h"
 #include "include/gpu/GrContextOptions.h"
 #include "src/sksl/SkSLString.h"
+#include "src/sksl/ir/SkSLProgram.h"
 
 namespace GrShaderUtils {
 
@@ -28,6 +29,8 @@
 
 GrContextOptions::ShaderErrorHandler* DefaultShaderErrorHandler();
 
+void PrintShaderBanner(SkSL::Program::Kind programKind);
+
 }  // namespace GrShaderUtils
 
 #endif
diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
index c3d3406..ff59dc0 100644
--- a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
@@ -17,17 +17,6 @@
 static const bool gPrintSKSL = false;
 static const bool gPrintGLSL = false;
 
-void print_shader_banner(SkSL::Program::Kind programKind) {
-    const char* typeName = "Unknown";
-    switch (programKind) {
-        case SkSL::Program::kVertex_Kind:   typeName = "Vertex";   break;
-        case SkSL::Program::kGeometry_Kind: typeName = "Geometry"; break;
-        case SkSL::Program::kFragment_Kind: typeName = "Fragment"; break;
-        default: break;
-    }
-    SkDebugf("---- %s shader ----------------------------------------------------\n", typeName);
-}
-
 std::unique_ptr<SkSL::Program> GrSkSLtoGLSL(const GrGLContext& context,
                                             SkSL::Program::Kind programKind,
                                             const SkSL::String& sksl,
@@ -48,7 +37,7 @@
     }
 
     if (gPrintSKSL || gPrintGLSL) {
-        print_shader_banner(programKind);
+        GrShaderUtils::PrintShaderBanner(programKind);
         if (gPrintSKSL) {
             SkDebugf("SKSL:\n");
             GrShaderUtils::PrintLineByLine(GrShaderUtils::PrettyPrint(sksl));
diff --git a/src/gpu/mtl/GrMtlPipelineStateBuilder.h b/src/gpu/mtl/GrMtlPipelineStateBuilder.h
index 166d087..a3c8a3b 100644
--- a/src/gpu/mtl/GrMtlPipelineStateBuilder.h
+++ b/src/gpu/mtl/GrMtlPipelineStateBuilder.h
@@ -53,12 +53,13 @@
                                             SkSL::Program::Kind kind,
                                             const SkSL::Program::Settings& settings,
                                             SkSL::String* msl,
-                                            SkSL::Program::Inputs* inputs);
+                                            SkSL::Program::Inputs* inputs,
+                                            GrContextOptions::ShaderErrorHandler* errorHandler);
     id<MTLLibrary> compileMtlShaderLibrary(const SkSL::String& shader,
-                                           SkSL::Program::Inputs inputs);
+                                           SkSL::Program::Inputs inputs,
+                                           GrContextOptions::ShaderErrorHandler* errorHandler);
     void storeShadersInCache(const SkSL::String shaders[], const SkSL::Program::Inputs inputs[],
                              bool isSkSL);
-    bool loadShadersFromCache(SkReadBuffer* cached, __strong id<MTLLibrary> outLibraries[]);
 
     GrGLSLUniformHandler* uniformHandler() override { return &fUniformHandler; }
     const GrGLSLUniformHandler* uniformHandler() const override { return &fUniformHandler; }
diff --git a/src/gpu/mtl/GrMtlPipelineStateBuilder.mm b/src/gpu/mtl/GrMtlPipelineStateBuilder.mm
index fb61346..140b1a2 100644
--- a/src/gpu/mtl/GrMtlPipelineStateBuilder.mm
+++ b/src/gpu/mtl/GrMtlPipelineStateBuilder.mm
@@ -66,27 +66,6 @@
 static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
 
 
-bool GrMtlPipelineStateBuilder::loadShadersFromCache(SkReadBuffer* cached,
-                                                     __strong id<MTLLibrary> outLibraries[]) {
-    SkSL::String shaders[kGrShaderTypeCount];
-    SkSL::Program::Inputs inputs[kGrShaderTypeCount];
-
-    if (!GrPersistentCacheUtils::UnpackCachedShaders(cached, shaders, inputs, kGrShaderTypeCount)) {
-        return false;
-    }
-
-    outLibraries[kVertex_GrShaderType] = this->compileMtlShaderLibrary(
-                                              shaders[kVertex_GrShaderType],
-                                              inputs[kVertex_GrShaderType]);
-    outLibraries[kFragment_GrShaderType] = this->compileMtlShaderLibrary(
-                                                shaders[kFragment_GrShaderType],
-                                                inputs[kFragment_GrShaderType]);
-
-    return outLibraries[kVertex_GrShaderType] &&
-           outLibraries[kFragment_GrShaderType] &&
-           shaders[kGeometry_GrShaderType].empty();  // Geometry shaders are not supported
-}
-
 void GrMtlPipelineStateBuilder::storeShadersInCache(const SkSL::String shaders[],
                                                     const SkSL::Program::Inputs inputs[],
                                                     bool isSkSL) {
@@ -106,18 +85,21 @@
         SkSL::Program::Kind kind,
         const SkSL::Program::Settings& settings,
         SkSL::String* msl,
-        SkSL::Program::Inputs* inputs) {
+        SkSL::Program::Inputs* inputs,
+        GrContextOptions::ShaderErrorHandler* errorHandler) {
     id<MTLLibrary> shaderLibrary = GrGenerateMtlShaderLibrary(fGpu, shader,
-                                                              kind, settings, msl, inputs);
+                                                              kind, settings, msl, inputs,
+                                                              errorHandler);
     if (shaderLibrary != nil && inputs->fRTHeight) {
         this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
     }
     return shaderLibrary;
 }
 
-id<MTLLibrary> GrMtlPipelineStateBuilder::compileMtlShaderLibrary(const SkSL::String& shader,
-                                                                  SkSL::Program::Inputs inputs) {
-    id<MTLLibrary> shaderLibrary = GrCompileMtlShaderLibrary(fGpu, shader);
+id<MTLLibrary> GrMtlPipelineStateBuilder::compileMtlShaderLibrary(
+        const SkSL::String& shader, SkSL::Program::Inputs inputs,
+        GrContextOptions::ShaderErrorHandler* errorHandler) {
+    id<MTLLibrary> shaderLibrary = GrCompileMtlShaderLibrary(fGpu, shader, errorHandler);
     if (shaderLibrary != nil && inputs.fRTHeight) {
         this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
     }
@@ -413,12 +395,23 @@
         }
     }
 
-    if (kMSL_Tag == shaderType && this->loadShadersFromCache(&reader, shaderLibraries)) {
-        // We successfully loaded and compiled MSL
+    auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler();
+    SkSL::String shaders[kGrShaderTypeCount];
+    SkSL::Program::Inputs inputs[kGrShaderTypeCount];
+    if (kMSL_Tag == shaderType &&
+        GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, inputs, kGrShaderTypeCount)) {
+        shaderLibraries[kVertex_GrShaderType] = this->compileMtlShaderLibrary(
+                                                        shaders[kVertex_GrShaderType],
+                                                        inputs[kVertex_GrShaderType],
+                                                        errorHandler);
+        shaderLibraries[kFragment_GrShaderType] = this->compileMtlShaderLibrary(
+                                                        shaders[kFragment_GrShaderType],
+                                                        inputs[kFragment_GrShaderType],
+                                                        errorHandler);
+        if (!shaderLibraries[kVertex_GrShaderType] || !shaderLibraries[kFragment_GrShaderType]) {
+            return nullptr;
+        }
     } else {
-        SkSL::String shaders[kGrShaderTypeCount];
-        SkSL::Program::Inputs inputs[kGrShaderTypeCount];
-
         SkSL::String* sksl[kGrShaderTypeCount] = {
             &fVS.fCompilerString,
             nullptr,              // geometry shaders not supported
@@ -439,17 +432,15 @@
                                                      SkSL::Program::kVertex_Kind,
                                                      settings,
                                                      &shaders[kVertex_GrShaderType],
-                                                     &inputs[kVertex_GrShaderType]);
+                                                     &inputs[kVertex_GrShaderType],
+                                                     errorHandler);
         shaderLibraries[kFragment_GrShaderType] = this->generateMtlShaderLibrary(
                                                        *sksl[kFragment_GrShaderType],
                                                        SkSL::Program::kFragment_Kind,
                                                        settings,
                                                        &shaders[kFragment_GrShaderType],
-                                                       &inputs[kFragment_GrShaderType]);
-
-        // Geometry shaders are not supported
-        SkASSERT(!this->primitiveProcessor().willUseGeoShader());
-
+                                                       &inputs[kFragment_GrShaderType],
+                                                       errorHandler);
         if (!shaderLibraries[kVertex_GrShaderType] || !shaderLibraries[kFragment_GrShaderType]) {
             return nullptr;
         }
@@ -469,6 +460,9 @@
         }
     }
 
+    // Geometry shaders are not supported
+    SkASSERT(!this->primitiveProcessor().willUseGeoShader());
+
     id<MTLFunction> vertexFunction =
             [shaderLibraries[kVertex_GrShaderType] newFunctionWithName: @"vertexMain"];
     id<MTLFunction> fragmentFunction =
diff --git a/src/gpu/mtl/GrMtlUtil.h b/src/gpu/mtl/GrMtlUtil.h
index cb11f52..97f3580 100644
--- a/src/gpu/mtl/GrMtlUtil.h
+++ b/src/gpu/mtl/GrMtlUtil.h
@@ -69,17 +69,19 @@
  * Returns a compiled MTLLibrary created from MSL code generated by SkSLC
  */
 id<MTLLibrary> GrGenerateMtlShaderLibrary(const GrMtlGpu* gpu,
-                                          const SkSL::String& shaderString,
+                                          const SkSL::String& sksl,
                                           SkSL::Program::Kind kind,
                                           const SkSL::Program::Settings& settings,
-                                          SkSL::String* mslShader,
-                                          SkSL::Program::Inputs* outInputs);
+                                          SkSL::String* msl,
+                                          SkSL::Program::Inputs* outInputs,
+                                          GrContextOptions::ShaderErrorHandler* errorHandler);
 
 /**
 * Returns a compiled MTLLibrary created from MSL code
 */
 id<MTLLibrary> GrCompileMtlShaderLibrary(const GrMtlGpu* gpu,
-                                         const SkSL::String& shaderString);
+                                         const SkSL::String& msl,
+                                         GrContextOptions::ShaderErrorHandler* errorHandler);
 
 /**
  * Replacement for newLibraryWithSource:options:error that has a timeout.
diff --git a/src/gpu/mtl/GrMtlUtil.mm b/src/gpu/mtl/GrMtlUtil.mm
index c24cc2c..ac74882 100644
--- a/src/gpu/mtl/GrMtlUtil.mm
+++ b/src/gpu/mtl/GrMtlUtil.mm
@@ -10,6 +10,7 @@
 #include "include/gpu/GrBackendSurface.h"
 #include "include/private/GrTypesPriv.h"
 #include "include/private/SkMutex.h"
+#include "src/gpu/GrShaderUtils.h"
 #include "src/gpu/GrSurface.h"
 #include "src/gpu/mtl/GrMtlGpu.h"
 #include "src/gpu/mtl/GrMtlRenderTarget.h"
@@ -22,8 +23,6 @@
 #error This file must be compiled with Arc. Use -fobjc-arc flag
 #endif
 
-#define PRINT_MSL 0 // print out the MSL code generated
-
 NSError* GrCreateMtlError(NSString* description, GrMtlErrorCode errorCode) {
     NSDictionary* userInfo = [NSDictionary dictionaryWithObject:description
                                                          forKey:NSLocalizedDescriptionKey];
@@ -48,55 +47,55 @@
     return texDesc;
 }
 
-#if PRINT_MSL
-void print_msl(const char* source) {
-    SkTArray<SkString> lines;
-    SkStrSplit(source, "\n", kStrict_SkStrSplitMode, &lines);
-    for (int i = 0; i < lines.count(); i++) {
-        SkString& line = lines[i];
-        line.prependf("%4i\t", i + 1);
-        SkDebugf("%s\n", line.c_str());
-    }
-}
-#endif
+// Print the source code for all shaders generated.
+static const bool gPrintSKSL = false;
+static const bool gPrintMSL = false;
 
 id<MTLLibrary> GrGenerateMtlShaderLibrary(const GrMtlGpu* gpu,
-                                          const SkSL::String& shaderString,
-                                          SkSL::Program::Kind kind,
+                                          const SkSL::String& sksl,
+                                          SkSL::Program::Kind programKind,
                                           const SkSL::Program::Settings& settings,
-                                          SkSL::String* mslShader,
-                                          SkSL::Program::Inputs* outInputs) {
+                                          SkSL::String* msl,
+                                          SkSL::Program::Inputs* outInputs,
+                                          GrContextOptions::ShaderErrorHandler* errorHandler) {
+#ifdef SK_DEBUG
+    SkSL::String src = GrShaderUtils::PrettyPrint(sksl);
+#else
+    const SkSL::String& src = sksl;
+#endif
+    SkSL::Compiler* compiler = gpu->shaderCompiler();
     std::unique_ptr<SkSL::Program> program =
-            gpu->shaderCompiler()->convertProgram(kind,
-                                                  shaderString,
+            gpu->shaderCompiler()->convertProgram(programKind,
+                                                  src,
                                                   settings);
-
-    if (!program) {
-        SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str());
-        SkASSERT(false);
+    if (!program || !compiler->toMetal(*program, msl)) {
+        errorHandler->compileError(src.c_str(), compiler->errorText().c_str());
         return nil;
     }
 
+    if (gPrintSKSL || gPrintMSL) {
+        GrShaderUtils::PrintShaderBanner(programKind);
+        if (gPrintSKSL) {
+            SkDebugf("SKSL:\n");
+            GrShaderUtils::PrintLineByLine(GrShaderUtils::PrettyPrint(sksl));
+        }
+        if (gPrintMSL) {
+            SkDebugf("MSL:\n");
+            GrShaderUtils::PrintLineByLine(GrShaderUtils::PrettyPrint(*msl));
+        }
+    }
+
     *outInputs = program->fInputs;
-    if (!gpu->shaderCompiler()->toMetal(*program, mslShader)) {
-        SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str());
-        SkASSERT(false);
-        return nil;
-    }
-
-    return GrCompileMtlShaderLibrary(gpu, *mslShader);
+    return GrCompileMtlShaderLibrary(gpu, *msl, errorHandler);
 }
 
 id<MTLLibrary> GrCompileMtlShaderLibrary(const GrMtlGpu* gpu,
-                                         const SkSL::String& shaderString) {
-    auto nsSource = [[NSString alloc] initWithBytesNoCopy:const_cast<char*>(shaderString.c_str())
-                                                   length:shaderString.size()
+                                         const SkSL::String& msl,
+                                         GrContextOptions::ShaderErrorHandler* errorHandler) {
+    auto nsSource = [[NSString alloc] initWithBytesNoCopy:const_cast<char*>(msl.c_str())
+                                                   length:msl.size()
                                                  encoding:NSUTF8StringEncoding
                                              freeWhenDone:NO];
-#if PRINT_MSL
-    print_msl(nsSource.UTF8String);
-#endif
-
     NSError* error = nil;
 #if defined(SK_BUILD_FOR_MAC)
     id<MTLLibrary> compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), nsSource,
@@ -107,9 +106,7 @@
                                                                    error:&error];
 #endif
     if (!compiledLibrary) {
-        SkDebugf("Error compiling MSL shader: %s\n%s\n",
-                 shaderString.c_str(),
-                 error.debugDescription.UTF8String);
+        errorHandler->compileError(msl.c_str(), error.debugDescription.UTF8String);
         return nil;
     }