aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrContext.cpp2
-rw-r--r--src/gpu/gl/GrGLAssembleInterface.cpp12
-rw-r--r--src/gpu/gl/GrGLCaps.cpp8
-rw-r--r--src/gpu/gl/GrGLCaps.h5
-rw-r--r--src/gpu/gl/GrGLCreateNullInterface.cpp3
-rw-r--r--src/gpu/gl/GrGLDefines.h4
-rw-r--r--src/gpu/gl/GrGLGpu.cpp69
-rw-r--r--src/gpu/gl/GrGLInterface.cpp9
-rw-r--r--src/gpu/gl/GrGLTestInterface.cpp3
-rw-r--r--src/gpu/gl/GrGLTestInterface.h3
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp182
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.h15
-rw-r--r--src/gpu/gl/builders/GrGLShaderStringBuilder.cpp87
-rw-r--r--src/gpu/gl/builders/GrGLShaderStringBuilder.h13
14 files changed, 286 insertions, 129 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 2d9f0115e3..2146858f79 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -213,6 +213,8 @@ bool GrContext::init(const GrContextOptions& options) {
fTaskGroup = skstd::make_unique<SkTaskGroup>(*options.fExecutor);
}
+ fPersistentCache = options.fPersistentCache;
+
return true;
}
diff --git a/src/gpu/gl/GrGLAssembleInterface.cpp b/src/gpu/gl/GrGLAssembleInterface.cpp
index d33a8b6cb1..b7698f1473 100644
--- a/src/gpu/gl/GrGLAssembleInterface.cpp
+++ b/src/gpu/gl/GrGLAssembleInterface.cpp
@@ -535,6 +535,12 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
GET_PROC(GetInternalformativ);
}
+ if (glVer >= GR_GL_VER(4, 1)) {
+ GET_PROC(GetProgramBinary);
+ GET_PROC(ProgramBinary);
+ GET_PROC(ProgramParameteri);
+ }
+
interface->fStandard = kGL_GrGLStandard;
interface->fExtensions.swap(&extensions);
@@ -977,6 +983,12 @@ const GrGLInterface* GrGLAssembleGLESInterface(void* ctx, GrGLGetProc get) {
GET_PROC(GetInternalformativ);
}
+ if (version >= GR_GL_VER(3, 0)) {
+ GET_PROC(GetProgramBinary);
+ GET_PROC(ProgramBinary);
+ GET_PROC(ProgramParameteri);
+ }
+
interface->fStandard = kGLES_GrGLStandard;
interface->fExtensions.swap(&extensions);
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 4ba504c4c9..9a454ef2b7 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -718,6 +718,14 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
fDrawArraysBaseVertexIsBroken = true;
}
+ if (kGL_GrGLStandard == standard) {
+ if (version >= GR_GL_VER(4, 1)) {
+ fProgramBinarySupport = true;
+ }
+ } else if (version >= GR_GL_VER(3, 0)) {
+ fProgramBinarySupport = true;
+ }
+
// Requires fTextureRedSupport, fTextureSwizzleSupport, msaa support, ES compatibility have
// already been detected.
this->initConfigTable(contextOptions, ctxInfo, gli, shaderCaps);
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index e9c325313a..2c82c4c021 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -414,6 +414,10 @@ public:
bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
bool* rectsMustMatch, bool* disallowSubrect) const override;
+ bool programBinarySupport() const {
+ return fProgramBinarySupport;
+ }
+
private:
enum ExternalFormatUsage {
kTexImage_ExternalFormatUsage,
@@ -490,6 +494,7 @@ private:
bool fDisallowTexSubImageForUnormConfigTexturesEverBoundToFBO : 1;
bool fUseDrawInsteadOfAllRenderTargetWrites : 1;
bool fRequiresCullFaceEnableDisableWhenDrawingLinesAfterNonLines : 1;
+ bool fProgramBinarySupport : 1;
uint32_t fBlitFramebufferFlags;
int fMaxInstancesPerDrawArraysWithoutCrashing;
diff --git a/src/gpu/gl/GrGLCreateNullInterface.cpp b/src/gpu/gl/GrGLCreateNullInterface.cpp
index e130247862..3b8b1fec04 100644
--- a/src/gpu/gl/GrGLCreateNullInterface.cpp
+++ b/src/gpu/gl/GrGLCreateNullInterface.cpp
@@ -789,7 +789,8 @@ private:
case GR_GL_COMPILE_STATUS:
*params = GR_GL_TRUE;
break;
- case GR_GL_INFO_LOG_LENGTH:
+ case GR_GL_INFO_LOG_LENGTH: // fallthru
+ case GL_PROGRAM_BINARY_LENGTH:
*params = 0;
break;
// we don't expect any other pnames
diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h
index b62c26bcc2..db6abd482f 100644
--- a/src/gpu/gl/GrGLDefines.h
+++ b/src/gpu/gl/GrGLDefines.h
@@ -1079,4 +1079,8 @@
#define GR_EGL_NONE 0x3038
#define GR_EGL_NO_IMAGE ((GrEGLImage)0)
+/* Programs */
+#define GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+
#endif
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index d3bd6e3cd0..6b194f98f7 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3570,18 +3570,21 @@ bool GrGLGpu::createCopyProgram(GrTexture* srcTex) {
length = SkToInt(vshaderTxt.size());
SkSL::Program::Settings settings;
settings.fCaps = shaderCaps;
- SkSL::Program::Inputs inputs;
+ SkSL::String glsl;
+ std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(*fGLContext, GR_GL_VERTEX_SHADER,
+ &str, &length, 1, settings, &glsl);
GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
- GR_GL_VERTEX_SHADER, &str, &length, 1,
- &fStats, settings, &inputs);
- SkASSERT(inputs.isEmpty());
+ GR_GL_VERTEX_SHADER, glsl.c_str(), glsl.size(),
+ &fStats, settings);
+ SkASSERT(program->fInputs.isEmpty());
str = fshaderTxt.c_str();
length = SkToInt(fshaderTxt.size());
+ program = GrSkSLtoGLSL(*fGLContext, GR_GL_FRAGMENT_SHADER, &str, &length, 1, settings, &glsl);
GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
- GR_GL_FRAGMENT_SHADER, &str, &length, 1,
- &fStats, settings, &inputs);
- SkASSERT(inputs.isEmpty());
+ GR_GL_FRAGMENT_SHADER, glsl.c_str(), glsl.size(),
+ &fStats, settings);
+ SkASSERT(program->fInputs.isEmpty());
GL_CALL(LinkProgram(fCopyPrograms[progIdx].fProgram));
@@ -3726,18 +3729,21 @@ bool GrGLGpu::createMipmapProgram(int progIdx) {
length = SkToInt(vshaderTxt.size());
SkSL::Program::Settings settings;
settings.fCaps = shaderCaps;
- SkSL::Program::Inputs inputs;
+ SkSL::String glsl;
+ std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(*fGLContext, GR_GL_VERTEX_SHADER,
+ &str, &length, 1, settings, &glsl);
GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram,
- GR_GL_VERTEX_SHADER, &str, &length, 1,
- &fStats, settings, &inputs);
- SkASSERT(inputs.isEmpty());
+ GR_GL_VERTEX_SHADER, glsl.c_str(), glsl.size(),
+ &fStats, settings);
+ SkASSERT(program->fInputs.isEmpty());
str = fshaderTxt.c_str();
length = SkToInt(fshaderTxt.size());
+ program = GrSkSLtoGLSL(*fGLContext, GR_GL_FRAGMENT_SHADER, &str, &length, 1, settings, &glsl);
GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram,
- GR_GL_FRAGMENT_SHADER, &str, &length, 1,
- &fStats, settings, &inputs);
- SkASSERT(inputs.isEmpty());
+ GR_GL_FRAGMENT_SHADER, glsl.c_str(), glsl.size(),
+ &fStats, settings);
+ SkASSERT(program->fInputs.isEmpty());
GL_CALL(LinkProgram(fMipmapPrograms[progIdx].fProgram));
@@ -3798,18 +3804,21 @@ bool GrGLGpu::createStencilClipClearProgram() {
length = SkToInt(vshaderTxt.size());
SkSL::Program::Settings settings;
settings.fCaps = this->caps()->shaderCaps();
- SkSL::Program::Inputs inputs;
- GrGLuint vshader =
- GrGLCompileAndAttachShader(*fGLContext, fStencilClipClearProgram, GR_GL_VERTEX_SHADER,
- &str, &length, 1, &fStats, settings, &inputs);
- SkASSERT(inputs.isEmpty());
+ SkSL::String glsl;
+ std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(*fGLContext, GR_GL_VERTEX_SHADER,
+ &str, &length, 1, settings, &glsl);
+ GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fStencilClipClearProgram,
+ GR_GL_VERTEX_SHADER, glsl.c_str(), glsl.size(),
+ &fStats, settings);
+ SkASSERT(program->fInputs.isEmpty());
str = fshaderTxt.c_str();
length = SkToInt(fshaderTxt.size());
- GrGLuint fshader =
- GrGLCompileAndAttachShader(*fGLContext, fStencilClipClearProgram, GR_GL_FRAGMENT_SHADER,
- &str, &length, 1, &fStats, settings, &inputs);
- SkASSERT(inputs.isEmpty());
+ program = GrSkSLtoGLSL(*fGLContext, GR_GL_FRAGMENT_SHADER, &str, &length, 1, settings, &glsl);
+ GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fStencilClipClearProgram,
+ GR_GL_FRAGMENT_SHADER, glsl.c_str(), glsl.size(),
+ &fStats, settings);
+ SkASSERT(program->fInputs.isEmpty());
GL_CALL(LinkProgram(fStencilClipClearProgram));
@@ -3910,18 +3919,18 @@ bool GrGLGpu::createClearColorProgram() {
length = SkToInt(vshaderTxt.size());
SkSL::Program::Settings settings;
settings.fCaps = this->caps()->shaderCaps();
- SkSL::Program::Inputs inputs;
+ SkSL::String glsl;
+ GrSkSLtoGLSL(*fGLContext, GR_GL_VERTEX_SHADER, &str, &length, 1, settings, &glsl);
GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fClearColorProgram.fProgram,
- GR_GL_VERTEX_SHADER, &str, &length, 1, &fStats,
- settings, &inputs);
- SkASSERT(inputs.isEmpty());
+ GR_GL_VERTEX_SHADER, glsl.c_str(), glsl.size(),
+ &fStats, settings);
str = fshaderTxt.c_str();
length = SkToInt(fshaderTxt.size());
+ GrSkSLtoGLSL(*fGLContext, GR_GL_FRAGMENT_SHADER, &str, &length, 1, settings, &glsl);
GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fClearColorProgram.fProgram,
- GR_GL_FRAGMENT_SHADER, &str, &length, 1, &fStats,
- settings, &inputs);
- SkASSERT(inputs.isEmpty());
+ GR_GL_FRAGMENT_SHADER, glsl.c_str(), glsl.size(),
+ &fStats, settings);
GL_CALL(LinkProgram(fClearColorProgram.fProgram));
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
index 81c4569519..8ce8af7098 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -819,5 +819,14 @@ bool GrGLInterface::validate() const {
}
}
+ if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,1)) ||
+ (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0))) {
+ if (!fFunctions.fGetProgramBinary ||
+ !fFunctions.fProgramBinary ||
+ !fFunctions.fProgramParameteri) {
+ RETURN_FALSE_INTERFACE;
+ }
+ }
+
return true;
}
diff --git a/src/gpu/gl/GrGLTestInterface.cpp b/src/gpu/gl/GrGLTestInterface.cpp
index d95fd09120..bceb947c58 100644
--- a/src/gpu/gl/GrGLTestInterface.cpp
+++ b/src/gpu/gl/GrGLTestInterface.cpp
@@ -326,4 +326,7 @@ GrGLTestInterface::GrGLTestInterface() {
fFunctions.fPopDebugGroup = bind_to_member(this, &GrGLTestInterface::popDebugGroup);
fFunctions.fObjectLabel = bind_to_member(this, &GrGLTestInterface::objectLabel);
fFunctions.fGetInternalformativ = bind_to_member(this, &GrGLTestInterface::getInternalformativ);
+ fFunctions.fProgramBinary = bind_to_member(this, &GrGLTestInterface::programBinary);
+ fFunctions.fGetProgramBinary = bind_to_member(this, &GrGLTestInterface::getProgramBinary);
+ fFunctions.fProgramParameteri = bind_to_member(this, &GrGLTestInterface::programParameteri);
}
diff --git a/src/gpu/gl/GrGLTestInterface.h b/src/gpu/gl/GrGLTestInterface.h
index 1ebf90b7cf..58b6f84c02 100644
--- a/src/gpu/gl/GrGLTestInterface.h
+++ b/src/gpu/gl/GrGLTestInterface.h
@@ -331,6 +331,9 @@ public:
virtual GrGLvoid popDebugGroup() {}
virtual GrGLvoid objectLabel(GrGLenum identifier, GrGLuint name, GrGLsizei length, const GrGLchar *label) {}
virtual GrGLvoid getInternalformativ(GrGLenum target, GrGLenum internalformat, GrGLenum pname, GrGLsizei bufSize, GrGLint *params) {}
+ virtual GrGLvoid programBinary(GrGLuint program, GrGLenum binaryFormat, void *binary, GrGLsizei length) {}
+ virtual GrGLvoid getProgramBinary(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length, GrGLenum *binaryFormat, void *binary) {}
+ virtual GrGLvoid programParameteri(GrGLuint program, GrGLenum pname, GrGLint value) {}
protected:
// This must be called by leaf class
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 31d20f0421..c9bc8f8910 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -41,11 +41,17 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrPipeline& pipeline,
// uniforms, varyings, textures, etc
GrGLProgramBuilder builder(gpu, pipeline, primProc, desc);
+ if (gpu->getContext()->getPersistentCache() && gpu->glCaps().programBinarySupport()) {
+ sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->keyLength());
+ builder.fCached = gpu->getContext()->getPersistentCache()->load(*key);
+ // the eventual end goal is to completely skip emitAndInstallProcs on a cache hit, but it's
+ // doing necessary setup in addition to generating the SkSL code. Currently we are only able
+ // to skip the SkSL->GLSL step on a cache hit.
+ }
if (!builder.emitAndInstallProcs()) {
builder.cleanupFragmentProcessors();
return nullptr;
}
-
return builder.finalize();
}
@@ -65,29 +71,27 @@ const GrCaps* GrGLProgramBuilder::caps() const {
return fGpu->caps();
}
-bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
+bool GrGLProgramBuilder::compileAndAttachShaders(const char* glsl,
+ int length,
GrGLuint programId,
GrGLenum type,
SkTDArray<GrGLuint>* shaderIds,
const SkSL::Program::Settings& settings,
- SkSL::Program::Inputs* outInputs) {
+ const SkSL::Program::Inputs& inputs) {
GrGLGpu* gpu = this->gpu();
GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
programId,
type,
- shader.fCompilerStrings.begin(),
- shader.fCompilerStringLengths.begin(),
- shader.fCompilerStrings.count(),
+ glsl,
+ length,
gpu->stats(),
- settings,
- outInputs);
-
+ settings);
if (!shaderId) {
return false;
}
*shaderIds->append() = shaderId;
- if (outInputs->fFlipY) {
+ if (inputs.fFlipY) {
GrProgramDesc* d = this->desc();
d->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
this->pipeline().proxy()->origin()));
@@ -97,6 +101,29 @@ bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
return true;
}
+bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
+ GrGLuint programId,
+ GrGLenum type,
+ SkTDArray<GrGLuint>* shaderIds,
+ const SkSL::Program::Settings& settings,
+ SkSL::Program::Inputs* outInputs) {
+ SkSL::String glsl;
+ std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(gpu()->glContext(), type,
+ shader.fCompilerStrings.begin(),
+ shader.fCompilerStringLengths.begin(),
+ shader.fCompilerStrings.count(),
+ settings,
+ &glsl);
+ *outInputs = program->fInputs;
+ return this->compileAndAttachShaders(glsl.c_str(),
+ glsl.size(),
+ programId,
+ type,
+ shaderIds,
+ settings,
+ *outInputs);
+}
+
GrGLProgram* GrGLProgramBuilder::finalize() {
TRACE_EVENT0("skia", TRACE_FUNC);
@@ -108,54 +135,99 @@ GrGLProgram* GrGLProgramBuilder::finalize() {
return nullptr;
}
+ if (this->gpu()->getContext()->getPersistentCache()) {
+ GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
+ }
+
this->finalizeShaders();
// compile shaders and bind attributes / uniforms
+ const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
SkSL::Program::Settings settings;
settings.fCaps = this->gpu()->glCaps().shaderCaps();
settings.fFlipY = this->pipeline().proxy()->origin() != kTopLeft_GrSurfaceOrigin;
SkSL::Program::Inputs inputs;
SkTDArray<GrGLuint> shadersToDelete;
- if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &shadersToDelete,
- settings, &inputs)) {
- this->cleanupProgram(programID, shadersToDelete);
- return nullptr;
- }
-
- // NVPR actually requires a vertex shader to compile
- const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
- bool useNvpr = primProc.isPathRendering();
- if (!useNvpr) {
- int vaCount = primProc.numAttribs();
- for (int i = 0; i < vaCount; i++) {
- GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
+ bool cached = nullptr != fCached.get();
+ if (cached) {
+ // cache hit, just hand the binary to GL
+ const uint8_t* bytes = fCached->bytes();
+ size_t offset = 0;
+ memcpy(&inputs, bytes + offset, sizeof(inputs));
+ offset += sizeof(inputs);
+ int binaryFormat;
+ memcpy(&binaryFormat, bytes + offset, sizeof(binaryFormat));
+ offset += sizeof(binaryFormat);
+ GL_CALL(ProgramBinary(programID, binaryFormat, (void*) (bytes + offset),
+ fCached->size() - offset));
+ } else {
+ // cache miss, compile shaders
+ if (fFS.fForceHighPrecision) {
+ settings.fForceHighPrecision = true;
+ }
+ SkSL::String glsl;
+ std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(gpu()->glContext(),
+ GR_GL_FRAGMENT_SHADER,
+ fFS.fCompilerStrings.begin(),
+ fFS.fCompilerStringLengths.begin(),
+ fFS.fCompilerStrings.count(),
+ settings,
+ &glsl);
+ inputs = fs->fInputs;
+ if (inputs.fRTHeight) {
+ this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
+ }
+ if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
+ GR_GL_FRAGMENT_SHADER, &shadersToDelete, settings,
+ inputs)) {
+ this->cleanupProgram(programID, shadersToDelete);
+ return nullptr;
}
- }
-
- if (primProc.willUseGeoShader() &&
- !this->compileAndAttachShaders(fGS, programID, GR_GL_GEOMETRY_SHADER, &shadersToDelete,
- settings, &inputs)) {
- this->cleanupProgram(programID, shadersToDelete);
- return nullptr;
- }
- if (fFS.fForceHighPrecision) {
- settings.fForceHighPrecision = true;
- }
- if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete,
- settings, &inputs)) {
- this->cleanupProgram(programID, shadersToDelete);
- return nullptr;
- }
+ std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(gpu()->glContext(),
+ GR_GL_VERTEX_SHADER,
+ fVS.fCompilerStrings.begin(),
+ fVS.fCompilerStringLengths.begin(),
+ fVS.fCompilerStrings.count(),
+ settings,
+ &glsl);
+ if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
+ GR_GL_VERTEX_SHADER, &shadersToDelete, settings,
+ inputs)) {
+ this->cleanupProgram(programID, shadersToDelete);
+ return nullptr;
+ }
- if (inputs.fRTHeight) {
- this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
- }
+ // NVPR actually requires a vertex shader to compile
+ bool useNvpr = primProc.isPathRendering();
+ if (!useNvpr) {
+ int vaCount = primProc.numAttribs();
+ for (int i = 0; i < vaCount; i++) {
+ GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
+ }
+ }
- this->bindProgramResourceLocations(programID);
+ if (primProc.willUseGeoShader()) {
+ std::unique_ptr<SkSL::Program> gs;
+ gs = GrSkSLtoGLSL(gpu()->glContext(),
+ GR_GL_GEOMETRY_SHADER,
+ fGS.fCompilerStrings.begin(),
+ fGS.fCompilerStringLengths.begin(),
+ fGS.fCompilerStrings.count(),
+ settings,
+ &glsl);
+ if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
+ GR_GL_GEOMETRY_SHADER, &shadersToDelete, settings,
+ inputs)) {
+ this->cleanupProgram(programID, shadersToDelete);
+ return nullptr;
+ }
- GL_CALL(LinkProgram(programID));
+ }
+ this->bindProgramResourceLocations(programID);
+ GL_CALL(LinkProgram(programID));
+ }
// Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
#ifdef SK_DEBUG
@@ -184,7 +256,27 @@ GrGLProgram* GrGLProgramBuilder::finalize() {
this->resolveProgramResourceLocations(programID);
this->cleanupShaders(shadersToDelete);
-
+ if (!cached && this->gpu()->getContext()->getPersistentCache() &&
+ fGpu->glCaps().programBinarySupport()) {
+ // store shader in cache
+ sk_sp<SkData> key = SkData::MakeWithoutCopy(desc()->asKey(), desc()->keyLength());
+ GrGLsizei length = 0;
+ GrGLenum binaryFormat;
+ GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
+ std::unique_ptr<char> binary(new char[length]);
+ GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get()));
+ size_t dataLength = sizeof(inputs) + sizeof(binaryFormat) + length;
+ std::unique_ptr<uint8_t> data((uint8_t*) malloc(dataLength));
+ size_t offset = 0;
+ memcpy(data.get() + offset, &inputs, sizeof(inputs));
+ offset += sizeof(inputs);
+ memcpy(data.get() + offset, &binaryFormat, sizeof(binaryFormat));
+ offset += sizeof(binaryFormat);
+ memcpy(data.get() + offset, binary.get(), length);
+ this->gpu()->getContext()->getPersistentCache()->store(*key,
+ *SkData::MakeWithoutCopy(data.get(),
+ dataLength));
+ }
return this->createProgram(programID);
}
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index cfbb734155..54c91b448b 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.h
@@ -47,6 +47,14 @@ private:
GrGLProgramBuilder(GrGLGpu*, const GrPipeline&, const GrPrimitiveProcessor&,
GrProgramDesc*);
+ bool compileAndAttachShaders(const char* glsl,
+ int length,
+ GrGLuint programId,
+ GrGLenum type,
+ SkTDArray<GrGLuint>* shaderIds,
+ const SkSL::Program::Settings& settings,
+ const SkSL::Program::Inputs& inputs);
+
bool compileAndAttachShaders(GrGLSLShaderBuilder& shader,
GrGLuint programId,
GrGLenum type,
@@ -67,11 +75,16 @@ private:
const GrGLSLUniformHandler* uniformHandler() const override { return &fUniformHandler; }
GrGLSLVaryingHandler* varyingHandler() override { return &fVaryingHandler; }
-
GrGLGpu* fGpu;
GrGLVaryingHandler fVaryingHandler;
GrGLUniformHandler fUniformHandler;
+ // shader pulled from cache. Data is organized as:
+ // SkSL::Program::Inputs inputs
+ // int binaryFormat
+ // (all remaining bytes) char[] binary
+ sk_sp<SkData> fCached;
+
typedef GrGLSLProgramBuilder INHERITED;
};
#endif
diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
index f7eae42ca0..eb2d4644d0 100644
--- a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
@@ -32,24 +32,41 @@ static void print_source_lines_with_numbers(const char* source,
}
// Prints shaders one line at the time. This ensures they don't get truncated by the adb log.
-static void print_shaders_line_by_line(const char** skslStrings, int* lengths,
- int count, const SkSL::String& glsl,
- std::function<void(const char*)> println = [](const char* ln) {
- SkDebugf("%s\n", ln);
- }) {
+static void print_sksl_line_by_line(const char** skslStrings, int* lengths, int count,
+ std::function<void(const char*)> println = [](const char* ln) {
+ SkDebugf("%s\n", ln);
+ }) {
SkSL::String sksl = GrSKSLPrettyPrint::PrettyPrint(skslStrings, lengths, count, false);
println("SKSL:");
print_source_lines_with_numbers(sksl.c_str(), println);
- if (0 != glsl.size()) {
- println("GLSL:");
- print_source_lines_with_numbers(glsl.c_str(), println);
- }
}
-std::unique_ptr<SkSL::Program> translate_to_glsl(const GrGLContext& context, GrGLenum type,
- const char** skslStrings, int* lengths, int count,
- const SkSL::Program::Settings& settings,
- SkSL::String* glsl) {
+static void print_glsl_line_by_line(const SkSL::String& glsl,
+ std::function<void(const char*)> println = [](const char* ln) {
+ SkDebugf("%s\n", ln);
+ }) {
+ println("GLSL:");
+ print_source_lines_with_numbers(glsl.c_str(), println);
+}
+
+std::unique_ptr<SkSL::Program> GrSkSLtoGLSL(const GrGLContext& context, GrGLenum type,
+ const char** skslStrings, int* lengths, int count,
+ const SkSL::Program::Settings& settings,
+ SkSL::String* glsl) {
+ // Trace event for shader preceding driver compilation
+ bool traceShader;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED("skia.gpu", &traceShader);
+ if (traceShader) {
+ SkString shaderDebugString;
+ print_sksl_line_by_line(skslStrings, lengths, count, [&](const char* ln) {
+ shaderDebugString.append(ln);
+ shaderDebugString.append("\n");
+ });
+ TRACE_EVENT_INSTANT1("skia.gpu", "skia_gpu::GLShader",
+ TRACE_EVENT_SCOPE_THREAD, "shader",
+ TRACE_STR_COPY(shaderDebugString.c_str()));
+ }
+
SkSL::String sksl;
#ifdef SK_DEBUG
sksl = GrSKSLPrettyPrint::PrettyPrint(skslStrings, lengths, count, false);
@@ -69,7 +86,7 @@ std::unique_ptr<SkSL::Program> translate_to_glsl(const GrGLContext& context, GrG
program = compiler->convertProgram(programKind, sksl, settings);
if (!program || !compiler->toGLSL(*program, glsl)) {
SkDebugf("SKSL compilation error\n----------------------\n");
- print_shaders_line_by_line(skslStrings, lengths, count, *glsl);
+ print_sksl_line_by_line(skslStrings, lengths, count);
SkDebugf("\nErrors:\n%s\n", compiler->errorText().c_str());
SkDEBUGFAIL("SKSL compilation failed!\n");
return nullptr;
@@ -80,43 +97,19 @@ std::unique_ptr<SkSL::Program> translate_to_glsl(const GrGLContext& context, GrG
GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
GrGLuint programId,
GrGLenum type,
- const char** skslStrings,
- int* lengths,
- int count,
+ const char* glsl,
+ int glslLength,
GrGpu::Stats* stats,
- const SkSL::Program::Settings& settings,
- SkSL::Program::Inputs* outInputs) {
+ const SkSL::Program::Settings& settings) {
const GrGLInterface* gli = glCtx.interface();
- SkSL::String glsl;
- auto program = translate_to_glsl(glCtx, type, skslStrings, lengths, count, settings, &glsl);
- if (!program) {
- return 0;
- }
-
// Specify GLSL source to the driver.
GrGLuint shaderId;
GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
if (0 == shaderId) {
return 0;
}
- const char* glslChars = glsl.c_str();
- GrGLint glslLength = (GrGLint) glsl.size();
- GR_GL_CALL(gli, ShaderSource(shaderId, 1, &glslChars, &glslLength));
-
- // Trace event for shader preceding driver compilation
- bool traceShader;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED("skia.gpu", &traceShader);
- if (traceShader) {
- SkString shaderDebugString;
- print_shaders_line_by_line(skslStrings, lengths, count, glsl, [&](const char* ln) {
- shaderDebugString.append(ln);
- shaderDebugString.append("\n");
- });
- TRACE_EVENT_INSTANT1("skia.gpu", "skia_gpu::GLShader",
- TRACE_EVENT_SCOPE_THREAD, "shader",
- TRACE_STR_COPY(shaderDebugString.c_str()));
- }
+ GR_GL_CALL(gli, ShaderSource(shaderId, 1, &glsl, &glslLength));
stats->incShaderCompilations();
GR_GL_CALL(gli, CompileShader(shaderId));
@@ -132,7 +125,7 @@ GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
if (!compiled) {
SkDebugf("GLSL compilation error\n----------------------\n");
- print_shaders_line_by_line(skslStrings, lengths, count, glsl);
+ print_glsl_line_by_line(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
@@ -157,7 +150,7 @@ GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
case GR_GL_FRAGMENT_SHADER: typeName = "Fragment"; break;
}
SkDebugf("---- %s shader ----------------------------------------------------\n", typeName);
- print_shaders_line_by_line(skslStrings, lengths, count, glsl);
+ print_glsl_line_by_line(glsl);
}
// Attach the shader, but defer deletion until after we have linked the program.
@@ -165,14 +158,14 @@ GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
// will immediately delete the shader object and free its memory even though it's
// attached to a program, which then causes glLinkProgram to fail.
GR_GL_CALL(gli, AttachShader(programId, shaderId));
- *outInputs = program->fInputs;
return shaderId;
}
void GrGLPrintShader(const GrGLContext& context, GrGLenum type, const char** skslStrings,
int* lengths, int count, const SkSL::Program::Settings& settings) {
+ print_sksl_line_by_line(skslStrings, lengths, count);
SkSL::String glsl;
- if (translate_to_glsl(context, type, skslStrings, lengths, count, settings, &glsl)) {
- print_shaders_line_by_line(skslStrings, lengths, count, glsl);
+ if (GrSkSLtoGLSL(context, type, skslStrings, lengths, count, settings, &glsl)) {
+ print_glsl_line_by_line(glsl);
}
}
diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.h b/src/gpu/gl/builders/GrGLShaderStringBuilder.h
index 59dea35b8d..c693a390cc 100644
--- a/src/gpu/gl/builders/GrGLShaderStringBuilder.h
+++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.h
@@ -14,15 +14,18 @@
#include "SkSLGLSLCodeGenerator.h"
#include "SkTypes.h"
+std::unique_ptr<SkSL::Program> GrSkSLtoGLSL(const GrGLContext& context, GrGLenum type,
+ const char** skslStrings, int* lengths, int count,
+ const SkSL::Program::Settings& settings,
+ SkSL::String* glsl);
+
GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
GrGLuint programId,
GrGLenum type,
- const char** skslStrings,
- int* lengths,
- int count,
+ const char* glsl,
+ int glslLength,
GrGpu::Stats*,
- const SkSL::Program::Settings& settings,
- SkSL::Program::Inputs* inputs);
+ const SkSL::Program::Settings& settings);
void GrGLPrintShader(const GrGLContext&, GrGLenum type, const char** skslStrings, int* lengths,
int count, const SkSL::Program::Settings&);