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