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
37static 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
43static 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
49sk_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
79GrGLProgramBuilder::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
91const GrCaps* GrGLProgramBuilder::caps() const {
92    return fGpu->caps();
93}
94
95SkSL::Compiler* GrGLProgramBuilder::shaderCompiler() const {
96    return fGpu->shaderCompiler();
97}
98
99bool 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
119void 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
149void GrGLProgramBuilder::addInputVars(const SkSL::Program::Inputs& inputs) {
150    if (inputs.fUseFlipRTUniform) {
151        this->addRTFlipUniform(SKSL_RTFLIP_NAME);
152    }
153}
154
155static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
156static constexpr SkFourByteTag kGLSL_Tag = SkSetFourByteTag('G', 'L', 'S', 'L');
157static constexpr SkFourByteTag kGLPB_Tag = SkSetFourByteTag('G', 'L', 'P', 'B');
158
159void 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
212static 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
233sk_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
485void 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
499bool 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
530void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID, bool force) {
531    fUniformHandler.getUniformLocations(programID, fGpu->glCaps(), force);
532}
533
534sk_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
550bool 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