• 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 
208 // Advanced Filter: Replace glsl shader of blur effect if AF is enabled
209 // In passthrough mode, uv transformed by Matrix in vert shader, and frag shader will use it directly
210 // Besides, uvOffset will be discarded by skia compiler, so the frag shader is mismatched with original shader
211 // Here we replace the shader by adding uvOffset
ApplyAdvancedFilter(std::string & glsl)212 static void ApplyAdvancedFilter(std::string& glsl)
213 {
214     glsl = "#version 320 es\n"
215         "precision mediump float;\n"
216         "precision mediump sampler2D;\n"
217         "out mediump vec4 sk_FragColor;\n"
218         "mediump vec4 inColor_Stage1_c0;\n"
219         "uniform highp mat3 umatrix_S1_c0;\n"
220         "uniform highp vec2 uin_blurOffset_S1[5];\n"
221         "uniform sampler2D uTextureSampler_0_S1;\n"
222         "in highp vec2 vLocalCoord_S0;\n"
223         "in highp vec2 vTransformedCoords_3_S0;\n"
224         "void main() {\n"
225         "    mediump vec4 _1_c = vec4(0.0, 0.0, 0.0, 0.0);\n"
226         "    for (highp int _2_i = 0; _2_i < 5; ++_2_i) {\n"
227         "        _1_c += texture(uTextureSampler_0_S1, vTransformedCoords_3_S0 + uin_blurOffset_S1[_2_i]);\n"
228         "    }\n"
229         "    sk_FragColor = vec4(_1_c.xyz * 0.2, 1.0);\n"
230         "}\n";
231 }
232 
finalize(const GrGLPrecompiledProgram * precompiledProgram)233 sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* precompiledProgram) {
234     TRACE_EVENT0("skia.shaders", TRACE_FUNC);
235 
236     // verify we can get a program id
237     GrGLuint programID;
238     if (precompiledProgram) {
239         programID = precompiledProgram->fProgramID;
240     } else {
241         GL_CALL_RET(programID, CreateProgram());
242     }
243     if (0 == programID) {
244         return nullptr;
245     }
246 
247     if (this->gpu()->glCaps().programBinarySupport() &&
248         this->gpu()->glCaps().programParameterSupport() &&
249         this->gpu()->getContext()->priv().getPersistentCache() &&
250         !precompiledProgram) {
251         GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
252     }
253 
254     this->finalizeShaders();
255 
256     // compile shaders and bind attributes / uniforms
257     auto errorHandler = this->gpu()->getContext()->priv().getShaderErrorHandler();
258     const GrGeometryProcessor& geomProc = this->geometryProcessor();
259     SkSL::Program::Settings settings;
260     settings.fSharpenTextures =
261                     this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
262     settings.fFragColorIsInOut = this->fragColorIsInOut();
263 
264     SkSL::Program::Inputs inputs;
265     SkTDArray<GrGLuint> shadersToDelete;
266 
267     bool checkLinked = !fGpu->glCaps().skipErrorChecks();
268 
269     bool cached = fCached.get() != nullptr;
270     bool usedProgramBinaries = false;
271     SkSL::String glsl[kGrShaderTypeCount];
272     SkSL::String* sksl[kGrShaderTypeCount] = {
273         &fVS.fCompilerString,
274         &fFS.fCompilerString,
275     };
276     SkSL::String cached_sksl[kGrShaderTypeCount];
277     if (precompiledProgram) {
278         // This is very similar to when we get program binaries. We even set that flag, as it's
279         // used to prevent other compile work later, and to force re-querying uniform locations.
280         this->addInputVars(precompiledProgram->fInputs);
281         this->computeCountsAndStrides(programID, geomProc, false);
282         usedProgramBinaries = true;
283     } else if (cached) {
284         TRACE_EVENT0_ALWAYS("skia.shaders", "cache_hit");
285         SkReadBuffer reader(fCached->data(), fCached->size());
286         SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
287 
288         switch (shaderType) {
289             case kGLPB_Tag: {
290                 // Program binary cache hit. We may opt not to use this if we don't trust program
291                 // binaries on this driver
292                 if (!fGpu->glCaps().programBinarySupport()) {
293                     cached = false;
294                     break;
295                 }
296                 reader.readPad32(&inputs, sizeof(inputs));
297                 GrGLenum binaryFormat = reader.readUInt();
298                 GrGLsizei length      = reader.readInt();
299                 const void* binary = reader.skip(length);
300                 if (!reader.isValid()) {
301                     break;
302                 }
303                 this->gpu()->clearErrorsAndCheckForOOM();
304                 GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
305                                       ProgramBinary(programID, binaryFormat,
306                                                     const_cast<void*>(binary), length));
307                 if (this->gpu()->getErrorAndCheckForOOM() == GR_GL_NO_ERROR) {
308                     if (checkLinked) {
309                         cached = this->checkLinkStatus(programID, errorHandler, nullptr, nullptr);
310                     }
311                     if (cached) {
312                         this->addInputVars(inputs);
313                         this->computeCountsAndStrides(programID, geomProc, false);
314                     }
315                 } else {
316                     cached = false;
317                 }
318                 usedProgramBinaries = cached;
319                 break;
320             }
321 
322             case kGLSL_Tag:
323                 // Source cache hit, we don't need to compile the SkSL->GLSL
324                 GrPersistentCacheUtils::UnpackCachedShaders(&reader, glsl, &inputs, 1);
325                 break;
326 
327             case kSKSL_Tag:
328                 // SkSL cache hit, this should only happen in tools overriding the generated SkSL
329                 if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, &inputs, 1)) {
330                     for (int i = 0; i < kGrShaderTypeCount; ++i) {
331                         sksl[i] = &cached_sksl[i];
332                     }
333                 }
334                 break;
335 
336             default:
337                 // We got something invalid, so pretend it wasn't there
338                 reader.validate(false);
339                 break;
340         }
341         if (!reader.isValid()) {
342             cached = false;
343         }
344     }
345     if (!usedProgramBinaries) {
346         TRACE_EVENT0_ALWAYS("skia.shaders", "cache_miss");
347         // Either a cache miss, or we got something other than binaries from the cache
348 
349         /*
350            Fragment Shader
351         */
352         if (glsl[kFragment_GrShaderType].empty()) {
353             // Don't have cached GLSL, need to compile SkSL->GLSL
354             if (fFS.fForceHighPrecision) {
355                 settings.fForceHighPrecision = true;
356             }
357             std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(this->gpu(),
358                                                              SkSL::ProgramKind::kFragment,
359                                                              *sksl[kFragment_GrShaderType],
360                                                              settings,
361                                                              &glsl[kFragment_GrShaderType],
362                                                              errorHandler);
363             if (!fs) {
364                 cleanup_program(fGpu, programID, shadersToDelete);
365                 return nullptr;
366             }
367             inputs = fs->fInputs;
368         }
369 
370         this->addInputVars(inputs);
371 
372         // Advanced Filter: Only when process name is render_service, check AF enabled or not
373         // If AF is enabled, replace the shader, previous code make sure gpu()->getContext() not null
374         if (gpu()->getContext()->getProcessName() == "render_service" && fProgramInfo.pipeline().checkAFRecursively()) {
375             ApplyAdvancedFilter(glsl[kFragment_GrShaderType]);
376         }
377 
378         if (!this->compileAndAttachShaders(glsl[kFragment_GrShaderType], programID,
379                                            GR_GL_FRAGMENT_SHADER, &shadersToDelete, errorHandler)) {
380             cleanup_program(fGpu, programID, shadersToDelete);
381             return nullptr;
382         }
383 
384         /*
385            Vertex Shader
386         */
387         if (glsl[kVertex_GrShaderType].empty()) {
388             // Don't have cached GLSL, need to compile SkSL->GLSL
389             std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(this->gpu(),
390                                                              SkSL::ProgramKind::kVertex,
391                                                              *sksl[kVertex_GrShaderType],
392                                                              settings,
393                                                              &glsl[kVertex_GrShaderType],
394                                                              errorHandler);
395             if (!vs) {
396                 cleanup_program(fGpu, programID, shadersToDelete);
397                 return nullptr;
398             }
399         }
400         if (!this->compileAndAttachShaders(glsl[kVertex_GrShaderType], programID,
401                                            GR_GL_VERTEX_SHADER, &shadersToDelete, errorHandler)) {
402             cleanup_program(fGpu, programID, shadersToDelete);
403             return nullptr;
404         }
405 
406         // This also binds vertex attribute locations.
407         this->computeCountsAndStrides(programID, geomProc, true);
408 
409         /*
410            Tessellation Shaders
411         */
412         if (fProgramInfo.geomProc().willUseTessellationShaders()) {
413             // Tessellation shaders are not currently supported by SkSL. So here, we temporarily
414             // generate GLSL strings directly using back door methods on GrGeometryProcessor, and
415             // pass those raw strings on to the driver.
416             SkString versionAndExtensionDecls;
417             versionAndExtensionDecls.appendf("%s\n", this->shaderCaps()->versionDeclString());
418             if (const char* extensionString = this->shaderCaps()->tessellationExtensionString()) {
419                 versionAndExtensionDecls.appendf("#extension %s : require\n", extensionString);
420             }
421 
422             SkString tessControlShader =
423                     fGPImpl->getTessControlShaderGLSL(geomProc,
424                                                       versionAndExtensionDecls.c_str(),
425                                                       fUniformHandler,
426                                                       *this->shaderCaps());
427             if (!this->compileAndAttachShaders(tessControlShader.c_str(), programID,
428                                                GR_GL_TESS_CONTROL_SHADER, &shadersToDelete,
429                                                errorHandler)) {
430                 cleanup_program(fGpu, programID, shadersToDelete);
431                 return nullptr;
432             }
433 
434             SkString tessEvaluationShader =
435                     fGPImpl->getTessEvaluationShaderGLSL(geomProc,
436                                                          versionAndExtensionDecls.c_str(),
437                                                          fUniformHandler,
438                                                          *this->shaderCaps());
439             if (!this->compileAndAttachShaders(tessEvaluationShader.c_str(), programID,
440                                                GR_GL_TESS_EVALUATION_SHADER, &shadersToDelete,
441                                                errorHandler)) {
442                 cleanup_program(fGpu, programID, shadersToDelete);
443                 return nullptr;
444             }
445         }
446 
447         this->bindProgramResourceLocations(programID);
448 
449         {
450             TRACE_EVENT0_ALWAYS("skia.shaders", "driver_link_program");
451             GL_CALL(LinkProgram(programID));
452             if (checkLinked) {
453                 if (!this->checkLinkStatus(programID, errorHandler, sksl, glsl)) {
454                     cleanup_program(fGpu, programID, shadersToDelete);
455                     return nullptr;
456                 }
457             }
458         }
459     }
460     this->resolveProgramResourceLocations(programID, usedProgramBinaries);
461 
462     cleanup_shaders(fGpu, shadersToDelete);
463 
464     // We temporarily can't cache tessellation shaders while using back door GLSL.
465     //
466     // We also can't cache SkSL or GLSL if we were given a precompiled program, but there's not
467     // much point in doing so.
468     if (!cached && !geomProc.willUseTessellationShaders() && !precompiledProgram) {
469         // FIXME: Remove the check for tessellation shaders in the above 'if' once the back door
470         // GLSL mechanism is removed.
471         (void)&GrGeometryProcessor::ProgramImpl::getTessControlShaderGLSL;
472         bool isSkSL = false;
473         if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
474                 GrContextOptions::ShaderCacheStrategy::kSkSL) {
475             for (int i = 0; i < kGrShaderTypeCount; ++i) {
476                 glsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
477             }
478             isSkSL = true;
479         }
480         this->storeShaderInCache(inputs, programID, glsl, isSkSL, &settings);
481     }
482     return this->createProgram(programID);
483 }
484 
bindProgramResourceLocations(GrGLuint programID)485 void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
486     fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
487 
488     const GrGLCaps& caps = this->gpu()->glCaps();
489     if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
490         GL_CALL(BindFragDataLocation(programID, 0,
491                                      GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
492     }
493     if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
494         GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
495                                   GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
496     }
497 }
498 
checkLinkStatus(GrGLuint programID,GrContextOptions::ShaderErrorHandler * errorHandler,SkSL::String * sksl[],const SkSL::String glsl[])499 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID,
500                                          GrContextOptions::ShaderErrorHandler* errorHandler,
501                                          SkSL::String* sksl[], const SkSL::String glsl[]) {
502     GrGLint linked = GR_GL_INIT_ZERO;
503     GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
504     if (!linked) {
505         SkSL::String allShaders;
506         if (sksl) {
507             allShaders.appendf("// Vertex SKSL\n%s\n", sksl[kVertex_GrShaderType]->c_str());
508             allShaders.appendf("// Fragment SKSL\n%s\n", sksl[kFragment_GrShaderType]->c_str());
509         }
510         if (glsl) {
511             allShaders.appendf("// Vertex GLSL\n%s\n", glsl[kVertex_GrShaderType].c_str());
512             allShaders.appendf("// Fragment GLSL\n%s\n", glsl[kFragment_GrShaderType].c_str());
513         }
514         GrGLint infoLen = GR_GL_INIT_ZERO;
515         GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
516         SkAutoMalloc log(infoLen+1);
517         if (infoLen > 0) {
518             // retrieve length even though we don't need it to workaround
519             // bug in chrome cmd buffer param validation.
520             GrGLsizei length = GR_GL_INIT_ZERO;
521             GL_CALL(GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get()));
522         }
523         const char* errorMsg = (infoLen > 0) ? (const char*)log.get()
524                                              : "link failed but did not provide an info log";
525         errorHandler->compileError(allShaders.c_str(), errorMsg);
526     }
527     return SkToBool(linked);
528 }
529 
resolveProgramResourceLocations(GrGLuint programID,bool force)530 void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID, bool force) {
531     fUniformHandler.getUniformLocations(programID, fGpu->glCaps(), force);
532 }
533 
createProgram(GrGLuint programID)534 sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID) {
535     return GrGLProgram::Make(fGpu,
536                              fUniformHandles,
537                              programID,
538                              fUniformHandler.fUniforms,
539                              fUniformHandler.fSamplers,
540                              std::move(fGPImpl),
541                              std::move(fXPImpl),
542                              std::move(fFPImpls),
543                              std::move(fAttributes),
544                              fVertexAttributeCnt,
545                              fInstanceAttributeCnt,
546                              fVertexStride,
547                              fInstanceStride);
548 }
549 
PrecompileProgram(GrDirectContext * dContext,GrGLPrecompiledProgram * precompiledProgram,const SkData & cachedData)550 bool GrGLProgramBuilder::PrecompileProgram(GrDirectContext* dContext,
551                                            GrGLPrecompiledProgram* precompiledProgram,
552                                            const SkData& cachedData) {
553     SkReadBuffer reader(cachedData.data(), cachedData.size());
554     SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
555     if (shaderType != kSKSL_Tag) {
556         // TODO: Support GLSL, and maybe even program binaries, too?
557         return false;
558     }
559 
560     GrGLGpu* glGpu = static_cast<GrGLGpu*>(dContext->priv().getGpu());
561 
562     const GrGLInterface* gl = glGpu->glInterface();
563     auto errorHandler = dContext->priv().getShaderErrorHandler();
564 
565     SkSL::Program::Settings settings;
566     settings.fSharpenTextures = dContext->priv().options().fSharpenMipmappedTextures;
567     GrPersistentCacheUtils::ShaderMetadata meta;
568     meta.fSettings = &settings;
569 
570     SkSL::String shaders[kGrShaderTypeCount];
571     SkSL::Program::Inputs inputs;
572     if (!GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &inputs, 1, &meta)) {
573         return false;
574     }
575 
576     GrGLuint programID;
577     GR_GL_CALL_RET(gl, programID, CreateProgram());
578     if (0 == programID) {
579         return false;
580     }
581 
582     SkTDArray<GrGLuint> shadersToDelete;
583 
584     auto compileShader = [&](SkSL::ProgramKind kind, const SkSL::String& sksl, GrGLenum type) {
585         SkSL::String glsl;
586         auto program = GrSkSLtoGLSL(glGpu, kind, sksl, settings, &glsl, errorHandler);
587         if (!program) {
588             return false;
589         }
590 
591         if (GrGLuint shaderID = GrGLCompileAndAttachShader(glGpu->glContext(), programID, type,
592                                                            glsl, glGpu->pipelineBuilder()->stats(),
593                                                            errorHandler)) {
594             shadersToDelete.push_back(shaderID);
595             return true;
596         } else {
597             return false;
598         }
599     };
600 
601     if (!compileShader(SkSL::ProgramKind::kFragment,
602                        shaders[kFragment_GrShaderType],
603                        GR_GL_FRAGMENT_SHADER) ||
604         !compileShader(SkSL::ProgramKind::kVertex,
605                        shaders[kVertex_GrShaderType],
606                        GR_GL_VERTEX_SHADER)) {
607         cleanup_program(glGpu, programID, shadersToDelete);
608         return false;
609     }
610 
611     for (int i = 0; i < meta.fAttributeNames.count(); ++i) {
612         GR_GL_CALL(glGpu->glInterface(), BindAttribLocation(programID, i,
613                                                           meta.fAttributeNames[i].c_str()));
614     }
615 
616     const GrGLCaps& caps = glGpu->glCaps();
617     if (meta.fHasCustomColorOutput && caps.bindFragDataLocationSupport()) {
618         GR_GL_CALL(glGpu->glInterface(),
619                    BindFragDataLocation(programID, 0,
620                                         GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
621     }
622     if (meta.fHasSecondaryColorOutput && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
623         GR_GL_CALL(glGpu->glInterface(),
624                    BindFragDataLocationIndexed(programID, 0, 1,
625                                GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
626     }
627 
628     GR_GL_CALL(glGpu->glInterface(), LinkProgram(programID));
629     GrGLint linked = GR_GL_INIT_ZERO;
630     GR_GL_CALL(glGpu->glInterface(), GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
631     if (!linked) {
632         cleanup_program(glGpu, programID, shadersToDelete);
633         return false;
634     }
635 
636     cleanup_shaders(glGpu, shadersToDelete);
637 
638     precompiledProgram->fProgramID = programID;
639     precompiledProgram->fInputs = inputs;
640     return true;
641 }
642