• 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/ganesh/gl/builders/GrGLProgramBuilder.h"
9 
10 #include "include/gpu/GrDirectContext.h"
11 #include "src/base/SkAutoMalloc.h"
12 #include "src/core/SkReadBuffer.h"
13 #include "src/core/SkTraceEvent.h"
14 #include "src/core/SkWriteBuffer.h"
15 #include "src/gpu/PipelineUtils.h"
16 #include "src/gpu/Swizzle.h"
17 #include "src/gpu/ganesh/GrAutoLocaleSetter.h"
18 #include "src/gpu/ganesh/GrDirectContextPriv.h"
19 #include "src/gpu/ganesh/GrFragmentProcessor.h"
20 #include "src/gpu/ganesh/GrGeometryProcessor.h"
21 #include "src/gpu/ganesh/GrPersistentCacheUtils.h"
22 #include "src/gpu/ganesh/GrProgramDesc.h"
23 #include "src/gpu/ganesh/GrShaderCaps.h"
24 #include "src/gpu/ganesh/GrXferProcessor.h"
25 #include "src/gpu/ganesh/gl/GrGLGpu.h"
26 #include "src/gpu/ganesh/gl/GrGLProgram.h"
27 #include "src/gpu/ganesh/gl/builders/GrGLProgramBuilder.h"
28 #include "src/sksl/SkSLProgramKind.h"
29 #include "src/sksl/SkSLProgramSettings.h"
30 #include "src/utils/SkShaderUtils.h"
31 
32 #include <memory>
33 #include "src/gpu/ganesh/gl/builders/GrGLShaderStringBuilder.h"
34 #include "src/gpu/ganesh/glsl/GrGLSLProgramDataManager.h"
35 
36 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
37 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
38 
cleanup_shaders(GrGLGpu * gpu,const SkTDArray<GrGLuint> & shaderIDs)39 static void cleanup_shaders(GrGLGpu* gpu, const SkTDArray<GrGLuint>& shaderIDs) {
40     for (int i = 0; i < shaderIDs.size(); ++i) {
41         GR_GL_CALL(gpu->glInterface(), DeleteShader(shaderIDs[i]));
42     }
43 }
44 
cleanup_program(GrGLGpu * gpu,GrGLuint programID,const SkTDArray<GrGLuint> & shaderIDs)45 static void cleanup_program(GrGLGpu* gpu, GrGLuint programID,
46                             const SkTDArray<GrGLuint>& shaderIDs) {
47     GR_GL_CALL(gpu->glInterface(), DeleteProgram(programID));
48     cleanup_shaders(gpu, shaderIDs);
49 }
50 
CreateProgram(GrDirectContext * dContext,const GrProgramDesc & desc,const GrProgramInfo & programInfo,const GrGLPrecompiledProgram * precompiledProgram)51 sk_sp<GrGLProgram> GrGLProgramBuilder::CreateProgram(
52                                                GrDirectContext* dContext,
53                                                const GrProgramDesc& desc,
54                                                const GrProgramInfo& programInfo,
55                                                const GrGLPrecompiledProgram* precompiledProgram) {
56     TRACE_EVENT0_ALWAYS("skia.shaders", "shader_compile");
57     GrAutoLocaleSetter als("C");
58 
59     GrGLGpu* glGpu = static_cast<GrGLGpu*>(dContext->priv().getGpu());
60 
61     // create a builder.  This will be handed off to effects so they can use it to add
62     // uniforms, varyings, textures, etc
63     GrGLProgramBuilder builder(glGpu, desc, programInfo);
64 
65     auto persistentCache = dContext->priv().getPersistentCache();
66     if (persistentCache && !precompiledProgram) {
67         sk_sp<SkData> key = SkData::MakeWithoutCopy(desc.asKey(), desc.keyLength());
68         builder.fCached = persistentCache->load(*key);
69         // the eventual end goal is to completely skip emitAndInstallProcs on a cache hit, but it's
70         // doing necessary setup in addition to generating the SkSL code. Currently we are only able
71         // to skip the SkSL->GLSL step on a cache hit.
72     }
73     if (!builder.emitAndInstallProcs()) {
74         return nullptr;
75     }
76     return builder.finalize(precompiledProgram);
77 }
78 
79 /////////////////////////////////////////////////////////////////////////////
80 
GrGLProgramBuilder(GrGLGpu * gpu,const GrProgramDesc & desc,const GrProgramInfo & programInfo)81 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
82                                        const GrProgramDesc& desc,
83                                        const GrProgramInfo& programInfo)
84         : INHERITED(desc, programInfo)
85         , fGpu(gpu)
86         , fVaryingHandler(this)
87         , fUniformHandler(this)
88         , fVertexAttributeCnt(0)
89         , fInstanceAttributeCnt(0)
90         , fVertexStride(0)
91         , fInstanceStride(0) {}
92 
caps() const93 const GrCaps* GrGLProgramBuilder::caps() const {
94     return fGpu->caps();
95 }
96 
compileAndAttachShaders(const std::string & glsl,GrGLuint programId,GrGLenum type,SkTDArray<GrGLuint> * shaderIds,bool shaderWasCached,GrContextOptions::ShaderErrorHandler * errHandler)97 bool GrGLProgramBuilder::compileAndAttachShaders(const std::string& glsl,
98                                                  GrGLuint programId,
99                                                  GrGLenum type,
100                                                  SkTDArray<GrGLuint>* shaderIds,
101                                                  bool shaderWasCached,
102                                                  GrContextOptions::ShaderErrorHandler* errHandler) {
103     GrGLGpu* gpu = this->gpu();
104     GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
105                                                    programId,
106                                                    type,
107                                                    glsl,
108                                                    shaderWasCached,
109                                                    gpu->pipelineBuilder()->stats(),
110                                                    errHandler);
111     if (!shaderId) {
112         return false;
113     }
114 
115     *shaderIds->append() = shaderId;
116     return true;
117 }
118 
computeCountsAndStrides(GrGLuint programID,const GrGeometryProcessor & geomProc,bool bindAttribLocations)119 void GrGLProgramBuilder::computeCountsAndStrides(GrGLuint programID,
120                                                  const GrGeometryProcessor& geomProc,
121                                                  bool bindAttribLocations) {
122     fVertexAttributeCnt = geomProc.numVertexAttributes();
123     fInstanceAttributeCnt = geomProc.numInstanceAttributes();
124     fAttributes = std::make_unique<GrGLProgram::Attribute[]>(
125             fVertexAttributeCnt + fInstanceAttributeCnt);
126     auto addAttr = [&](int i, const auto& a) {
127         fAttributes[i].fCPUType = a.cpuType();
128         fAttributes[i].fGPUType = a.gpuType();
129         fAttributes[i].fOffset = *a.offset();
130         fAttributes[i].fLocation = i;
131         if (bindAttribLocations) {
132             GL_CALL(BindAttribLocation(programID, i, a.name()));
133         }
134     };
135     fVertexStride = geomProc.vertexStride();
136     int i = 0;
137     for (auto attr : geomProc.vertexAttributes()) {
138         addAttr(i++, attr);
139     }
140     fInstanceStride = geomProc.instanceStride();
141     for (auto attr : geomProc.instanceAttributes()) {
142         addAttr(i++, attr);
143     }
144     SkASSERT(fInstanceStride == geomProc.instanceStride());
145 }
146 
addInputVars(const SkSL::Program::Interface & interface)147 void GrGLProgramBuilder::addInputVars(const SkSL::Program::Interface& interface) {
148     uint8_t useRTFlip = interface.fRTFlipUniform;
149     if (!this->gpu()->glCaps().shaderCaps()->fCanUseFragCoord) {
150         useRTFlip &= ~SkSL::Program::Interface::kRTFlip_FragCoord;
151     }
152 
153     if (useRTFlip != SkSL::Program::Interface::kRTFlip_None) {
154         this->addRTFlipUniform(SKSL_RTFLIP_NAME);
155     }
156 }
157 
158 static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
159 static constexpr SkFourByteTag kGLSL_Tag = SkSetFourByteTag('G', 'L', 'S', 'L');
160 static constexpr SkFourByteTag kGLPB_Tag = SkSetFourByteTag('G', 'L', 'P', 'B');
161 
storeShaderInCache(const SkSL::Program::Interface & interface,GrGLuint programID,const std::string shaders[],bool isSkSL,SkSL::ProgramSettings * settings)162 void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Interface& interface,
163                                             GrGLuint programID,
164                                             const std::string shaders[],
165                                             bool isSkSL,
166                                             SkSL::ProgramSettings* settings) {
167     if (!this->gpu()->getContext()->priv().getPersistentCache()) {
168         return;
169     }
170     sk_sp<SkData> key = SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().keyLength());
171     SkString description = GrProgramDesc::Describe(fProgramInfo, *fGpu->caps());
172     if (fGpu->glCaps().programBinarySupport()) {
173         // binary cache
174         GrGLsizei length = 0;
175         GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
176         if (length > 0) {
177             SkBinaryWriteBuffer writer({});
178             writer.writeInt(GrPersistentCacheUtils::GetCurrentVersion());
179             writer.writeUInt(kGLPB_Tag);
180 
181             writer.writePad32(&interface, sizeof(interface));
182 
183             SkAutoSMalloc<2048> binary(length);
184             GrGLenum binaryFormat;
185             GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get()));
186 
187             writer.writeUInt(binaryFormat);
188             writer.writeInt(length);
189             writer.writePad32(binary.get(), length);
190 
191             auto data = writer.snapshotAsData();
192             this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data, description);
193         }
194     } else {
195         // source cache, plus metadata to allow for a complete precompile
196         GrPersistentCacheUtils::ShaderMetadata meta;
197         meta.fSettings = settings;
198         meta.fHasSecondaryColorOutput = fFS.hasSecondaryOutput();
199         for (auto attr : this->geometryProcessor().vertexAttributes()) {
200             meta.fAttributeNames.emplace_back(attr.name());
201         }
202         for (auto attr : this->geometryProcessor().instanceAttributes()) {
203             meta.fAttributeNames.emplace_back(attr.name());
204         }
205 
206         auto data = GrPersistentCacheUtils::PackCachedShaders(isSkSL ? kSKSL_Tag : kGLSL_Tag,
207                                                               shaders, &interface, 1, &meta);
208         this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data, description);
209     }
210 }
211 
finalize(const GrGLPrecompiledProgram * precompiledProgram)212 sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* precompiledProgram) {
213     TRACE_EVENT0("skia.shaders", TRACE_FUNC);
214 
215     // verify we can get a program id
216     GrGLuint programID;
217     if (precompiledProgram) {
218         programID = precompiledProgram->fProgramID;
219     } else {
220         GL_CALL_RET(programID, CreateProgram());
221     }
222     if (0 == programID) {
223         return nullptr;
224     }
225 
226     if (this->gpu()->glCaps().programBinarySupport() &&
227         this->gpu()->glCaps().programParameterSupport() &&
228         this->gpu()->getContext()->priv().getPersistentCache() &&
229         !precompiledProgram) {
230         GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
231     }
232 
233     this->finalizeShaders();
234 
235     // compile shaders and bind attributes / uniforms
236     auto errorHandler = this->gpu()->getContext()->priv().getShaderErrorHandler();
237     const GrGeometryProcessor& geomProc = this->geometryProcessor();
238     SkSL::ProgramSettings settings;
239     settings.fSharpenTextures = true;
240     settings.fFragColorIsInOut = this->fragColorIsInOut();
241 
242     SkSL::Program::Interface interface;
243     SkTDArray<GrGLuint> shadersToDelete;
244 
245     bool cached = fCached.get() != nullptr;
246     bool usedProgramBinaries = false;
247     std::string glsl[kGrShaderTypeCount];
248     const std::string* sksl[kGrShaderTypeCount] = {
249         &fVS.fCompilerString,
250         &fFS.fCompilerString,
251     };
252     std::string cached_sksl[kGrShaderTypeCount];
253     if (precompiledProgram) {
254         // This is very similar to when we get program binaries. We even set that flag, as it's
255         // used to prevent other compile work later, and to force re-querying uniform locations.
256         this->addInputVars(precompiledProgram->fInterface);
257         this->computeCountsAndStrides(programID, geomProc, false);
258         usedProgramBinaries = true;
259     } else if (cached) {
260         TRACE_EVENT0_ALWAYS("skia.shaders", "cache_hit");
261         SkReadBuffer reader(fCached->data(), fCached->size());
262         SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
263 
264         switch (shaderType) {
265             case kGLPB_Tag: {
266                 // Program binary cache hit. We may opt not to use this if we don't trust program
267                 // binaries on this driver
268                 if (!fGpu->glCaps().programBinarySupport()) {
269                     cached = false;
270                     break;
271                 }
272                 reader.readPad32(&interface, sizeof(interface));
273                 GrGLenum binaryFormat = reader.readUInt();
274                 GrGLsizei length      = reader.readInt();
275                 const void* binary = reader.skip(length);
276                 if (!reader.isValid()) {
277                     break;
278                 }
279                 if (length <= 0 || !fGpu->glCaps().programBinaryFormatIsValid(binaryFormat)) {
280                     cached = false;
281                     break;
282                 }
283                 GL_CALL(ProgramBinary(programID, binaryFormat, const_cast<void*>(binary), length));
284                 // Pass nullptr for the error handler. We don't want to treat this as a compile
285                 // failure (we can still recover by compiling the program from source, below).
286                 // Clients won't be directly notified, but they can infer this from the trace
287                 // events, and from the traffic to the persistent cache.
288                 cached = GrGLCheckLinkStatus(fGpu, programID, /*shaderWasCached=*/true,
289                                              /*errorHandler=*/nullptr, nullptr, nullptr);
290                 if (cached) {
291                     this->addInputVars(interface);
292                     this->computeCountsAndStrides(programID, geomProc, false);
293                 }
294                 usedProgramBinaries = cached;
295                 break;
296             }
297 
298             case kGLSL_Tag:
299                 // Source cache hit, we don't need to compile the SkSL->GLSL
300                 GrPersistentCacheUtils::UnpackCachedShaders(&reader, glsl, &interface, 1);
301                 break;
302 
303             case kSKSL_Tag:
304                 // SkSL cache hit, this should only happen in tools overriding the generated SkSL
305                 if (GrPersistentCacheUtils::UnpackCachedShaders(
306                             &reader, cached_sksl, &interface, 1)) {
307                     for (int i = 0; i < kGrShaderTypeCount; ++i) {
308                         sksl[i] = &cached_sksl[i];
309                     }
310                 }
311                 break;
312 
313             default:
314                 // We got something invalid, so pretend it wasn't there
315                 reader.validate(false);
316                 break;
317         }
318         if (!reader.isValid()) {
319             cached = false;
320         }
321     }
322     if (!usedProgramBinaries) {
323         TRACE_EVENT0_ALWAYS("skia.shaders", "cache_miss");
324         // Either a cache miss, or we got something other than binaries from the cache
325 
326         /*
327            Fragment Shader
328         */
329         if (glsl[kFragment_GrShaderType].empty()) {
330             // Don't have cached GLSL, need to compile SkSL->GLSL
331             if (fFS.fForceHighPrecision) {
332                 settings.fForceHighPrecision = true;
333             }
334             if (!skgpu::SkSLToGLSL(this->gpu()->caps()->shaderCaps(),
335                                    *sksl[kFragment_GrShaderType],
336                                    SkSL::ProgramKind::kFragment,
337                                    settings,
338                                    &glsl[kFragment_GrShaderType],
339                                    &interface,
340                                    errorHandler)) {
341                 cleanup_program(fGpu, programID, shadersToDelete);
342                 return nullptr;
343             }
344         }
345 
346         this->addInputVars(interface);
347         if (!this->compileAndAttachShaders(glsl[kFragment_GrShaderType],
348                                            programID,
349                                            GR_GL_FRAGMENT_SHADER,
350                                            &shadersToDelete,
351                                            cached,
352                                            errorHandler)) {
353             cleanup_program(fGpu, programID, shadersToDelete);
354             return nullptr;
355         }
356 
357         /*
358            Vertex Shader
359         */
360         if (glsl[kVertex_GrShaderType].empty()) {
361             // Don't have cached GLSL, need to compile SkSL->GLSL
362             SkSL::Program::Interface unusedInterface;
363             if (!skgpu::SkSLToGLSL(this->gpu()->caps()->shaderCaps(),
364                                    *sksl[kVertex_GrShaderType],
365                                    SkSL::ProgramKind::kVertex,
366                                    settings,
367                                    &glsl[kVertex_GrShaderType],
368                                    &unusedInterface,
369                                    errorHandler)) {
370                 cleanup_program(fGpu, programID, shadersToDelete);
371                 return nullptr;
372             }
373         }
374         if (!this->compileAndAttachShaders(glsl[kVertex_GrShaderType],
375                                            programID,
376                                            GR_GL_VERTEX_SHADER,
377                                            &shadersToDelete,
378                                            cached,
379                                            errorHandler)) {
380             cleanup_program(fGpu, programID, shadersToDelete);
381             return nullptr;
382         }
383 
384         // This also binds vertex attribute locations.
385         this->computeCountsAndStrides(programID, geomProc, true);
386 
387         this->bindProgramResourceLocations(programID);
388 
389         {
390             TRACE_EVENT0_ALWAYS("skia.shaders", "driver_link_program");
391             GL_CALL(LinkProgram(programID));
392             if (!GrGLCheckLinkStatus(fGpu, programID, cached, errorHandler, sksl, glsl)) {
393                 cleanup_program(fGpu, programID, shadersToDelete);
394                 return nullptr;
395             }
396         }
397     }
398     this->resolveProgramResourceLocations(programID, usedProgramBinaries);
399 
400     cleanup_shaders(fGpu, shadersToDelete);
401 
402     // We can't cache SkSL or GLSL if we were given a precompiled program, but there's not
403     // much point in doing so.
404     if (!cached && !precompiledProgram) {
405         bool isSkSL = false;
406         if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
407                 GrContextOptions::ShaderCacheStrategy::kSkSL) {
408             for (int i = 0; i < kGrShaderTypeCount; ++i) {
409                 glsl[i] = SkShaderUtils::PrettyPrint(*sksl[i]);
410             }
411             isSkSL = true;
412         }
413         this->storeShaderInCache(interface, programID, glsl, isSkSL, &settings);
414     }
415     return this->createProgram(programID);
416 }
417 
bindProgramResourceLocations(GrGLuint programID)418 void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
419     fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
420 
421     const GrGLCaps& caps = this->gpu()->glCaps();
422     if (caps.bindFragDataLocationSupport()) {
423         SkASSERT(caps.shaderCaps()->mustDeclareFragmentShaderOutput());
424         GL_CALL(BindFragDataLocation(programID, 0,
425                                      GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
426         if (fFS.hasSecondaryOutput()) {
427             GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
428                                   GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
429         }
430     }
431 }
432 
resolveProgramResourceLocations(GrGLuint programID,bool force)433 void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID, bool force) {
434     fUniformHandler.getUniformLocations(programID, fGpu->glCaps(), force);
435 }
436 
createProgram(GrGLuint programID)437 sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID) {
438     return GrGLProgram::Make(fGpu,
439                              fUniformHandles,
440                              programID,
441                              fUniformHandler.fUniforms,
442                              fUniformHandler.fSamplers,
443                              std::move(fGPImpl),
444                              std::move(fXPImpl),
445                              std::move(fFPImpls),
446                              std::move(fAttributes),
447                              fVertexAttributeCnt,
448                              fInstanceAttributeCnt,
449                              fVertexStride,
450                              fInstanceStride);
451 }
452 
PrecompileProgram(GrDirectContext * dContext,GrGLPrecompiledProgram * precompiledProgram,const SkData & cachedData)453 bool GrGLProgramBuilder::PrecompileProgram(GrDirectContext* dContext,
454                                            GrGLPrecompiledProgram* precompiledProgram,
455                                            const SkData& cachedData) {
456     SkReadBuffer reader(cachedData.data(), cachedData.size());
457     SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
458     if (shaderType != kSKSL_Tag) {
459         // TODO: Support GLSL, and maybe even program binaries, too?
460         return false;
461     }
462 
463     GrGLGpu* glGpu = static_cast<GrGLGpu*>(dContext->priv().getGpu());
464 
465     const GrGLInterface* gl = glGpu->glInterface();
466     auto errorHandler = dContext->priv().getShaderErrorHandler();
467 
468     SkSL::ProgramSettings settings;
469     settings.fSharpenTextures = true;
470     GrPersistentCacheUtils::ShaderMetadata meta;
471     meta.fSettings = &settings;
472 
473     std::string shaders[kGrShaderTypeCount];
474     SkSL::Program::Interface interface;
475     if (!GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &interface, 1, &meta)) {
476         return false;
477     }
478 
479     GrGLuint programID;
480     GR_GL_CALL_RET(gl, programID, CreateProgram());
481     if (0 == programID) {
482         return false;
483     }
484 
485     SkTDArray<GrGLuint> shadersToDelete;
486 
487     auto compileShader = [&](SkSL::ProgramKind kind, const std::string& sksl, GrGLenum type) {
488         std::string glsl;
489         SkSL::Program::Interface unusedInterface;
490         if (!skgpu::SkSLToGLSL(glGpu->caps()->shaderCaps(),
491                                sksl,
492                                kind,
493                                settings,
494                                &glsl,
495                                &unusedInterface,
496                                errorHandler)) {
497             return false;
498         }
499 
500         if (GrGLuint shaderID = GrGLCompileAndAttachShader(glGpu->glContext(),
501                                                            programID,
502                                                            type,
503                                                            glsl,
504                                                            /*shaderWasCached=*/false,
505                                                            glGpu->pipelineBuilder()->stats(),
506                                                            errorHandler)) {
507             shadersToDelete.push_back(shaderID);
508             return true;
509         } else {
510             return false;
511         }
512     };
513 
514     if (!compileShader(SkSL::ProgramKind::kFragment,
515                        shaders[kFragment_GrShaderType],
516                        GR_GL_FRAGMENT_SHADER) ||
517         !compileShader(SkSL::ProgramKind::kVertex,
518                        shaders[kVertex_GrShaderType],
519                        GR_GL_VERTEX_SHADER)) {
520         cleanup_program(glGpu, programID, shadersToDelete);
521         return false;
522     }
523 
524     for (int i = 0; i < meta.fAttributeNames.size(); ++i) {
525         GR_GL_CALL(glGpu->glInterface(), BindAttribLocation(programID, i,
526                                                           meta.fAttributeNames[i].c_str()));
527     }
528 
529     const GrGLCaps& caps = glGpu->glCaps();
530     if (caps.bindFragDataLocationSupport()) {
531         SkASSERT(caps.shaderCaps()->mustDeclareFragmentShaderOutput());
532         GR_GL_CALL(glGpu->glInterface(),
533                    BindFragDataLocation(programID, 0,
534                                         GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
535 
536         if (meta.fHasSecondaryColorOutput) {
537             GR_GL_CALL(glGpu->glInterface(),
538                        BindFragDataLocationIndexed(programID, 0, 1,
539                                   GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
540         }
541     }
542 
543     GR_GL_CALL(glGpu->glInterface(), LinkProgram(programID));
544     GrGLint linked = GR_GL_INIT_ZERO;
545     GR_GL_CALL(glGpu->glInterface(), GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
546     if (!linked) {
547         cleanup_program(glGpu, programID, shadersToDelete);
548         return false;
549     }
550 
551     cleanup_shaders(glGpu, shadersToDelete);
552 
553     precompiledProgram->fProgramID = programID;
554     precompiledProgram->fInterface = interface;
555     return true;
556 }
557