• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/gpu/gl/builders/GrGLProgramBuilder.h"
9 
10 #include "include/gpu/GrContext.h"
11 #include "src/core/SkATrace.h"
12 #include "src/core/SkAutoMalloc.h"
13 #include "src/core/SkReader32.h"
14 #include "src/core/SkTraceEvent.h"
15 #include "src/core/SkWriter32.h"
16 #include "src/gpu/GrAutoLocaleSetter.h"
17 #include "src/gpu/GrContextPriv.h"
18 #include "src/gpu/GrCoordTransform.h"
19 #include "src/gpu/GrPersistentCacheUtils.h"
20 #include "src/gpu/GrProgramDesc.h"
21 #include "src/gpu/GrShaderCaps.h"
22 #include "src/gpu/GrShaderUtils.h"
23 #include "src/gpu/GrSwizzle.h"
24 #include "src/gpu/gl/GrGLGpu.h"
25 #include "src/gpu/gl/GrGLProgram.h"
26 #include "src/gpu/gl/builders/GrGLProgramBuilder.h"
27 #include "src/gpu/gl/builders/GrGLShaderStringBuilder.h"
28 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
29 #include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
30 #include "src/gpu/glsl/GrGLSLProgramDataManager.h"
31 #include "src/gpu/glsl/GrGLSLXferProcessor.h"
32 
33 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
34 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
35 
cleanup_shaders(GrGLGpu * gpu,const SkTDArray<GrGLuint> & shaderIDs)36 static void cleanup_shaders(GrGLGpu* gpu, const SkTDArray<GrGLuint>& shaderIDs) {
37     for (int i = 0; i < shaderIDs.count(); ++i) {
38         GR_GL_CALL(gpu->glInterface(), DeleteShader(shaderIDs[i]));
39     }
40 }
41 
cleanup_program(GrGLGpu * gpu,GrGLuint programID,const SkTDArray<GrGLuint> & shaderIDs)42 static void cleanup_program(GrGLGpu* gpu, GrGLuint programID,
43                             const SkTDArray<GrGLuint>& shaderIDs) {
44     GR_GL_CALL(gpu->glInterface(), DeleteProgram(programID));
45     cleanup_shaders(gpu, shaderIDs);
46 }
47 
CreateProgram(GrGLGpu * gpu,GrRenderTarget * renderTarget,const GrProgramDesc & desc,const GrProgramInfo & programInfo,const GrGLPrecompiledProgram * precompiledProgram)48 sk_sp<GrGLProgram> GrGLProgramBuilder::CreateProgram(
49                                                GrGLGpu* gpu,
50                                                GrRenderTarget* renderTarget,
51                                                const GrProgramDesc& desc,
52                                                const GrProgramInfo& programInfo,
53                                                const GrGLPrecompiledProgram* precompiledProgram) {
54     ATRACE_ANDROID_FRAMEWORK_ALWAYS("shader_compile");
55     GrAutoLocaleSetter als("C");
56 
57     // create a builder.  This will be handed off to effects so they can use it to add
58     // uniforms, varyings, textures, etc
59     GrGLProgramBuilder builder(gpu, renderTarget, desc, programInfo);
60 
61     auto persistentCache = gpu->getContext()->priv().getPersistentCache();
62     if (persistentCache && !precompiledProgram) {
63         sk_sp<SkData> key = SkData::MakeWithoutCopy(desc.asKey(), desc.keyLength());
64         builder.fCached = persistentCache->load(*key);
65         // the eventual end goal is to completely skip emitAndInstallProcs on a cache hit, but it's
66         // doing necessary setup in addition to generating the SkSL code. Currently we are only able
67         // to skip the SkSL->GLSL step on a cache hit.
68     }
69     if (!builder.emitAndInstallProcs()) {
70         return nullptr;
71     }
72     return builder.finalize(precompiledProgram);
73 }
74 
75 /////////////////////////////////////////////////////////////////////////////
76 
GrGLProgramBuilder(GrGLGpu * gpu,GrRenderTarget * renderTarget,const GrProgramDesc & desc,const GrProgramInfo & programInfo)77 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
78                                        GrRenderTarget* renderTarget,
79                                        const GrProgramDesc& desc,
80                                        const GrProgramInfo& programInfo)
81         : INHERITED(renderTarget, desc, programInfo)
82         , fGpu(gpu)
83         , fVaryingHandler(this)
84         , fUniformHandler(this)
85         , fVertexAttributeCnt(0)
86         , fInstanceAttributeCnt(0)
87         , fVertexStride(0)
88         , fInstanceStride(0) {}
89 
caps() const90 const GrCaps* GrGLProgramBuilder::caps() const {
91     return fGpu->caps();
92 }
93 
compileAndAttachShaders(const SkSL::String & glsl,GrGLuint programId,GrGLenum type,SkTDArray<GrGLuint> * shaderIds,GrContextOptions::ShaderErrorHandler * errHandler)94 bool GrGLProgramBuilder::compileAndAttachShaders(const SkSL::String& glsl,
95                                                  GrGLuint programId,
96                                                  GrGLenum type,
97                                                  SkTDArray<GrGLuint>* shaderIds,
98                                                  GrContextOptions::ShaderErrorHandler* errHandler) {
99     GrGLGpu* gpu = this->gpu();
100     GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
101                                                    programId,
102                                                    type,
103                                                    glsl,
104                                                    gpu->stats(),
105                                                    errHandler);
106     if (!shaderId) {
107         return false;
108     }
109 
110     *shaderIds->append() = shaderId;
111     return true;
112 }
113 
computeCountsAndStrides(GrGLuint programID,const GrPrimitiveProcessor & primProc,bool bindAttribLocations)114 void GrGLProgramBuilder::computeCountsAndStrides(GrGLuint programID,
115                                                  const GrPrimitiveProcessor& primProc,
116                                                  bool bindAttribLocations) {
117     fVertexAttributeCnt = primProc.numVertexAttributes();
118     fInstanceAttributeCnt = primProc.numInstanceAttributes();
119     fAttributes.reset(
120             new GrGLProgram::Attribute[fVertexAttributeCnt + fInstanceAttributeCnt]);
121     auto addAttr = [&](int i, const auto& a, size_t* stride) {
122         fAttributes[i].fCPUType = a.cpuType();
123         fAttributes[i].fGPUType = a.gpuType();
124         fAttributes[i].fOffset = *stride;
125         *stride += a.sizeAlign4();
126         fAttributes[i].fLocation = i;
127         if (bindAttribLocations) {
128             GL_CALL(BindAttribLocation(programID, i, a.name()));
129         }
130     };
131     fVertexStride = 0;
132     int i = 0;
133     for (const auto& attr : primProc.vertexAttributes()) {
134         addAttr(i++, attr, &fVertexStride);
135     }
136     SkASSERT(fVertexStride == primProc.vertexStride());
137     fInstanceStride = 0;
138     for (const auto& attr : primProc.instanceAttributes()) {
139         addAttr(i++, attr, &fInstanceStride);
140     }
141     SkASSERT(fInstanceStride == primProc.instanceStride());
142 }
143 
addInputVars(const SkSL::Program::Inputs & inputs)144 void GrGLProgramBuilder::addInputVars(const SkSL::Program::Inputs& inputs) {
145     if (inputs.fRTWidth) {
146         this->addRTWidthUniform(SKSL_RTWIDTH_NAME);
147     }
148     if (inputs.fRTHeight) {
149         this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
150     }
151 }
152 
153 static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
154 static constexpr SkFourByteTag kGLSL_Tag = SkSetFourByteTag('G', 'L', 'S', 'L');
155 static constexpr SkFourByteTag kGLPB_Tag = SkSetFourByteTag('G', 'L', 'P', 'B');
156 
storeShaderInCache(const SkSL::Program::Inputs & inputs,GrGLuint programID,const SkSL::String shaders[],bool isSkSL,SkSL::Program::Settings * settings)157 void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Inputs& inputs, GrGLuint programID,
158                                             const SkSL::String shaders[], bool isSkSL,
159                                             SkSL::Program::Settings* settings) {
160     if (!this->gpu()->getContext()->priv().getPersistentCache()) {
161         return;
162     }
163     sk_sp<SkData> key = SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().keyLength());
164     if (fGpu->glCaps().programBinarySupport()) {
165         // binary cache
166         GrGLsizei length = 0;
167         GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
168         if (length > 0) {
169             SkWriter32 writer;
170             writer.write32(kGLPB_Tag);
171 
172             writer.writePad(&inputs, sizeof(inputs));
173             writer.write32(length);
174 
175             void* binary = writer.reservePad(length);
176             GrGLenum binaryFormat;
177             GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary));
178             writer.write32(binaryFormat);
179 
180             auto data = writer.snapshotAsData();
181             this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
182         }
183     } else {
184         // source cache, plus metadata to allow for a complete precompile
185         GrPersistentCacheUtils::ShaderMetadata meta;
186         meta.fSettings = settings;
187         meta.fHasCustomColorOutput = fFS.hasCustomColorOutput();
188         meta.fHasSecondaryColorOutput = fFS.hasSecondaryOutput();
189         for (const auto& attr : this->primitiveProcessor().vertexAttributes()) {
190             meta.fAttributeNames.emplace_back(attr.name());
191         }
192         for (const auto& attr : this->primitiveProcessor().instanceAttributes()) {
193             meta.fAttributeNames.emplace_back(attr.name());
194         }
195 
196         auto data = GrPersistentCacheUtils::PackCachedShaders(isSkSL ? kSKSL_Tag : kGLSL_Tag,
197                                                               shaders, &inputs, 1, &meta);
198         this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
199     }
200 }
201 
finalize(const GrGLPrecompiledProgram * precompiledProgram)202 sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* precompiledProgram) {
203     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
204 
205     // verify we can get a program id
206     GrGLuint programID;
207     if (precompiledProgram) {
208         programID = precompiledProgram->fProgramID;
209     } else {
210         GL_CALL_RET(programID, CreateProgram());
211     }
212     if (0 == programID) {
213         return nullptr;
214     }
215 
216     if (this->gpu()->glCaps().programBinarySupport() &&
217         this->gpu()->glCaps().programParameterSupport() &&
218         this->gpu()->getContext()->priv().getPersistentCache() &&
219         !precompiledProgram) {
220         GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
221     }
222 
223     this->finalizeShaders();
224 
225     // compile shaders and bind attributes / uniforms
226     auto errorHandler = this->gpu()->getContext()->priv().getShaderErrorHandler();
227     const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
228     SkSL::Program::Settings settings;
229     settings.fCaps = this->gpu()->glCaps().shaderCaps();
230     settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
231     settings.fSharpenTextures =
232                     this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
233     settings.fFragColorIsInOut = this->fragColorIsInOut();
234 
235     SkSL::Program::Inputs inputs;
236     SkTDArray<GrGLuint> shadersToDelete;
237     // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
238     bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
239 #ifdef SK_DEBUG
240     checkLinked = true;
241 #endif
242     bool cached = fCached.get() != nullptr;
243     bool usedProgramBinaries = false;
244     SkSL::String glsl[kGrShaderTypeCount];
245     SkSL::String* sksl[kGrShaderTypeCount] = {
246         &fVS.fCompilerString,
247         &fGS.fCompilerString,
248         &fFS.fCompilerString,
249     };
250     SkSL::String cached_sksl[kGrShaderTypeCount];
251     if (precompiledProgram) {
252         // This is very similar to when we get program binaries. We even set that flag, as it's
253         // used to prevent other compile work later, and to force re-querying uniform locations.
254         this->addInputVars(precompiledProgram->fInputs);
255         this->computeCountsAndStrides(programID, primProc, false);
256         usedProgramBinaries = true;
257     } else if (cached) {
258         ATRACE_ANDROID_FRAMEWORK_ALWAYS("cache_hit");
259         SkReader32 reader(fCached->data(), fCached->size());
260         SkFourByteTag shaderType = reader.readU32();
261 
262         switch (shaderType) {
263             case kGLPB_Tag: {
264                 // Program binary cache hit. We may opt not to use this if we don't trust program
265                 // binaries on this driver
266                 if (!fGpu->glCaps().programBinarySupport()) {
267                     cached = false;
268                     break;
269                 }
270                 reader.read(&inputs, sizeof(inputs));
271                 GrGLsizei length = reader.readInt();
272                 const void* binary = reader.skip(length);
273                 GrGLenum binaryFormat = reader.readU32();
274                 GrGLClearErr(this->gpu()->glInterface());
275                 GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
276                                       ProgramBinary(programID, binaryFormat,
277                                                     const_cast<void*>(binary), length));
278                 if (GR_GL_GET_ERROR(this->gpu()->glInterface()) == GR_GL_NO_ERROR) {
279                     if (checkLinked) {
280                         cached = this->checkLinkStatus(programID, errorHandler, nullptr, nullptr);
281                     }
282                     if (cached) {
283                         this->addInputVars(inputs);
284                         this->computeCountsAndStrides(programID, primProc, false);
285                     }
286                 } else {
287                     cached = false;
288                 }
289                 usedProgramBinaries = cached;
290                 break;
291             }
292 
293             case kGLSL_Tag:
294                 // Source cache hit, we don't need to compile the SkSL->GLSL
295                 GrPersistentCacheUtils::UnpackCachedShaders(&reader, glsl, &inputs, 1);
296                 break;
297 
298             case kSKSL_Tag:
299                 // SkSL cache hit, this should only happen in tools overriding the generated SkSL
300                 GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, &inputs, 1);
301                 for (int i = 0; i < kGrShaderTypeCount; ++i) {
302                     sksl[i] = &cached_sksl[i];
303                 }
304                 break;
305         }
306     }
307     if (!usedProgramBinaries) {
308         ATRACE_ANDROID_FRAMEWORK_ALWAYS("cache_miss");
309         // Either a cache miss, or we got something other than binaries from the cache
310 
311         /*
312            Fragment Shader
313         */
314         if (glsl[kFragment_GrShaderType].empty()) {
315             // Don't have cached GLSL, need to compile SkSL->GLSL
316             if (fFS.fForceHighPrecision) {
317                 settings.fForceHighPrecision = true;
318             }
319             std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(gpu()->glContext(),
320                                                              SkSL::Program::kFragment_Kind,
321                                                              *sksl[kFragment_GrShaderType],
322                                                              settings,
323                                                              &glsl[kFragment_GrShaderType],
324                                                              errorHandler);
325             if (!fs) {
326                 cleanup_program(fGpu, programID, shadersToDelete);
327                 return nullptr;
328             }
329             inputs = fs->fInputs;
330         }
331 
332         this->addInputVars(inputs);
333         if (!this->compileAndAttachShaders(glsl[kFragment_GrShaderType], programID,
334                                            GR_GL_FRAGMENT_SHADER, &shadersToDelete, errorHandler)) {
335             cleanup_program(fGpu, programID, shadersToDelete);
336             return nullptr;
337         }
338 
339         /*
340            Vertex Shader
341         */
342         if (glsl[kVertex_GrShaderType].empty()) {
343             // Don't have cached GLSL, need to compile SkSL->GLSL
344             std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(gpu()->glContext(),
345                                                              SkSL::Program::kVertex_Kind,
346                                                              *sksl[kVertex_GrShaderType],
347                                                              settings,
348                                                              &glsl[kVertex_GrShaderType],
349                                                              errorHandler);
350             if (!vs) {
351                 cleanup_program(fGpu, programID, shadersToDelete);
352                 return nullptr;
353             }
354         }
355         if (!this->compileAndAttachShaders(glsl[kVertex_GrShaderType], programID,
356                                            GR_GL_VERTEX_SHADER, &shadersToDelete, errorHandler)) {
357             cleanup_program(fGpu, programID, shadersToDelete);
358             return nullptr;
359         }
360 
361         // This also binds vertex attribute locations. NVPR doesn't really use vertices,
362         // even though it requires a vertex shader in the program.
363         if (!primProc.isPathRendering()) {
364             this->computeCountsAndStrides(programID, primProc, true);
365         }
366 
367         /*
368            Tessellation Shaders
369         */
370         if (fProgramInfo.primProc().willUseTessellationShaders()) {
371             // Tessellation shaders are not currently supported by SkSL. So here, we temporarily
372             // generate GLSL strings directly using back door methods on GrPrimitiveProcessor, and
373             // pass those raw strings on to the driver.
374             SkString versionAndExtensionDecls;
375             versionAndExtensionDecls.appendf("%s\n", this->shaderCaps()->versionDeclString());
376             if (const char* extensionString = this->shaderCaps()->tessellationExtensionString()) {
377                 versionAndExtensionDecls.appendf("#extension %s : require\n", extensionString);
378             }
379 
380             SkString tessControlShader = primProc.getTessControlShaderGLSL(
381                     versionAndExtensionDecls.c_str(), *this->shaderCaps());
382             if (!this->compileAndAttachShaders(tessControlShader.c_str(), programID,
383                                                GR_GL_TESS_CONTROL_SHADER, &shadersToDelete,
384                                                errorHandler)) {
385                 cleanup_program(fGpu, programID, shadersToDelete);
386                 return nullptr;
387             }
388 
389             SkString tessEvaluationShader = primProc.getTessEvaluationShaderGLSL(
390                     versionAndExtensionDecls.c_str(), *this->shaderCaps());
391             if (!this->compileAndAttachShaders(tessEvaluationShader.c_str(), programID,
392                                                GR_GL_TESS_EVALUATION_SHADER, &shadersToDelete,
393                                                errorHandler)) {
394                 cleanup_program(fGpu, programID, shadersToDelete);
395                 return nullptr;
396             }
397         }
398 
399         /*
400            Geometry Shader
401         */
402         if (primProc.willUseGeoShader()) {
403             if (glsl[kGeometry_GrShaderType].empty()) {
404                 // Don't have cached GLSL, need to compile SkSL->GLSL
405                 std::unique_ptr<SkSL::Program> gs;
406                 gs = GrSkSLtoGLSL(gpu()->glContext(),
407                                   SkSL::Program::kGeometry_Kind,
408                                   *sksl[kGeometry_GrShaderType],
409                                   settings,
410                                   &glsl[kGeometry_GrShaderType],
411                                   errorHandler);
412                 if (!gs) {
413                     cleanup_program(fGpu, programID, shadersToDelete);
414                     return nullptr;
415                 }
416             }
417             if (!this->compileAndAttachShaders(glsl[kGeometry_GrShaderType], programID,
418                                                GR_GL_GEOMETRY_SHADER, &shadersToDelete,
419                                                errorHandler)) {
420                 cleanup_program(fGpu, programID, shadersToDelete);
421                 return nullptr;
422             }
423         }
424         this->bindProgramResourceLocations(programID);
425 
426         GL_CALL(LinkProgram(programID));
427         if (checkLinked) {
428             if (!this->checkLinkStatus(programID, errorHandler, sksl, glsl)) {
429                 cleanup_program(fGpu, programID, shadersToDelete);
430                 return nullptr;
431             }
432         }
433     }
434     this->resolveProgramResourceLocations(programID, usedProgramBinaries);
435 
436     cleanup_shaders(fGpu, shadersToDelete);
437 
438     // With ANGLE, we can't cache path-rendering programs. We use ProgramPathFragmentInputGen,
439     // and ANGLE's deserialized program state doesn't restore enough state to handle that.
440     // The native NVIDIA drivers do, but this is such an edge case that it's easier to just
441     // black-list caching these programs in all cases. See: anglebug.com/3619
442     //
443     // We temporarily can't cache tessellation shaders while using back door GLSL.
444     //
445     // We also can't cache SkSL or GLSL if we were given a precompiled program, but there's not
446     // much point in doing so.
447     if (!cached && !primProc.isPathRendering() && !primProc.willUseTessellationShaders() &&
448         !precompiledProgram) {
449         // FIXME: Remove the check for tessellation shaders in the above 'if' once the back door
450         // GLSL mechanism is removed.
451         (void)&GrPrimitiveProcessor::getTessControlShaderGLSL;
452         bool isSkSL = false;
453         if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
454                 GrContextOptions::ShaderCacheStrategy::kSkSL) {
455             for (int i = 0; i < kGrShaderTypeCount; ++i) {
456                 glsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
457             }
458             isSkSL = true;
459         }
460         this->storeShaderInCache(inputs, programID, glsl, isSkSL, &settings);
461     }
462     return this->createProgram(programID);
463 }
464 
bindProgramResourceLocations(GrGLuint programID)465 void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
466     fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
467 
468     const GrGLCaps& caps = this->gpu()->glCaps();
469     if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
470         GL_CALL(BindFragDataLocation(programID, 0,
471                                      GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
472     }
473     if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
474         GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
475                                   GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
476     }
477 
478     // handle NVPR separable varyings
479     if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
480         !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
481         return;
482     }
483     int count = fVaryingHandler.fPathProcVaryingInfos.count();
484     for (int i = 0; i < count; ++i) {
485         GL_CALL(BindFragmentInputLocation(programID, i,
486                                        fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
487         fVaryingHandler.fPathProcVaryingInfos[i].fLocation = i;
488     }
489 }
490 
checkLinkStatus(GrGLuint programID,GrContextOptions::ShaderErrorHandler * errorHandler,SkSL::String * sksl[],const SkSL::String glsl[])491 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID,
492                                          GrContextOptions::ShaderErrorHandler* errorHandler,
493                                          SkSL::String* sksl[], const SkSL::String glsl[]) {
494     GrGLint linked = GR_GL_INIT_ZERO;
495     GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
496     if (!linked) {
497         SkSL::String allShaders;
498         if (sksl) {
499             allShaders.appendf("// Vertex SKSL\n%s\n", sksl[kVertex_GrShaderType]->c_str());
500             if (!sksl[kGeometry_GrShaderType]->empty()) {
501                 allShaders.appendf("// Geometry SKSL\n%s\n", sksl[kGeometry_GrShaderType]->c_str());
502             }
503             allShaders.appendf("// Fragment SKSL\n%s\n", sksl[kFragment_GrShaderType]->c_str());
504         }
505         if (glsl) {
506             allShaders.appendf("// Vertex GLSL\n%s\n", glsl[kVertex_GrShaderType].c_str());
507             if (!glsl[kGeometry_GrShaderType].empty()) {
508                 allShaders.appendf("// Geometry GLSL\n%s\n", glsl[kGeometry_GrShaderType].c_str());
509             }
510             allShaders.appendf("// Fragment GLSL\n%s\n", glsl[kFragment_GrShaderType].c_str());
511         }
512         GrGLint infoLen = GR_GL_INIT_ZERO;
513         GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
514         SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
515         if (infoLen > 0) {
516             // retrieve length even though we don't need it to workaround
517             // bug in chrome cmd buffer param validation.
518             GrGLsizei length = GR_GL_INIT_ZERO;
519             GL_CALL(GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get()));
520         }
521         errorHandler->compileError(allShaders.c_str(), infoLen > 0 ? (const char*)log.get() : "");
522     }
523     return SkToBool(linked);
524 }
525 
resolveProgramResourceLocations(GrGLuint programID,bool force)526 void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID, bool force) {
527     fUniformHandler.getUniformLocations(programID, fGpu->glCaps(), force);
528 
529     // handle NVPR separable varyings
530     if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
531         fGpu->glPathRendering()->shouldBindFragmentInputs()) {
532         return;
533     }
534     int count = fVaryingHandler.fPathProcVaryingInfos.count();
535     for (int i = 0; i < count; ++i) {
536         GrGLint location;
537         GL_CALL_RET(location, GetProgramResourceLocation(
538                                        programID,
539                                        GR_GL_FRAGMENT_INPUT,
540                                        fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
541         fVaryingHandler.fPathProcVaryingInfos[i].fLocation = location;
542     }
543 }
544 
createProgram(GrGLuint programID)545 sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID) {
546     return sk_sp<GrGLProgram>(new GrGLProgram(fGpu,
547                                               fUniformHandles,
548                                               programID,
549                                               fUniformHandler.fUniforms,
550                                               fUniformHandler.fSamplers,
551                                               fVaryingHandler.fPathProcVaryingInfos,
552                                               std::move(fGeometryProcessor),
553                                               std::move(fXferProcessor),
554                                               std::move(fFragmentProcessors),
555                                               fFragmentProcessorCnt,
556                                               std::move(fAttributes),
557                                               fVertexAttributeCnt,
558                                               fInstanceAttributeCnt,
559                                               fVertexStride,
560                                               fInstanceStride));
561 }
562 
PrecompileProgram(GrGLPrecompiledProgram * precompiledProgram,GrGLGpu * gpu,const SkData & cachedData)563 bool GrGLProgramBuilder::PrecompileProgram(GrGLPrecompiledProgram* precompiledProgram,
564                                            GrGLGpu* gpu,
565                                            const SkData& cachedData) {
566     SkReader32 reader(cachedData.data(), cachedData.size());
567     SkFourByteTag shaderType = reader.readU32();
568     if (shaderType != kSKSL_Tag) {
569         // TODO: Support GLSL, and maybe even program binaries, too?
570         return false;
571     }
572 
573     const GrGLInterface* gl = gpu->glInterface();
574     auto errorHandler = gpu->getContext()->priv().getShaderErrorHandler();
575     GrGLuint programID;
576     GR_GL_CALL_RET(gl, programID, CreateProgram());
577     if (0 == programID) {
578         return false;
579     }
580 
581     SkTDArray<GrGLuint> shadersToDelete;
582 
583     SkSL::Program::Settings settings;
584     const GrGLCaps& caps = gpu->glCaps();
585     settings.fCaps = caps.shaderCaps();
586     settings.fSharpenTextures = gpu->getContext()->priv().options().fSharpenMipmappedTextures;
587     GrPersistentCacheUtils::ShaderMetadata meta;
588     meta.fSettings = &settings;
589 
590     SkSL::String shaders[kGrShaderTypeCount];
591     SkSL::Program::Inputs inputs;
592     GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &inputs, 1, &meta);
593 
594     auto compileShader = [&](SkSL::Program::Kind kind, const SkSL::String& sksl, GrGLenum type) {
595         SkSL::String glsl;
596         auto program = GrSkSLtoGLSL(gpu->glContext(), kind, sksl, settings, &glsl, errorHandler);
597         if (!program) {
598             return false;
599         }
600 
601         if (GrGLuint shaderID = GrGLCompileAndAttachShader(gpu->glContext(), programID, type, glsl,
602                                                            gpu->stats(), errorHandler)) {
603             shadersToDelete.push_back(shaderID);
604             return true;
605         } else {
606             return false;
607         }
608     };
609 
610     if (!compileShader(SkSL::Program::kFragment_Kind,
611                        shaders[kFragment_GrShaderType],
612                        GR_GL_FRAGMENT_SHADER) ||
613         !compileShader(SkSL::Program::kVertex_Kind,
614                        shaders[kVertex_GrShaderType],
615                        GR_GL_VERTEX_SHADER) ||
616         (!shaders[kGeometry_GrShaderType].empty() &&
617          !compileShader(SkSL::Program::kGeometry_Kind,
618                        shaders[kGeometry_GrShaderType],
619                        GR_GL_GEOMETRY_SHADER))) {
620         cleanup_program(gpu, programID, shadersToDelete);
621         return false;
622     }
623 
624     for (int i = 0; i < meta.fAttributeNames.count(); ++i) {
625         GR_GL_CALL(gpu->glInterface(), BindAttribLocation(programID, i,
626                                                           meta.fAttributeNames[i].c_str()));
627     }
628 
629     if (meta.fHasCustomColorOutput && caps.bindFragDataLocationSupport()) {
630         GR_GL_CALL(gpu->glInterface(), BindFragDataLocation(programID, 0,
631                 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
632     }
633     if (meta.fHasSecondaryColorOutput && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
634         GR_GL_CALL(gpu->glInterface(), BindFragDataLocationIndexed(programID, 0, 1,
635                 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
636     }
637 
638     GR_GL_CALL(gpu->glInterface(), LinkProgram(programID));
639     GrGLint linked = GR_GL_INIT_ZERO;
640     GR_GL_CALL(gpu->glInterface(), GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
641     if (!linked) {
642         cleanup_program(gpu, programID, shadersToDelete);
643         return false;
644     }
645 
646     cleanup_shaders(gpu, shadersToDelete);
647 
648     precompiledProgram->fProgramID = programID;
649     precompiledProgram->fInputs = inputs;
650     return true;
651 }
652