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