When precompiling SkSL, avoid the need to re-link
Adds metadata to the SkSL blobs about attributes (and other resources)
so that we can do all necessary work during precompile.
Change-Id: I1846c6c96946d5a43a48112d062853717a6571a0
Bug: skia:9402
Bug: b/140174804
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/243739
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 38c15ff..c521c31 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -163,7 +163,7 @@
void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Inputs& inputs, GrGLuint programID,
const SkSL::String shaders[], bool isSkSL,
- const SkSL::Program::Settings& settings) {
+ SkSL::Program::Settings* settings) {
if (!this->gpu()->getContext()->priv().getPersistentCache()) {
return;
}
@@ -188,9 +188,20 @@
this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
}
} else {
- // source cache
+ // source cache, plus metadata to allow for a complete precompile
+ GrPersistentCacheUtils::ShaderMetadata meta;
+ meta.fSettings = settings;
+ meta.fHasCustomColorOutput = fFS.hasCustomColorOutput();
+ meta.fHasSecondaryColorOutput = fFS.hasSecondaryOutput();
+ for (const auto& attr : this->primitiveProcessor().vertexAttributes()) {
+ meta.fAttributeNames.emplace_back(attr.name());
+ }
+ for (const auto& attr : this->primitiveProcessor().instanceAttributes()) {
+ meta.fAttributeNames.emplace_back(attr.name());
+ }
+
auto data = GrPersistentCacheUtils::PackCachedShaders(isSkSL ? kSKSL_Tag : kGLSL_Tag,
- shaders, &inputs, 1, &settings);
+ shaders, &inputs, 1, &meta);
this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
}
}
@@ -247,12 +258,8 @@
if (precompiledProgram) {
// This is very similar to when we get program binaries. We even set that flag, as it's
// used to prevent other compile work later, and to force re-querying uniform locations.
- // We couldn't bind attribute or program resource locations during the pre-compile, so do
- // that now. Those APIs don't take effect until the next link, so re-link the program.
this->addInputVars(precompiledProgram->fInputs);
- this->computeCountsAndStrides(programID, primProc, true);
- this->bindProgramResourceLocations(programID);
- GL_CALL(LinkProgram(programID));
+ this->computeCountsAndStrides(programID, primProc, false);
usedProgramBinaries = true;
} else if (cached) {
SkReader32 reader(fCached->data(), fCached->size());
@@ -416,7 +423,7 @@
}
isSkSL = true;
}
- this->storeShaderInCache(inputs, programID, glsl, isSkSL, settings);
+ this->storeShaderInCache(inputs, programID, glsl, isSkSL, &settings);
}
return this->createProgram(programID);
}
@@ -540,12 +547,15 @@
SkTDArray<GrGLuint> shadersToDelete;
SkSL::Program::Settings settings;
- settings.fCaps = gpu->glCaps().shaderCaps();
+ const GrGLCaps& caps = gpu->glCaps();
+ settings.fCaps = caps.shaderCaps();
settings.fSharpenTextures = gpu->getContext()->priv().options().fSharpenMipmappedTextures;
+ GrPersistentCacheUtils::ShaderMetadata meta;
+ meta.fSettings = &settings;
SkSL::String shaders[kGrShaderTypeCount];
SkSL::Program::Inputs inputs;
- GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &inputs, 1, &settings);
+ GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &inputs, 1, &meta);
auto compileShader = [&](SkSL::Program::Kind kind, const SkSL::String& sksl, GrGLenum type) {
SkSL::String glsl;
@@ -577,6 +587,20 @@
return false;
}
+ for (int i = 0; i < meta.fAttributeNames.count(); ++i) {
+ GR_GL_CALL(gpu->glInterface(), BindAttribLocation(programID, i,
+ meta.fAttributeNames[i].c_str()));
+ }
+
+ if (meta.fHasCustomColorOutput && caps.bindFragDataLocationSupport()) {
+ GR_GL_CALL(gpu->glInterface(), BindFragDataLocation(programID, 0,
+ GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
+ }
+ if (meta.fHasSecondaryColorOutput && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
+ GR_GL_CALL(gpu->glInterface(), BindFragDataLocationIndexed(programID, 0, 1,
+ GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
+ }
+
GR_GL_CALL(gpu->glInterface(), LinkProgram(programID));
GrGLint linked = GR_GL_INIT_ZERO;
GR_GL_CALL(gpu->glInterface(), GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));