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