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