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