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