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