blob: 96a750458d6cfbfe489b516ebd2c8e41c6ede71c [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
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
joshualitt47bb3822014-10-07 16:43:25 -07008#include "GrGLProgramBuilder.h"
joshualitt8072caa2015-02-12 14:20:52 -08009
bsalomon6f7f2012015-03-16 14:00:52 -070010#include "GrAutoLocaleSetter.h"
Robert Phillips9bee2e52017-05-29 12:37:20 -040011#include "GrContext.h"
Robert Phillips6be756b2018-01-16 15:07:54 -050012#include "GrContextPriv.h"
joshualitt47bb3822014-10-07 16:43:25 -070013#include "GrCoordTransform.h"
joshualitt30ba4362014-08-21 20:18:45 -070014#include "GrGLProgramBuilder.h"
egdaniel5d8f69f2016-09-07 07:24:12 -070015#include "GrProgramDesc.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050016#include "GrShaderCaps.h"
bsalomon7f9b2e42016-01-12 13:29:26 -080017#include "GrSwizzle.h"
Hal Canary95e3c052017-01-11 12:44:43 -050018#include "SkAutoMalloc.h"
Derek Sollenberger488f0d62017-03-03 15:48:33 -050019#include "SkATrace.h"
joshualitt30ba4362014-08-21 20:18:45 -070020#include "SkTraceEvent.h"
joshualitte7afc2d2015-09-11 10:44:13 -070021#include "gl/GrGLGpu.h"
joshualitte7afc2d2015-09-11 10:44:13 -070022#include "gl/GrGLProgram.h"
egdaniel574a4c12015-11-02 06:22:44 -080023#include "gl/builders/GrGLShaderStringBuilder.h"
egdaniel64c47282015-11-13 06:54:19 -080024#include "glsl/GrGLSLFragmentProcessor.h"
egdaniele659a582015-11-13 09:55:43 -080025#include "glsl/GrGLSLGeometryProcessor.h"
egdaniel018fb622015-10-28 07:26:40 -070026#include "glsl/GrGLSLProgramDataManager.h"
egdanielfa4cc8b2015-11-13 08:34:52 -080027#include "glsl/GrGLSLXferProcessor.h"
joshualitt30ba4362014-08-21 20:18:45 -070028
joshualitt30ba4362014-08-21 20:18:45 -070029#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
30#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
31
Robert Phillipsd0fe8752019-01-31 14:13:59 -050032GrGLProgram* GrGLProgramBuilder::CreateProgram(GrRenderTarget* renderTarget, GrSurfaceOrigin origin,
33 const GrPrimitiveProcessor& primProc,
Greg Daniel9a51a862018-11-30 10:18:14 -050034 const GrTextureProxy* const primProcProxies[],
Brian Salomonff168d92018-06-23 15:17:27 -040035 const GrPipeline& pipeline,
Ethan Nicholas38657112017-02-09 17:01:22 -050036 GrProgramDesc* desc,
egdaniel0e1853c2016-03-17 11:35:45 -070037 GrGLGpu* gpu) {
Brian Salomon7eae3e02018-08-07 14:02:38 +000038 SkASSERT(!pipeline.isBad());
Robert Phillipsa91e0b72017-05-01 13:12:20 -040039
Derek Sollenberger488f0d62017-03-03 15:48:33 -050040 ATRACE_ANDROID_FRAMEWORK("Shader Compile");
bsalomon3318ee72015-03-16 11:56:29 -070041 GrAutoLocaleSetter als("C");
42
joshualitt47bb3822014-10-07 16:43:25 -070043 // create a builder. This will be handed off to effects so they can use it to add
44 // uniforms, varyings, textures, etc
Robert Phillipsd0fe8752019-01-31 14:13:59 -050045 GrGLProgramBuilder builder(gpu, renderTarget, origin,
46 pipeline, primProc, primProcProxies, desc);
joshualitt47bb3822014-10-07 16:43:25 -070047
Robert Phillips9da87e02019-02-04 13:26:26 -050048 auto persistentCache = gpu->getContext()->priv().getPersistentCache();
Ethan Nicholas8d058832019-01-07 10:49:58 -050049 if (persistentCache) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040050 sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->keyLength());
Robert Phillips0c4b7b12018-03-06 08:20:37 -050051 builder.fCached = persistentCache->load(*key);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040052 // the eventual end goal is to completely skip emitAndInstallProcs on a cache hit, but it's
53 // doing necessary setup in addition to generating the SkSL code. Currently we are only able
54 // to skip the SkSL->GLSL step on a cache hit.
55 }
Ethan Nicholas2983f402017-05-08 09:36:08 -040056 if (!builder.emitAndInstallProcs()) {
halcanary96fcdcc2015-08-27 07:41:13 -070057 return nullptr;
joshualitt6c891102015-05-13 08:51:49 -070058 }
egdanielc1e71012016-01-20 07:53:51 -080059 return builder.finalize();
joshualitt47bb3822014-10-07 16:43:25 -070060}
61
joshualitt47bb3822014-10-07 16:43:25 -070062/////////////////////////////////////////////////////////////////////////////
63
egdaniel0e1853c2016-03-17 11:35:45 -070064GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
Robert Phillipsd0fe8752019-01-31 14:13:59 -050065 GrRenderTarget* renderTarget,
66 GrSurfaceOrigin origin,
egdaniel0e1853c2016-03-17 11:35:45 -070067 const GrPipeline& pipeline,
68 const GrPrimitiveProcessor& primProc,
Greg Daniel9a51a862018-11-30 10:18:14 -050069 const GrTextureProxy* const primProcProxies[],
Ethan Nicholas38657112017-02-09 17:01:22 -050070 GrProgramDesc* desc)
Robert Phillipsd0fe8752019-01-31 14:13:59 -050071 : INHERITED(renderTarget, origin, primProc, primProcProxies, pipeline, desc)
Brian Salomon802cb312018-06-08 18:05:20 -040072 , fGpu(gpu)
73 , fVaryingHandler(this)
74 , fUniformHandler(this)
Brian Salomon92be2f72018-06-19 14:33:47 -040075 , fVertexAttributeCnt(0)
76 , fInstanceAttributeCnt(0)
Brian Salomon802cb312018-06-08 18:05:20 -040077 , fVertexStride(0)
78 , fInstanceStride(0) {}
joshualitt30ba4362014-08-21 20:18:45 -070079
egdanielfa896322016-01-13 12:19:30 -080080const GrCaps* GrGLProgramBuilder::caps() const {
81 return fGpu->caps();
82}
83
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040084bool GrGLProgramBuilder::compileAndAttachShaders(const char* glsl,
85 int length,
egdaniel574a4c12015-11-02 06:22:44 -080086 GrGLuint programId,
87 GrGLenum type,
Ethan Nicholas941e7e22016-12-12 15:33:30 -050088 SkTDArray<GrGLuint>* shaderIds,
89 const SkSL::Program::Settings& settings,
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040090 const SkSL::Program::Inputs& inputs) {
egdaniel574a4c12015-11-02 06:22:44 -080091 GrGLGpu* gpu = this->gpu();
92 GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
93 programId,
94 type,
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040095 glsl,
96 length,
Ethan Nicholas941e7e22016-12-12 15:33:30 -050097 gpu->stats(),
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -040098 settings);
egdaniel574a4c12015-11-02 06:22:44 -080099 if (!shaderId) {
100 return false;
101 }
102
103 *shaderIds->append() = shaderId;
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400104 if (inputs.fFlipY) {
Ethan Nicholas38657112017-02-09 17:01:22 -0500105 GrProgramDesc* d = this->desc();
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500106 d->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(this->origin()));
Ethan Nicholas38657112017-02-09 17:01:22 -0500107 }
egdaniel574a4c12015-11-02 06:22:44 -0800108
109 return true;
110}
111
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400112void GrGLProgramBuilder::computeCountsAndStrides(GrGLuint programID,
113 const GrPrimitiveProcessor& primProc,
114 bool bindAttribLocations) {
115 fVertexAttributeCnt = primProc.numVertexAttributes();
116 fInstanceAttributeCnt = primProc.numInstanceAttributes();
117 fAttributes.reset(
118 new GrGLProgram::Attribute[fVertexAttributeCnt + fInstanceAttributeCnt]);
119 auto addAttr = [&](int i, const auto& a, size_t* stride) {
Brian Osman4a3f5c82018-09-18 16:16:38 -0400120 fAttributes[i].fCPUType = a.cpuType();
121 fAttributes[i].fGPUType = a.gpuType();
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400122 fAttributes[i].fOffset = *stride;
123 *stride += a.sizeAlign4();
124 fAttributes[i].fLocation = i;
125 if (bindAttribLocations) {
126 GL_CALL(BindAttribLocation(programID, i, a.name()));
127 }
128 };
129 fVertexStride = 0;
130 int i = 0;
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500131 for (const auto& attr : primProc.vertexAttributes()) {
132 addAttr(i++, attr, &fVertexStride);
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400133 }
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500134 SkASSERT(fVertexStride == primProc.vertexStride());
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400135 fInstanceStride = 0;
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500136 for (const auto& attr : primProc.instanceAttributes()) {
137 addAttr(i++, attr, &fInstanceStride);
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400138 }
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500139 SkASSERT(fInstanceStride == primProc.instanceStride());
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400140}
141
Ethan Nicholascd700e92018-08-24 16:43:57 -0400142void GrGLProgramBuilder::addInputVars(const SkSL::Program::Inputs& inputs) {
143 if (inputs.fRTWidth) {
144 this->addRTWidthUniform(SKSL_RTWIDTH_NAME);
145 }
146 if (inputs.fRTHeight) {
147 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
148 }
149}
150
Ethan Nicholas8d058832019-01-07 10:49:58 -0500151void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Inputs& inputs, GrGLuint programID,
152 const SkSL::String& glsl) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500153 if (!this->gpu()->getContext()->priv().getPersistentCache()) {
Ethan Nicholas8d058832019-01-07 10:49:58 -0500154 return;
155 }
156 sk_sp<SkData> key = SkData::MakeWithoutCopy(desc()->asKey(), desc()->keyLength());
157 if (fGpu->glCaps().programBinarySupport()) {
158 // binary cache
159 GrGLsizei length = 0;
160 GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
161 if (length > 0) {
162 GrGLenum binaryFormat;
163 std::unique_ptr<char[]> binary(new char[length]);
164 GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get()));
165 size_t dataLength = sizeof(inputs) + sizeof(binaryFormat) + length;
166 std::unique_ptr<uint8_t[]> data(new uint8_t[dataLength]);
167 size_t offset = 0;
168 memcpy(data.get() + offset, &inputs, sizeof(inputs));
169 offset += sizeof(inputs);
170 memcpy(data.get() + offset, &binaryFormat, sizeof(binaryFormat));
171 offset += sizeof(binaryFormat);
172 memcpy(data.get() + offset, binary.get(), length);
Robert Phillips9da87e02019-02-04 13:26:26 -0500173 this->gpu()->getContext()->priv().getPersistentCache()->store(
Ethan Nicholas8d058832019-01-07 10:49:58 -0500174 *key, *SkData::MakeWithoutCopy(data.get(), dataLength));
175 }
176 } else {
177 // source cache
178 size_t dataLength = sizeof(inputs) + glsl.length();
179 std::unique_ptr<uint8_t[]> data(new uint8_t[dataLength]);
180 size_t offset = 0;
181 memcpy(data.get() + offset, &inputs, sizeof(inputs));
182 offset += sizeof(inputs);
183 memcpy(data.get() + offset, glsl.data(), glsl.length());
Robert Phillips9da87e02019-02-04 13:26:26 -0500184 this->gpu()->getContext()->priv().getPersistentCache()->store(
Ethan Nicholas8d058832019-01-07 10:49:58 -0500185 *key, *SkData::MakeWithoutCopy(data.get(), dataLength));
186 }
187}
188
joshualitt47bb3822014-10-07 16:43:25 -0700189GrGLProgram* GrGLProgramBuilder::finalize() {
Brian Osman39c08ac2017-07-26 09:36:09 -0400190 TRACE_EVENT0("skia", TRACE_FUNC);
Ryan Macnak38a10ad2017-07-10 10:36:34 -0700191
joshualitt47bb3822014-10-07 16:43:25 -0700192 // verify we can get a program id
193 GrGLuint programID;
194 GL_CALL_RET(programID, CreateProgram());
195 if (0 == programID) {
halcanary96fcdcc2015-08-27 07:41:13 -0700196 return nullptr;
joshualitt30ba4362014-08-21 20:18:45 -0700197 }
198
Ethan Nicholas06d55fb2017-11-08 09:48:50 -0500199 if (this->gpu()->glCaps().programBinarySupport() &&
Robert Phillips9da87e02019-02-04 13:26:26 -0500200 this->gpu()->getContext()->priv().getPersistentCache()) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400201 GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
202 }
203
egdaniel9f1d4152016-02-10 09:50:38 -0800204 this->finalizeShaders();
205
joshualitt47bb3822014-10-07 16:43:25 -0700206 // compile shaders and bind attributes / uniforms
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400207 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500208 SkSL::Program::Settings settings;
209 settings.fCaps = this->gpu()->glCaps().shaderCaps();
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500210 settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
Robert Phillipsc1541ae2019-02-04 12:05:37 -0500211 settings.fSharpenTextures =
Robert Phillips9da87e02019-02-04 13:26:26 -0500212 this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
Brian Salomondc092132018-04-04 10:14:16 -0400213 settings.fFragColorIsInOut = this->fragColorIsInOut();
214
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500215 SkSL::Program::Inputs inputs;
joshualitt30ba4362014-08-21 20:18:45 -0700216 SkTDArray<GrGLuint> shadersToDelete;
Ethan Nicholas5a0338c2019-01-02 11:48:56 -0500217 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
218 bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
219#ifdef SK_DEBUG
220 checkLinked = true;
221#endif
Ethan Nicholas8d058832019-01-07 10:49:58 -0500222 bool cached = fCached.get() != nullptr;
223 SkSL::String glsl;
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400224 if (cached) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400225 const uint8_t* bytes = fCached->bytes();
226 size_t offset = 0;
227 memcpy(&inputs, bytes + offset, sizeof(inputs));
228 offset += sizeof(inputs);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500229 if (fGpu->glCaps().programBinarySupport()) {
230 // binary cache hit, just hand the binary to GL
231 int binaryFormat;
232 memcpy(&binaryFormat, bytes + offset, sizeof(binaryFormat));
233 offset += sizeof(binaryFormat);
234 GrGLClearErr(this->gpu()->glInterface());
235 GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
236 ProgramBinary(programID, binaryFormat, (void*) (bytes + offset),
237 fCached->size() - offset));
238 if (GR_GL_GET_ERROR(this->gpu()->glInterface()) == GR_GL_NO_ERROR) {
239 if (checkLinked) {
240 cached = this->checkLinkStatus(programID);
241 }
242 if (cached) {
243 this->addInputVars(inputs);
244 this->computeCountsAndStrides(programID, primProc, false);
245 }
246 } else {
247 cached = false;
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400248 }
Ethan Nicholas98ad5b72018-03-13 09:53:02 -0400249 } else {
Ethan Nicholas8d058832019-01-07 10:49:58 -0500250 // source cache hit, we don't need to compile the SkSL->GLSL
251 glsl = SkSL::String(((const char*) bytes) + offset, fCached->size() - offset);
Ethan Nicholas98ad5b72018-03-13 09:53:02 -0400252 }
253 }
Ethan Nicholas8d058832019-01-07 10:49:58 -0500254 if (!cached || !fGpu->glCaps().programBinarySupport()) {
255 // either a cache miss, or we can't store binaries in the cache
256 if (glsl == "" || true) {
257 // don't have cached GLSL, need to compile SkSL->GLSL
258 if (fFS.fForceHighPrecision) {
259 settings.fForceHighPrecision = true;
260 }
261 std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(gpu()->glContext(),
262 GR_GL_FRAGMENT_SHADER,
263 fFS.fCompilerStrings.begin(),
264 fFS.fCompilerStringLengths.begin(),
265 fFS.fCompilerStrings.count(),
266 settings,
267 &glsl);
268 if (!fs) {
269 this->cleanupProgram(programID, shadersToDelete);
270 return nullptr;
271 }
272 inputs = fs->fInputs;
273 } else {
274 // we've pulled GLSL and inputs from the cache, but still need to do some setup
275 this->addInputVars(inputs);
276 this->computeCountsAndStrides(programID, primProc, false);
egdaniel8dcdedc2015-11-11 06:27:20 -0800277 }
Ethan Nicholascd700e92018-08-24 16:43:57 -0400278 this->addInputVars(inputs);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400279 if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
280 GR_GL_FRAGMENT_SHADER, &shadersToDelete, settings,
281 inputs)) {
282 this->cleanupProgram(programID, shadersToDelete);
283 return nullptr;
284 }
285
286 std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(gpu()->glContext(),
287 GR_GL_VERTEX_SHADER,
288 fVS.fCompilerStrings.begin(),
289 fVS.fCompilerStringLengths.begin(),
290 fVS.fCompilerStrings.count(),
291 settings,
292 &glsl);
Brian Salomon7c934722018-06-01 14:42:53 -0400293 if (!vs || !this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
294 GR_GL_VERTEX_SHADER, &shadersToDelete, settings,
295 inputs)) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400296 this->cleanupProgram(programID, shadersToDelete);
297 return nullptr;
298 }
299
300 // NVPR actually requires a vertex shader to compile
301 bool useNvpr = primProc.isPathRendering();
302 if (!useNvpr) {
Ethan Nicholasad77dce2018-07-11 13:59:03 -0400303 this->computeCountsAndStrides(programID, primProc, true);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400304 }
305
306 if (primProc.willUseGeoShader()) {
307 std::unique_ptr<SkSL::Program> gs;
308 gs = GrSkSLtoGLSL(gpu()->glContext(),
309 GR_GL_GEOMETRY_SHADER,
310 fGS.fCompilerStrings.begin(),
311 fGS.fCompilerStringLengths.begin(),
312 fGS.fCompilerStrings.count(),
313 settings,
314 &glsl);
Brian Salomon7c934722018-06-01 14:42:53 -0400315 if (!gs || !this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
316 GR_GL_GEOMETRY_SHADER, &shadersToDelete,
317 settings, inputs)) {
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400318 this->cleanupProgram(programID, shadersToDelete);
319 return nullptr;
320 }
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400321 }
322 this->bindProgramResourceLocations(programID);
323
324 GL_CALL(LinkProgram(programID));
Ethan Nicholas5a0338c2019-01-02 11:48:56 -0500325 if (checkLinked) {
326 if (!this->checkLinkStatus(programID)) {
327 GL_CALL(DeleteProgram(programID));
328 SkDebugf("VS:\n");
329 GrGLPrintShader(fGpu->glContext(),
330 GR_GL_VERTEX_SHADER,
331 fVS.fCompilerStrings.begin(),
332 fVS.fCompilerStringLengths.begin(),
333 fVS.fCompilerStrings.count(),
334 settings);
335 if (primProc.willUseGeoShader()) {
336 SkDebugf("\nGS:\n");
337 GrGLPrintShader(fGpu->glContext(),
338 GR_GL_GEOMETRY_SHADER,
339 fGS.fCompilerStrings.begin(),
340 fGS.fCompilerStringLengths.begin(),
341 fGS.fCompilerStrings.count(), settings);
342 }
343 SkDebugf("\nFS:\n");
344 GrGLPrintShader(fGpu->glContext(),
345 GR_GL_FRAGMENT_SHADER,
346 fFS.fCompilerStrings.begin(),
347 fFS.fCompilerStringLengths.begin(),
348 fFS.fCompilerStrings.count(),
349 settings);
350 return nullptr;
Brian Salomone334c592017-05-15 11:00:58 -0400351 }
Brian Salomone334c592017-05-15 11:00:58 -0400352 }
joshualittfe1233c2014-10-07 12:16:35 -0700353 }
kkinnunen7aedda52015-06-29 23:01:28 -0700354 this->resolveProgramResourceLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700355
joshualitt47bb3822014-10-07 16:43:25 -0700356 this->cleanupShaders(shadersToDelete);
Ethan Nicholas8d058832019-01-07 10:49:58 -0500357 if (!cached) {
358 this->storeShaderInCache(inputs, programID, glsl);
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400359 }
joshualitt47bb3822014-10-07 16:43:25 -0700360 return this->createProgram(programID);
361}
362
kkinnunen7aedda52015-06-29 23:01:28 -0700363void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800364 fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
kkinnunen7aedda52015-06-29 23:01:28 -0700365
egdaniel8dcdedc2015-11-11 06:27:20 -0800366 const GrGLCaps& caps = this->gpu()->glCaps();
367 if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
368 GL_CALL(BindFragDataLocation(programID, 0,
egdaniel2d721d32015-11-11 13:06:05 -0800369 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800370 }
Brian Salomon1edc5b92016-11-29 13:43:46 -0500371 if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
egdaniel8dcdedc2015-11-11 06:27:20 -0800372 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
egdaniel2d721d32015-11-11 13:06:05 -0800373 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800374 }
joshualittd8dd47b2015-09-11 11:45:01 -0700375
376 // handle NVPR separable varyings
377 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
378 !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
379 return;
380 }
egdaniel0eafe792015-11-20 14:01:22 -0800381 int count = fVaryingHandler.fPathProcVaryingInfos.count();
joshualittd8dd47b2015-09-11 11:45:01 -0700382 for (int i = 0; i < count; ++i) {
egdaniel0eafe792015-11-20 14:01:22 -0800383 GL_CALL(BindFragmentInputLocation(programID, i,
384 fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
385 fVaryingHandler.fPathProcVaryingInfos[i].fLocation = i;
joshualittd8dd47b2015-09-11 11:45:01 -0700386 }
joshualitt47bb3822014-10-07 16:43:25 -0700387}
388
389bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
390 GrGLint linked = GR_GL_INIT_ZERO;
391 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
392 if (!linked) {
Brian Salomone334c592017-05-15 11:00:58 -0400393 SkDebugf("Program linking failed.\n");
joshualitt47bb3822014-10-07 16:43:25 -0700394 GrGLint infoLen = GR_GL_INIT_ZERO;
395 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
396 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
397 if (infoLen > 0) {
398 // retrieve length even though we don't need it to workaround
399 // bug in chrome cmd buffer param validation.
400 GrGLsizei length = GR_GL_INIT_ZERO;
401 GL_CALL(GetProgramInfoLog(programID,
402 infoLen+1,
403 &length,
404 (char*)log.get()));
kkinnunen297aaf92015-02-19 06:32:12 -0800405 SkDebugf("%s", (char*)log.get());
joshualitt47bb3822014-10-07 16:43:25 -0700406 }
joshualitt47bb3822014-10-07 16:43:25 -0700407 }
408 return SkToBool(linked);
409}
410
kkinnunen7aedda52015-06-29 23:01:28 -0700411void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800412 fUniformHandler.getUniformLocations(programID, fGpu->glCaps());
joshualittd8dd47b2015-09-11 11:45:01 -0700413
414 // handle NVPR separable varyings
415 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
kkinnunen7bdb05d2016-01-25 00:47:23 -0800416 fGpu->glPathRendering()->shouldBindFragmentInputs()) {
joshualittd8dd47b2015-09-11 11:45:01 -0700417 return;
418 }
egdaniel0eafe792015-11-20 14:01:22 -0800419 int count = fVaryingHandler.fPathProcVaryingInfos.count();
joshualittd8dd47b2015-09-11 11:45:01 -0700420 for (int i = 0; i < count; ++i) {
421 GrGLint location;
egdaniel0eafe792015-11-20 14:01:22 -0800422 GL_CALL_RET(location, GetProgramResourceLocation(
423 programID,
424 GR_GL_FRAGMENT_INPUT,
425 fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
426 fVaryingHandler.fPathProcVaryingInfos[i].fLocation = location;
joshualittd8dd47b2015-09-11 11:45:01 -0700427 }
joshualitt30ba4362014-08-21 20:18:45 -0700428}
429
joshualitt47bb3822014-10-07 16:43:25 -0700430void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
431 GL_CALL(DeleteProgram(programID));
egdanielfa896322016-01-13 12:19:30 -0800432 this->cleanupShaders(shaderIDs);
joshualitt47bb3822014-10-07 16:43:25 -0700433}
434void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
435 for (int i = 0; i < shaderIDs.count(); ++i) {
Brian Salomon802cb312018-06-08 18:05:20 -0400436 GL_CALL(DeleteShader(shaderIDs[i]));
joshualitt47bb3822014-10-07 16:43:25 -0700437 }
438}
439
440GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800441 return new GrGLProgram(fGpu,
egdaniel7ea439b2015-12-03 09:20:44 -0800442 fUniformHandles,
443 programID,
444 fUniformHandler.fUniforms,
egdaniel09aa1fc2016-04-20 07:09:46 -0700445 fUniformHandler.fSamplers,
egdaniel0eafe792015-11-20 14:01:22 -0800446 fVaryingHandler.fPathProcVaryingInfos,
Robert Phillips369e8b72017-08-01 16:13:04 -0400447 std::move(fGeometryProcessor),
448 std::move(fXferProcessor),
Brian Salomon4d3f5172018-06-07 14:42:52 -0400449 std::move(fFragmentProcessors),
Brian Salomon802cb312018-06-08 18:05:20 -0400450 fFragmentProcessorCnt,
451 std::move(fAttributes),
Brian Salomon92be2f72018-06-19 14:33:47 -0400452 fVertexAttributeCnt,
453 fInstanceAttributeCnt,
Brian Salomon802cb312018-06-08 18:05:20 -0400454 fVertexStride,
455 fInstanceStride);
joshualitt47bb3822014-10-07 16:43:25 -0700456}