Add ShaderErrorHandler to GrContextOptions
Allows clients to customize behavior when shaders fail to compile.
Added nicer shader error handling to viewer.
Change-Id: If82b48e40d64fd786f37e88c564fd623b53c7f9d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/211361
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index ca9e679..98d6f21 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -21,6 +21,7 @@
#include "src/gpu/GrResourceCache.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrSemaphore.h"
+#include "src/gpu/GrShaderUtils.h"
#include "src/gpu/GrSoftwarePathRenderer.h"
#include "src/gpu/GrTracing.h"
#include "src/gpu/SkGr.h"
@@ -92,6 +93,10 @@
}
fPersistentCache = this->options().fPersistentCache;
+ fShaderErrorHandler = this->options().fShaderErrorHandler;
+ if (!fShaderErrorHandler) {
+ fShaderErrorHandler = GrShaderUtils::DefaultShaderErrorHandler();
+ }
return true;
}
diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h
index 97c76e4..ebf3f6a 100644
--- a/src/gpu/GrContextPriv.h
+++ b/src/gpu/GrContextPriv.h
@@ -253,6 +253,9 @@
void copyOpListsFromDDL(const SkDeferredDisplayList*, GrRenderTargetProxy* newDest);
GrContextOptions::PersistentCache* getPersistentCache() { return fContext->fPersistentCache; }
+ GrContextOptions::ShaderErrorHandler* getShaderErrorHandler() const {
+ return fContext->fShaderErrorHandler;
+ }
#ifdef SK_ENABLE_DUMP_GPU
/** Returns a string with detailed information about the context & GPU, in JSON format. */
diff --git a/src/gpu/GrShaderUtils.cpp b/src/gpu/GrShaderUtils.cpp
index 5367202..d0fe2d7 100644
--- a/src/gpu/GrShaderUtils.cpp
+++ b/src/gpu/GrShaderUtils.cpp
@@ -6,6 +6,7 @@
*/
#include "include/core/SkString.h"
+#include "include/gpu/GrContextOptions.h"
#include "src/gpu/GrShaderUtils.h"
#include "src/sksl/SkSLString.h"
@@ -190,8 +191,10 @@
// Prints shaders one line at the time. This ensures they don't get truncated by the adb log.
void PrintLineByLine(const char* header, const SkSL::String& text) {
+ if (header) {
+ SkDebugf("%s\n", header);
+ }
SkSL::String pretty = PrettyPrint(text);
- SkDebugf("%s\n", header);
SkTArray<SkString> lines;
SkStrSplit(pretty.c_str(), "\n", kStrict_SkStrSplitMode, &lines);
for (int i = 0; i < lines.count(); ++i) {
@@ -199,4 +202,20 @@
}
}
+GrContextOptions::ShaderErrorHandler* DefaultShaderErrorHandler() {
+ class GrDefaultShaderErrorHandler : public GrContextOptions::ShaderErrorHandler {
+ public:
+ void compileError(const char* shader, const char* errors) override {
+ SkDebugf("Shader compilation error\n"
+ "------------------------\n");
+ PrintLineByLine(nullptr, shader);
+ SkDebugf("Errors:\n%s\n", errors);
+ SkDEBUGFAIL("Shader compilation failed!");
+ }
+ };
+
+ static GrDefaultShaderErrorHandler gHandler;
+ return &gHandler;
+}
+
} // namespace
diff --git a/src/gpu/GrShaderUtils.h b/src/gpu/GrShaderUtils.h
index 731d546..c30120d 100644
--- a/src/gpu/GrShaderUtils.h
+++ b/src/gpu/GrShaderUtils.h
@@ -9,12 +9,14 @@
#define GrShaderUtils_DEFINED
#include "include/core/SkTypes.h"
+#include "include/gpu/GrContextOptions.h"
#include "src/sksl/SkSLString.h"
namespace GrShaderUtils {
SkSL::String PrettyPrint(const SkSL::String& string);
void PrintLineByLine(const char* header, const SkSL::String& text);
+GrContextOptions::ShaderErrorHandler* DefaultShaderErrorHandler();
}
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 5efd09e..0a044b6 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3440,24 +3440,23 @@
"}"
);
+ auto errorHandler = this->getContext()->priv().getShaderErrorHandler();
SkSL::String sksl(vshaderTxt.c_str(), vshaderTxt.size());
SkSL::Program::Settings settings;
settings.fCaps = shaderCaps;
SkSL::String glsl;
- bool assertOnCompileFailure =
- this->getContext()->priv().options().fAssertOnShaderCompileFailure;
std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(*fGLContext, SkSL::Program::kVertex_Kind,
- sksl, settings, &glsl);
+ sksl, settings, &glsl, errorHandler);
GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
- GR_GL_VERTEX_SHADER, glsl, &fStats,
- assertOnCompileFailure);
+ GR_GL_VERTEX_SHADER, glsl, &fStats, errorHandler);
SkASSERT(program->fInputs.isEmpty());
sksl.assign(fshaderTxt.c_str(), fshaderTxt.size());
- program = GrSkSLtoGLSL(*fGLContext, SkSL::Program::kFragment_Kind, sksl, settings, &glsl);
+ program = GrSkSLtoGLSL(*fGLContext, SkSL::Program::kFragment_Kind, sksl, settings, &glsl,
+ errorHandler);
GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
GR_GL_FRAGMENT_SHADER, glsl, &fStats,
- assertOnCompileFailure);
+ errorHandler);
SkASSERT(program->fInputs.isEmpty());
GL_CALL(LinkProgram(fCopyPrograms[progIdx].fProgram));
@@ -3596,24 +3595,23 @@
fshaderTxt.append("}");
+ auto errorHandler = this->getContext()->priv().getShaderErrorHandler();
SkSL::String sksl(vshaderTxt.c_str(), vshaderTxt.size());
SkSL::Program::Settings settings;
settings.fCaps = shaderCaps;
SkSL::String glsl;
- bool assertOnCompileFailure =
- this->getContext()->priv().options().fAssertOnShaderCompileFailure;
std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(*fGLContext, SkSL::Program::kVertex_Kind,
- sksl, settings, &glsl);
+ sksl, settings, &glsl, errorHandler);
GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram,
- GR_GL_VERTEX_SHADER, glsl, &fStats,
- assertOnCompileFailure);
+ GR_GL_VERTEX_SHADER, glsl, &fStats, errorHandler);
SkASSERT(program->fInputs.isEmpty());
sksl.assign(fshaderTxt.c_str(), fshaderTxt.size());
- program = GrSkSLtoGLSL(*fGLContext, SkSL::Program::kFragment_Kind, sksl, settings, &glsl);
+ program = GrSkSLtoGLSL(*fGLContext, SkSL::Program::kFragment_Kind, sksl, settings, &glsl,
+ errorHandler);
GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram,
GR_GL_FRAGMENT_SHADER, glsl, &fStats,
- assertOnCompileFailure);
+ errorHandler);
SkASSERT(program->fInputs.isEmpty());
GL_CALL(LinkProgram(fMipmapPrograms[progIdx].fProgram));
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index d7ac7e4..bed69a3 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -89,15 +89,15 @@
GrGLuint programId,
GrGLenum type,
SkTDArray<GrGLuint>* shaderIds,
- const SkSL::Program::Inputs& inputs) {
+ const SkSL::Program::Inputs& inputs,
+ GrContextOptions::ShaderErrorHandler* errHandler) {
GrGLGpu* gpu = this->gpu();
- bool assertOnCompileFailure = gpu->getContext()->priv().options().fAssertOnShaderCompileFailure;
GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
programId,
type,
glsl,
gpu->stats(),
- assertOnCompileFailure);
+ errHandler);
if (!shaderId) {
return false;
}
@@ -202,6 +202,7 @@
this->finalizeShaders();
// compile shaders and bind attributes / uniforms
+ auto errorHandler = this->gpu()->getContext()->priv().getShaderErrorHandler();
const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
SkSL::Program::Settings settings;
settings.fCaps = this->gpu()->glCaps().shaderCaps();
@@ -241,7 +242,7 @@
length));
if (GR_GL_GET_ERROR(this->gpu()->glInterface()) == GR_GL_NO_ERROR) {
if (checkLinked) {
- cached = this->checkLinkStatus(programID);
+ cached = this->checkLinkStatus(programID, errorHandler, nullptr, nullptr);
}
if (cached) {
this->addInputVars(inputs);
@@ -284,7 +285,8 @@
SkSL::Program::kFragment_Kind,
*sksl[kFragment_GrShaderType],
settings,
- &glsl[kFragment_GrShaderType]);
+ &glsl[kFragment_GrShaderType],
+ errorHandler);
if (!fs) {
this->cleanupProgram(programID, shadersToDelete);
return nullptr;
@@ -297,7 +299,8 @@
this->computeCountsAndStrides(programID, primProc, false);
}
if (!this->compileAndAttachShaders(glsl[kFragment_GrShaderType], programID,
- GR_GL_FRAGMENT_SHADER, &shadersToDelete, inputs)) {
+ GR_GL_FRAGMENT_SHADER, &shadersToDelete, inputs,
+ errorHandler)) {
this->cleanupProgram(programID, shadersToDelete);
return nullptr;
}
@@ -308,14 +311,16 @@
SkSL::Program::kVertex_Kind,
*sksl[kVertex_GrShaderType],
settings,
- &glsl[kVertex_GrShaderType]);
+ &glsl[kVertex_GrShaderType],
+ errorHandler);
if (!vs) {
this->cleanupProgram(programID, shadersToDelete);
return nullptr;
}
}
if (!this->compileAndAttachShaders(glsl[kVertex_GrShaderType], programID,
- GR_GL_VERTEX_SHADER, &shadersToDelete, inputs)) {
+ GR_GL_VERTEX_SHADER, &shadersToDelete, inputs,
+ errorHandler)) {
this->cleanupProgram(programID, shadersToDelete);
return nullptr;
}
@@ -334,14 +339,16 @@
SkSL::Program::kGeometry_Kind,
*sksl[kGeometry_GrShaderType],
settings,
- &glsl[kGeometry_GrShaderType]);
+ &glsl[kGeometry_GrShaderType],
+ errorHandler);
if (!gs) {
this->cleanupProgram(programID, shadersToDelete);
return nullptr;
}
}
if (!this->compileAndAttachShaders(glsl[kGeometry_GrShaderType], programID,
- GR_GL_GEOMETRY_SHADER, &shadersToDelete, inputs)) {
+ GR_GL_GEOMETRY_SHADER, &shadersToDelete, inputs,
+ errorHandler)) {
this->cleanupProgram(programID, shadersToDelete);
return nullptr;
}
@@ -350,22 +357,8 @@
GL_CALL(LinkProgram(programID));
if (checkLinked) {
- if (!this->checkLinkStatus(programID)) {
+ if (!this->checkLinkStatus(programID, errorHandler, sksl, glsl)) {
GL_CALL(DeleteProgram(programID));
- GrGLPrintShader(fGpu->glContext(),
- SkSL::Program::kVertex_Kind,
- fVS.fCompilerString,
- settings);
- if (primProc.willUseGeoShader()) {
- GrGLPrintShader(fGpu->glContext(),
- SkSL::Program::kGeometry_Kind,
- fGS.fCompilerString,
- settings);
- }
- GrGLPrintShader(fGpu->glContext(),
- SkSL::Program::kFragment_Kind,
- fFS.fCompilerString,
- settings);
return nullptr;
}
}
@@ -414,11 +407,27 @@
}
}
-bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
+bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID,
+ GrContextOptions::ShaderErrorHandler* errorHandler,
+ SkSL::String* sksl[], const SkSL::String glsl[]) {
GrGLint linked = GR_GL_INIT_ZERO;
GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
if (!linked) {
- SkDebugf("Program linking failed.\n");
+ SkSL::String allShaders;
+ if (sksl) {
+ allShaders.appendf("// Vertex SKSL\n%s\n", sksl[kVertex_GrShaderType]->c_str());
+ if (!sksl[kGeometry_GrShaderType]->empty()) {
+ allShaders.appendf("// Geometry SKSL\n%s\n", sksl[kGeometry_GrShaderType]->c_str());
+ }
+ allShaders.appendf("// Fragment SKSL\n%s\n", sksl[kFragment_GrShaderType]->c_str());
+ }
+ if (glsl) {
+ allShaders.appendf("// Vertex GLSL\n%s\n", glsl[kVertex_GrShaderType].c_str());
+ if (!glsl[kGeometry_GrShaderType].empty()) {
+ allShaders.appendf("// Geometry GLSL\n%s\n", glsl[kGeometry_GrShaderType].c_str());
+ }
+ allShaders.appendf("// Fragment GLSL\n%s\n", glsl[kFragment_GrShaderType].c_str());
+ }
GrGLint infoLen = GR_GL_INIT_ZERO;
GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
@@ -426,12 +435,9 @@
// retrieve length even though we don't need it to workaround
// bug in chrome cmd buffer param validation.
GrGLsizei length = GR_GL_INIT_ZERO;
- GL_CALL(GetProgramInfoLog(programID,
- infoLen+1,
- &length,
- (char*)log.get()));
- SkDebugf("%s", (char*)log.get());
+ GL_CALL(GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get()));
}
+ errorHandler->compileError(allShaders.c_str(), infoLen > 0 ? (const char*)log.get() : "");
}
return SkToBool(linked);
}
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index cde80ae..1d216b5 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.h
@@ -56,7 +56,8 @@
GrGLuint programId,
GrGLenum type,
SkTDArray<GrGLuint>* shaderIds,
- const SkSL::Program::Inputs& inputs);
+ const SkSL::Program::Inputs& inputs,
+ GrContextOptions::ShaderErrorHandler* errorHandler);
void computeCountsAndStrides(GrGLuint programID, const GrPrimitiveProcessor& primProc,
bool bindAttribLocations);
@@ -64,7 +65,8 @@
const SkSL::String shaders[], bool isSkSL);
GrGLProgram* finalize();
void bindProgramResourceLocations(GrGLuint programID);
- bool checkLinkStatus(GrGLuint programID);
+ bool checkLinkStatus(GrGLuint programID, GrContextOptions::ShaderErrorHandler* errorHandler,
+ SkSL::String* sksl[], const SkSL::String glsl[]);
void resolveProgramResourceLocations(GrGLuint programID);
void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
index 473414e..1bd0396 100644
--- a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
@@ -32,15 +32,14 @@
SkSL::Program::Kind programKind,
const SkSL::String& sksl,
const SkSL::Program::Settings& settings,
- SkSL::String* glsl) {
+ SkSL::String* glsl,
+ GrContextOptions::ShaderErrorHandler* errorHandler) {
SkSL::Compiler* compiler = context.compiler();
std::unique_ptr<SkSL::Program> program;
program = compiler->convertProgram(programKind, sksl, settings);
if (!program || !compiler->toGLSL(*program, glsl)) {
- SkDebugf("SKSL compilation error\n----------------------\n");
- GrShaderUtils::PrintLineByLine("SKSL:", sksl);
- SkDebugf("\nErrors:\n%s\n", compiler->errorText().c_str());
- SkDEBUGFAIL("SKSL compilation failed!\n");
+ errorHandler->compileError(GrShaderUtils::PrettyPrint(sksl).c_str(),
+ compiler->errorText().c_str());
return nullptr;
}
@@ -62,7 +61,7 @@
GrGLenum type,
const SkSL::String& glsl,
GrGpu::Stats* stats,
- bool assertOnFailure) {
+ GrContextOptions::ShaderErrorHandler* errorHandler) {
const GrGLInterface* gli = glCtx.interface();
// Specify GLSL source to the driver.
@@ -88,8 +87,6 @@
GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
if (!compiled) {
- SkDebugf("GLSL compilation error\n----------------------\n");
- GrShaderUtils::PrintLineByLine("GLSL:", glsl);
GrGLint infoLen = GR_GL_INIT_ZERO;
GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
@@ -98,13 +95,8 @@
// buffer param validation.
GrGLsizei length = GR_GL_INIT_ZERO;
GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
- SkDebugf("Errors:\n%s\n", (const char*) log.get());
}
- // In Chrome we may have failed due to context-loss. So we should just continue along
- // wihthout asserting until the GrContext gets abandoned.
- if (assertOnFailure && kChromium_GrGLDriver != glCtx.driver()) {
- SkDEBUGFAIL("GLSL compilation failed!");
- }
+ errorHandler->compileError(glsl.c_str(), infoLen > 0 ? (const char*)log.get() : "");
GR_GL_CALL(gli, DeleteShader(shaderId));
return 0;
}
@@ -117,13 +109,3 @@
GR_GL_CALL(gli, AttachShader(programId, shaderId));
return shaderId;
}
-
-void GrGLPrintShader(const GrGLContext& context, SkSL::Program::Kind programKind,
- const SkSL::String& sksl, const SkSL::Program::Settings& settings) {
- print_shader_banner(programKind);
- GrShaderUtils::PrintLineByLine("SKSL:", sksl);
- SkSL::String glsl;
- if (GrSkSLtoGLSL(context, programKind, sksl, settings, &glsl)) {
- GrShaderUtils::PrintLineByLine("GLSL:", glsl);
- }
-}
diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.h b/src/gpu/gl/builders/GrGLShaderStringBuilder.h
index e65d995..12bebc3 100644
--- a/src/gpu/gl/builders/GrGLShaderStringBuilder.h
+++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.h
@@ -9,6 +9,7 @@
#define GrGLShaderStringBuilder_DEFINED
#include "include/core/SkTypes.h"
+#include "include/gpu/GrContextOptions.h"
#include "src/gpu/GrAllocator.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/gl/GrGLContext.h"
@@ -18,16 +19,14 @@
SkSL::Program::Kind programKind,
const SkSL::String& sksl,
const SkSL::Program::Settings& settings,
- SkSL::String* glsl);
+ SkSL::String* glsl,
+ GrContextOptions::ShaderErrorHandler* errorHandler);
GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
GrGLuint programId,
GrGLenum type,
const SkSL::String& glsl,
GrGpu::Stats*,
- bool assertOnFailure);
-
-void GrGLPrintShader(const GrGLContext&, SkSL::Program::Kind programKind, const SkSL::String& sksl,
- const SkSL::Program::Settings&);
+ GrContextOptions::ShaderErrorHandler* errorHandler);
#endif
diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
index fcd885e..58516e8 100644
--- a/src/gpu/vk/GrVkPipelineStateBuilder.cpp
+++ b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
@@ -106,9 +106,7 @@
static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
int GrVkPipelineStateBuilder::loadShadersFromCache(const SkData& cached,
- VkShaderModule* outVertShaderModule,
- VkShaderModule* outFragShaderModule,
- VkShaderModule* outGeomShaderModule,
+ VkShaderModule outShaderModules[],
VkPipelineShaderStageCreateInfo* outStageInfo) {
SkSL::String shaders[kGrShaderTypeCount];
SkSL::Program::Inputs inputs[kGrShaderTypeCount];
@@ -120,14 +118,14 @@
SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
fVS,
- outVertShaderModule,
+ &outShaderModules[kVertex_GrShaderType],
&outStageInfo[0],
shaders[kVertex_GrShaderType],
inputs[kVertex_GrShaderType]));
SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
fFS,
- outFragShaderModule,
+ &outShaderModules[kFragment_GrShaderType],
&outStageInfo[1],
shaders[kFragment_GrShaderType],
inputs[kFragment_GrShaderType]));
@@ -135,7 +133,7 @@
if (!shaders[kGeometry_GrShaderType].empty()) {
SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
fGS,
- outGeomShaderModule,
+ &outShaderModules[kGeometry_GrShaderType],
&outStageInfo[2],
shaders[kGeometry_GrShaderType],
inputs[kGeometry_GrShaderType]));
@@ -162,9 +160,9 @@
Desc* desc) {
VkDescriptorSetLayout dsLayout[2];
VkPipelineLayout pipelineLayout;
- VkShaderModule vertShaderModule = VK_NULL_HANDLE;
- VkShaderModule geomShaderModule = VK_NULL_HANDLE;
- VkShaderModule fragShaderModule = VK_NULL_HANDLE;
+ VkShaderModule shaderModules[kGrShaderTypeCount] = { VK_NULL_HANDLE,
+ VK_NULL_HANDLE,
+ VK_NULL_HANDLE };
GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
// These layouts are not owned by the PipelineStateBuilder and thus should not be destroyed
@@ -221,8 +219,7 @@
#endif
int numShaderStages = 0;
if (cached && binaryCache) {
- numShaderStages = this->loadShadersFromCache(*cached, &vertShaderModule, &fragShaderModule,
- &geomShaderModule, shaderStageInfo);
+ numShaderStages = this->loadShadersFromCache(*cached, shaderModules, shaderStageInfo);
}
if (!numShaderStages) {
@@ -247,35 +244,48 @@
}
#endif
- SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
+ bool success = this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
*sksl[kVertex_GrShaderType],
- &vertShaderModule,
+ &shaderModules[kVertex_GrShaderType],
&shaderStageInfo[0],
settings,
desc,
&shaders[kVertex_GrShaderType],
- &inputs[kVertex_GrShaderType]));
+ &inputs[kVertex_GrShaderType]);
- SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
- *sksl[kFragment_GrShaderType],
- &fragShaderModule,
- &shaderStageInfo[1],
- settings,
- desc,
- &shaders[kFragment_GrShaderType],
- &inputs[kFragment_GrShaderType]));
+ success = success && this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
+ *sksl[kFragment_GrShaderType],
+ &shaderModules[kFragment_GrShaderType],
+ &shaderStageInfo[1],
+ settings,
+ desc,
+ &shaders[kFragment_GrShaderType],
+ &inputs[kFragment_GrShaderType]);
if (this->primitiveProcessor().willUseGeoShader()) {
- SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
- *sksl[kGeometry_GrShaderType],
- &geomShaderModule,
- &shaderStageInfo[2],
- settings,
- desc,
- &shaders[kGeometry_GrShaderType],
- &inputs[kGeometry_GrShaderType]));
+ success = success && this->createVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
+ *sksl[kGeometry_GrShaderType],
+ &shaderModules[kGeometry_GrShaderType],
+ &shaderStageInfo[2],
+ settings,
+ desc,
+ &shaders[kGeometry_GrShaderType],
+ &inputs[kGeometry_GrShaderType]);
++numShaderStages;
}
+
+ if (!success) {
+ for (int i = 0; i < kGrShaderTypeCount; ++i) {
+ if (shaderModules[i]) {
+ GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(),
+ shaderModules[i], nullptr));
+ }
+ }
+ GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
+ nullptr));
+ return nullptr;
+ }
+
if (persistentCache && !cached) {
bool isSkSL = false;
#if GR_TEST_UTILS
@@ -292,15 +302,13 @@
GrVkPipeline* pipeline = resourceProvider.createPipeline(
this->renderTarget()->numColorSamples(), fPrimProc, fPipeline, stencil, this->origin(),
shaderStageInfo, numShaderStages, primitiveType, compatibleRenderPass, pipelineLayout);
- GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShaderModule,
- nullptr));
- GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShaderModule,
- nullptr));
- // This if check should not be needed since calling destroy on a VK_NULL_HANDLE is allowed.
- // However this is causing a crash in certain drivers (e.g. NVidia).
- if (this->primitiveProcessor().willUseGeoShader()) {
- GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), geomShaderModule,
- nullptr));
+ for (int i = 0; i < kGrShaderTypeCount; ++i) {
+ // This if check should not be needed since calling destroy on a VK_NULL_HANDLE is allowed.
+ // However this is causing a crash in certain drivers (e.g. NVidia).
+ if (shaderModules[i]) {
+ GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), shaderModules[i],
+ nullptr));
+ }
}
if (!pipeline) {
diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.h b/src/gpu/vk/GrVkPipelineStateBuilder.h
index 5a68801..7b79f73 100644
--- a/src/gpu/vk/GrVkPipelineStateBuilder.h
+++ b/src/gpu/vk/GrVkPipelineStateBuilder.h
@@ -91,10 +91,7 @@
Desc*);
// returns number of shader stages
- int loadShadersFromCache(const SkData& cached,
- VkShaderModule* outVertShaderModule,
- VkShaderModule* outFragShaderModule,
- VkShaderModule* outGeomShaderModule,
+ int loadShadersFromCache(const SkData& cached, VkShaderModule outShaderModules[],
VkPipelineShaderStageCreateInfo* outStageInfo);
void storeShadersInCache(const SkSL::String shaders[], const SkSL::Program::Inputs inputs[],
diff --git a/src/gpu/vk/GrVkUtil.cpp b/src/gpu/vk/GrVkUtil.cpp
index d1de474..6738bc9 100644
--- a/src/gpu/vk/GrVkUtil.cpp
+++ b/src/gpu/vk/GrVkUtil.cpp
@@ -7,6 +7,7 @@
#include "src/gpu/vk/GrVkUtil.h"
+#include "src/gpu/GrContextPriv.h"
#include "src/gpu/vk/GrVkGpu.h"
#include "src/sksl/SkSLCompiler.h"
@@ -207,16 +208,18 @@
const SkSL::Program::Settings& settings,
SkSL::String* outSPIRV,
SkSL::Program::Inputs* outInputs) {
+ auto errorHandler = gpu->getContext()->priv().getShaderErrorHandler();
std::unique_ptr<SkSL::Program> program = gpu->shaderCompiler()->convertProgram(
vk_shader_stage_to_skiasl_kind(stage), shaderString, settings);
if (!program) {
- printf("%s\n", shaderString.c_str());
- SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str());
- SkASSERT(false);
+ errorHandler->compileError(shaderString.c_str(),
+ gpu->shaderCompiler()->errorText().c_str());
+ return false;
}
*outInputs = program->fInputs;
if (!gpu->shaderCompiler()->toSPIRV(*program, outSPIRV)) {
- SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str());
+ errorHandler->compileError(shaderString.c_str(),
+ gpu->shaderCompiler()->errorText().c_str());
return false;
}