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