• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/GrContext.h"
11 #include "src/core/SkATrace.h"
12 #include "src/core/SkAutoMalloc.h"
13 #include "src/core/SkReader32.h"
14 #include "src/core/SkTraceEvent.h"
15 #include "src/core/SkWriter32.h"
16 #include "src/gpu/GrAutoLocaleSetter.h"
17 #include "src/gpu/GrContextPriv.h"
18 #include "src/gpu/GrCoordTransform.h"
19 #include "src/gpu/GrPersistentCacheUtils.h"
20 #include "src/gpu/GrProgramDesc.h"
21 #include "src/gpu/GrShaderCaps.h"
22 #include "src/gpu/GrShaderUtils.h"
23 #include "src/gpu/GrSwizzle.h"
24 #include "src/gpu/gl/GrGLGpu.h"
25 #include "src/gpu/gl/GrGLProgram.h"
26 #include "src/gpu/gl/builders/GrGLProgramBuilder.h"
27 #include "src/gpu/gl/builders/GrGLShaderStringBuilder.h"
28 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
29 #include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
30 #include "src/gpu/glsl/GrGLSLProgramDataManager.h"
31 #include "src/gpu/glsl/GrGLSLXferProcessor.h"
32 
33 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
34 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
35 
CreateProgram(GrRenderTarget * renderTarget,GrSurfaceOrigin origin,const GrPrimitiveProcessor & primProc,const GrTextureProxy * const primProcProxies[],const GrPipeline & pipeline,GrProgramDesc * desc,GrGLGpu * gpu)36 GrGLProgram* GrGLProgramBuilder::CreateProgram(GrRenderTarget* renderTarget, GrSurfaceOrigin origin,
37                                                const GrPrimitiveProcessor& primProc,
38                                                const GrTextureProxy* const primProcProxies[],
39                                                const GrPipeline& pipeline,
40                                                GrProgramDesc* desc,
41                                                GrGLGpu* gpu) {
42     SkASSERT(!pipeline.isBad());
43 
44     ATRACE_ANDROID_FRAMEWORK("Shader Compile");
45     GrAutoLocaleSetter als("C");
46 
47     // create a builder.  This will be handed off to effects so they can use it to add
48     // uniforms, varyings, textures, etc
49     GrGLProgramBuilder builder(gpu, renderTarget, origin,
50                                pipeline, primProc, primProcProxies, desc);
51 
52     auto persistentCache = gpu->getContext()->priv().getPersistentCache();
53     if (persistentCache) {
54         sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->keyLength());
55         builder.fCached = persistentCache->load(*key);
56         // the eventual end goal is to completely skip emitAndInstallProcs on a cache hit, but it's
57         // doing necessary setup in addition to generating the SkSL code. Currently we are only able
58         // to skip the SkSL->GLSL step on a cache hit.
59     }
60     if (!builder.emitAndInstallProcs()) {
61         return nullptr;
62     }
63     return builder.finalize();
64 }
65 
66 /////////////////////////////////////////////////////////////////////////////
67 
GrGLProgramBuilder(GrGLGpu * gpu,GrRenderTarget * renderTarget,GrSurfaceOrigin origin,const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,const GrTextureProxy * const primProcProxies[],GrProgramDesc * desc)68 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
69                                        GrRenderTarget* renderTarget,
70                                        GrSurfaceOrigin origin,
71                                        const GrPipeline& pipeline,
72                                        const GrPrimitiveProcessor& primProc,
73                                        const GrTextureProxy* const primProcProxies[],
74                                        GrProgramDesc* desc)
75         : INHERITED(renderTarget, origin, primProc, primProcProxies, pipeline, desc)
76         , fGpu(gpu)
77         , fVaryingHandler(this)
78         , fUniformHandler(this)
79         , fVertexAttributeCnt(0)
80         , fInstanceAttributeCnt(0)
81         , fVertexStride(0)
82         , fInstanceStride(0) {}
83 
caps() const84 const GrCaps* GrGLProgramBuilder::caps() const {
85     return fGpu->caps();
86 }
87 
compileAndAttachShaders(const SkSL::String & glsl,GrGLuint programId,GrGLenum type,SkTDArray<GrGLuint> * shaderIds,GrContextOptions::ShaderErrorHandler * errHandler)88 bool GrGLProgramBuilder::compileAndAttachShaders(const SkSL::String& glsl,
89                                                  GrGLuint programId,
90                                                  GrGLenum type,
91                                                  SkTDArray<GrGLuint>* shaderIds,
92                                                  GrContextOptions::ShaderErrorHandler* errHandler) {
93     GrGLGpu* gpu = this->gpu();
94     GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
95                                                    programId,
96                                                    type,
97                                                    glsl,
98                                                    gpu->stats(),
99                                                    errHandler);
100     if (!shaderId) {
101         return false;
102     }
103 
104     *shaderIds->append() = shaderId;
105     return true;
106 }
107 
computeCountsAndStrides(GrGLuint programID,const GrPrimitiveProcessor & primProc,bool bindAttribLocations)108 void GrGLProgramBuilder::computeCountsAndStrides(GrGLuint programID,
109                                                  const GrPrimitiveProcessor& primProc,
110                                                  bool bindAttribLocations) {
111     fVertexAttributeCnt = primProc.numVertexAttributes();
112     fInstanceAttributeCnt = primProc.numInstanceAttributes();
113     fAttributes.reset(
114             new GrGLProgram::Attribute[fVertexAttributeCnt + fInstanceAttributeCnt]);
115     auto addAttr = [&](int i, const auto& a, size_t* stride) {
116         fAttributes[i].fCPUType = a.cpuType();
117         fAttributes[i].fGPUType = a.gpuType();
118         fAttributes[i].fOffset = *stride;
119         *stride += a.sizeAlign4();
120         fAttributes[i].fLocation = i;
121         if (bindAttribLocations) {
122             GL_CALL(BindAttribLocation(programID, i, a.name()));
123         }
124     };
125     fVertexStride = 0;
126     int i = 0;
127     for (const auto& attr : primProc.vertexAttributes()) {
128         addAttr(i++, attr, &fVertexStride);
129     }
130     SkASSERT(fVertexStride == primProc.vertexStride());
131     fInstanceStride = 0;
132     for (const auto& attr : primProc.instanceAttributes()) {
133         addAttr(i++, attr, &fInstanceStride);
134     }
135     SkASSERT(fInstanceStride == primProc.instanceStride());
136 }
137 
addInputVars(const SkSL::Program::Inputs & inputs)138 void GrGLProgramBuilder::addInputVars(const SkSL::Program::Inputs& inputs) {
139     if (inputs.fRTWidth) {
140         this->addRTWidthUniform(SKSL_RTWIDTH_NAME);
141     }
142     if (inputs.fRTHeight) {
143         this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
144     }
145 }
146 
147 static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
148 static constexpr SkFourByteTag kGLSL_Tag = SkSetFourByteTag('G', 'L', 'S', 'L');
149 
storeShaderInCache(const SkSL::Program::Inputs & inputs,GrGLuint programID,const SkSL::String shaders[],bool isSkSL)150 void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Inputs& inputs, GrGLuint programID,
151                                             const SkSL::String shaders[], bool isSkSL) {
152     if (!this->gpu()->getContext()->priv().getPersistentCache()) {
153         return;
154     }
155     sk_sp<SkData> key = SkData::MakeWithoutCopy(desc()->asKey(), desc()->keyLength());
156     if (fGpu->glCaps().programBinarySupport()) {
157         // binary cache
158         GrGLsizei length = 0;
159         GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
160         if (length > 0) {
161             SkWriter32 writer;
162             writer.writePad(&inputs, sizeof(inputs));
163             writer.write32(length);
164 
165             void* binary = writer.reservePad(length);
166             GrGLenum binaryFormat;
167             GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary));
168             writer.write32(binaryFormat);
169 
170             auto data = writer.snapshotAsData();
171             this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
172         }
173     } else {
174         // source cache
175         auto data = GrPersistentCacheUtils::PackCachedShaders(isSkSL ? kSKSL_Tag : kGLSL_Tag,
176                                                               shaders, &inputs, 1);
177         this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
178     }
179 }
180 
finalize()181 GrGLProgram* GrGLProgramBuilder::finalize() {
182     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
183 
184     // verify we can get a program id
185     GrGLuint programID;
186     GL_CALL_RET(programID, CreateProgram());
187     if (0 == programID) {
188         return nullptr;
189     }
190 
191     if (this->gpu()->glCaps().programBinarySupport() &&
192         this->gpu()->glCaps().programParameterSupport() &&
193         this->gpu()->getContext()->priv().getPersistentCache()) {
194         GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
195     }
196 
197     this->finalizeShaders();
198 
199     // compile shaders and bind attributes / uniforms
200     auto errorHandler = this->gpu()->getContext()->priv().getShaderErrorHandler();
201     const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
202     SkSL::Program::Settings settings;
203     settings.fCaps = this->gpu()->glCaps().shaderCaps();
204     settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
205     settings.fSharpenTextures =
206                     this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
207     settings.fFragColorIsInOut = this->fragColorIsInOut();
208 
209     SkSL::Program::Inputs inputs;
210     SkTDArray<GrGLuint> shadersToDelete;
211     // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
212     bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
213 #ifdef SK_DEBUG
214     checkLinked = true;
215 #endif
216     bool cached = fCached.get() != nullptr;
217     bool usedProgramBinaries = false;
218     SkSL::String glsl[kGrShaderTypeCount];
219     SkSL::String* sksl[kGrShaderTypeCount] = {
220         &fVS.fCompilerString,
221         &fGS.fCompilerString,
222         &fFS.fCompilerString,
223     };
224 #if GR_TEST_UTILS
225     SkSL::String cached_sksl[kGrShaderTypeCount];
226 #endif
227     if (cached) {
228         if (fGpu->glCaps().programBinarySupport()) {
229             // binary cache hit, just hand the binary to GL
230             SkReader32 reader(fCached->data(), fCached->size());
231             reader.read(&inputs, sizeof(inputs));
232             GrGLsizei length = reader.readInt();
233             const void* binary = reader.skip(length);
234             GrGLenum binaryFormat = reader.readU32();
235             GrGLClearErr(this->gpu()->glInterface());
236             GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
237                                   ProgramBinary(programID, binaryFormat, const_cast<void*>(binary),
238                                                 length));
239             if (GR_GL_GET_ERROR(this->gpu()->glInterface()) == GR_GL_NO_ERROR) {
240                 if (checkLinked) {
241                     cached = this->checkLinkStatus(programID, errorHandler, nullptr, nullptr);
242                 }
243                 if (cached) {
244                     this->addInputVars(inputs);
245                     this->computeCountsAndStrides(programID, primProc, false);
246                 }
247             } else {
248                 cached = false;
249             }
250             usedProgramBinaries = cached;
251 #if GR_TEST_UTILS
252         } else if (fGpu->getContext()->priv().options().fCacheSKSL) {
253             // Only switch to the stored SkSL if it unpacks correctly
254             if (kSKSL_Tag == GrPersistentCacheUtils::UnpackCachedShaders(fCached.get(),
255                                                                          cached_sksl,
256                                                                          &inputs, 1)) {
257                 for (int i = 0; i < kGrShaderTypeCount; ++i) {
258                     sksl[i] = &cached_sksl[i];
259                 }
260             }
261 #endif
262         } else {
263             // source cache hit, we don't need to compile the SkSL->GLSL
264             // It's unlikely, but if we get the wrong kind of shader back, don't use the strings
265             if (kGLSL_Tag != GrPersistentCacheUtils::UnpackCachedShaders(fCached.get(),
266                                                                          glsl,
267                                                                          &inputs, 1)) {
268                 for (int i = 0; i < kGrShaderTypeCount; ++i) {
269                     glsl[i].clear();
270                 }
271             }
272         }
273     }
274     if (!cached || !fGpu->glCaps().programBinarySupport()) {
275         // either a cache miss, or we can't store binaries in the cache
276         if (glsl[kFragment_GrShaderType].empty()) {
277             // Don't have cached GLSL, need to compile SkSL->GLSL
278             if (fFS.fForceHighPrecision) {
279                 settings.fForceHighPrecision = true;
280             }
281             std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(gpu()->glContext(),
282                                                              SkSL::Program::kFragment_Kind,
283                                                              *sksl[kFragment_GrShaderType],
284                                                              settings,
285                                                              &glsl[kFragment_GrShaderType],
286                                                              errorHandler);
287             if (!fs) {
288                 this->cleanupProgram(programID, shadersToDelete);
289                 return nullptr;
290             }
291             inputs = fs->fInputs;
292             this->addInputVars(inputs);
293         } else {
294             // we've pulled GLSL and inputs from the cache, but still need to do some setup
295             this->addInputVars(inputs);
296             this->computeCountsAndStrides(programID, primProc, false);
297         }
298         if (!this->compileAndAttachShaders(glsl[kFragment_GrShaderType], programID,
299                                            GR_GL_FRAGMENT_SHADER, &shadersToDelete, errorHandler)) {
300             this->cleanupProgram(programID, shadersToDelete);
301             return nullptr;
302         }
303 
304         if (glsl[kVertex_GrShaderType].empty()) {
305             // Don't have cached GLSL, need to compile SkSL->GLSL
306             std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(gpu()->glContext(),
307                                                              SkSL::Program::kVertex_Kind,
308                                                              *sksl[kVertex_GrShaderType],
309                                                              settings,
310                                                              &glsl[kVertex_GrShaderType],
311                                                              errorHandler);
312             if (!vs) {
313                 this->cleanupProgram(programID, shadersToDelete);
314                 return nullptr;
315             }
316         }
317         if (!this->compileAndAttachShaders(glsl[kVertex_GrShaderType], programID,
318                                            GR_GL_VERTEX_SHADER, &shadersToDelete, errorHandler)) {
319             this->cleanupProgram(programID, shadersToDelete);
320             return nullptr;
321         }
322 
323         // NVPR actually requires a vertex shader to compile
324         bool useNvpr = primProc.isPathRendering();
325         if (!useNvpr) {
326             this->computeCountsAndStrides(programID, primProc, true);
327         }
328 
329         if (primProc.willUseGeoShader()) {
330             if (glsl[kGeometry_GrShaderType].empty()) {
331                 // Don't have cached GLSL, need to compile SkSL->GLSL
332                 std::unique_ptr<SkSL::Program> gs;
333                 gs = GrSkSLtoGLSL(gpu()->glContext(),
334                                   SkSL::Program::kGeometry_Kind,
335                                   *sksl[kGeometry_GrShaderType],
336                                   settings,
337                                   &glsl[kGeometry_GrShaderType],
338                                   errorHandler);
339                 if (!gs) {
340                     this->cleanupProgram(programID, shadersToDelete);
341                     return nullptr;
342                 }
343             }
344             if (!this->compileAndAttachShaders(glsl[kGeometry_GrShaderType], programID,
345                                                GR_GL_GEOMETRY_SHADER, &shadersToDelete,
346                                                errorHandler)) {
347                 this->cleanupProgram(programID, shadersToDelete);
348                 return nullptr;
349             }
350         }
351         this->bindProgramResourceLocations(programID);
352 
353         GL_CALL(LinkProgram(programID));
354         if (checkLinked) {
355             if (!this->checkLinkStatus(programID, errorHandler, sksl, glsl)) {
356                 GL_CALL(DeleteProgram(programID));
357                 return nullptr;
358             }
359         }
360     }
361     this->resolveProgramResourceLocations(programID, usedProgramBinaries);
362 
363     this->cleanupShaders(shadersToDelete);
364 
365     // With ANGLE, we can't cache path-rendering programs. We use ProgramPathFragmentInputGen,
366     // and ANGLE's deserialized program state doesn't restore enough state to handle that.
367     // The native NVIDIA drivers do, but this is such an edge case that it's easier to just
368     // black-list caching these programs in all cases. See: anglebug.com/3619
369     if (!cached && !primProc.isPathRendering()) {
370         bool isSkSL = false;
371 #if GR_TEST_UTILS
372         if (fGpu->getContext()->priv().options().fCacheSKSL) {
373             for (int i = 0; i < kGrShaderTypeCount; ++i) {
374                 glsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
375             }
376             isSkSL = true;
377         }
378 #endif
379         this->storeShaderInCache(inputs, programID, glsl, isSkSL);
380     }
381     return this->createProgram(programID);
382 }
383 
bindProgramResourceLocations(GrGLuint programID)384 void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
385     fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
386 
387     const GrGLCaps& caps = this->gpu()->glCaps();
388     if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
389         GL_CALL(BindFragDataLocation(programID, 0,
390                                      GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
391     }
392     if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
393         GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
394                                   GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
395     }
396 
397     // handle NVPR separable varyings
398     if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
399         !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
400         return;
401     }
402     int count = fVaryingHandler.fPathProcVaryingInfos.count();
403     for (int i = 0; i < count; ++i) {
404         GL_CALL(BindFragmentInputLocation(programID, i,
405                                        fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
406         fVaryingHandler.fPathProcVaryingInfos[i].fLocation = i;
407     }
408 }
409 
checkLinkStatus(GrGLuint programID,GrContextOptions::ShaderErrorHandler * errorHandler,SkSL::String * sksl[],const SkSL::String glsl[])410 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID,
411                                          GrContextOptions::ShaderErrorHandler* errorHandler,
412                                          SkSL::String* sksl[], const SkSL::String glsl[]) {
413     GrGLint linked = GR_GL_INIT_ZERO;
414     GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
415     if (!linked) {
416         SkSL::String allShaders;
417         if (sksl) {
418             allShaders.appendf("// Vertex SKSL\n%s\n", sksl[kVertex_GrShaderType]->c_str());
419             if (!sksl[kGeometry_GrShaderType]->empty()) {
420                 allShaders.appendf("// Geometry SKSL\n%s\n", sksl[kGeometry_GrShaderType]->c_str());
421             }
422             allShaders.appendf("// Fragment SKSL\n%s\n", sksl[kFragment_GrShaderType]->c_str());
423         }
424         if (glsl) {
425             allShaders.appendf("// Vertex GLSL\n%s\n", glsl[kVertex_GrShaderType].c_str());
426             if (!glsl[kGeometry_GrShaderType].empty()) {
427                 allShaders.appendf("// Geometry GLSL\n%s\n", glsl[kGeometry_GrShaderType].c_str());
428             }
429             allShaders.appendf("// Fragment GLSL\n%s\n", glsl[kFragment_GrShaderType].c_str());
430         }
431         GrGLint infoLen = GR_GL_INIT_ZERO;
432         GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
433         SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
434         if (infoLen > 0) {
435             // retrieve length even though we don't need it to workaround
436             // bug in chrome cmd buffer param validation.
437             GrGLsizei length = GR_GL_INIT_ZERO;
438             GL_CALL(GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get()));
439         }
440         errorHandler->compileError(allShaders.c_str(), infoLen > 0 ? (const char*)log.get() : "");
441     }
442     return SkToBool(linked);
443 }
444 
resolveProgramResourceLocations(GrGLuint programID,bool force)445 void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID, bool force) {
446     fUniformHandler.getUniformLocations(programID, fGpu->glCaps(), force);
447 
448     // handle NVPR separable varyings
449     if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
450         fGpu->glPathRendering()->shouldBindFragmentInputs()) {
451         return;
452     }
453     int count = fVaryingHandler.fPathProcVaryingInfos.count();
454     for (int i = 0; i < count; ++i) {
455         GrGLint location;
456         GL_CALL_RET(location, GetProgramResourceLocation(
457                                        programID,
458                                        GR_GL_FRAGMENT_INPUT,
459                                        fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
460         fVaryingHandler.fPathProcVaryingInfos[i].fLocation = location;
461     }
462 }
463 
cleanupProgram(GrGLuint programID,const SkTDArray<GrGLuint> & shaderIDs)464 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
465     GL_CALL(DeleteProgram(programID));
466     this->cleanupShaders(shaderIDs);
467 }
cleanupShaders(const SkTDArray<GrGLuint> & shaderIDs)468 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
469     for (int i = 0; i < shaderIDs.count(); ++i) {
470         GL_CALL(DeleteShader(shaderIDs[i]));
471     }
472 }
473 
createProgram(GrGLuint programID)474 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
475     return new GrGLProgram(fGpu,
476                            fUniformHandles,
477                            programID,
478                            fUniformHandler.fUniforms,
479                            fUniformHandler.fSamplers,
480                            fVaryingHandler.fPathProcVaryingInfos,
481                            std::move(fGeometryProcessor),
482                            std::move(fXferProcessor),
483                            std::move(fFragmentProcessors),
484                            fFragmentProcessorCnt,
485                            std::move(fAttributes),
486                            fVertexAttributeCnt,
487                            fInstanceAttributeCnt,
488                            fVertexStride,
489                            fInstanceStride);
490 }
491