blob: 67ba08339b89387c8a84dd53f4c05d9e14df24e2 [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"
joshualitt47bb3822014-10-07 16:43:25 -070011#include "GrCoordTransform.h"
joshualitt30ba4362014-08-21 20:18:45 -070012#include "GrGLProgramBuilder.h"
13#include "GrTexture.h"
joshualitt30ba4362014-08-21 20:18:45 -070014#include "SkRTConf.h"
15#include "SkTraceEvent.h"
egdaniel574a4c12015-11-02 06:22:44 -080016#include "gl/GrGLFragmentProcessor.h"
joshualitte7afc2d2015-09-11 10:44:13 -070017#include "gl/GrGLGeometryProcessor.h"
18#include "gl/GrGLGpu.h"
joshualitte7afc2d2015-09-11 10:44:13 -070019#include "gl/GrGLProgram.h"
20#include "gl/GrGLSLPrettyPrint.h"
21#include "gl/GrGLXferProcessor.h"
egdaniel574a4c12015-11-02 06:22:44 -080022#include "gl/builders/GrGLShaderStringBuilder.h"
joshualitte7afc2d2015-09-11 10:44:13 -070023#include "glsl/GrGLSLCaps.h"
egdaniel018fb622015-10-28 07:26:40 -070024#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7dc4bd02015-10-29 07:57:01 -070025#include "glsl/GrGLSLTextureSampler.h"
joshualitt30ba4362014-08-21 20:18:45 -070026
joshualitt30ba4362014-08-21 20:18:45 -070027#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
28#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
29
joshualitt873ad0e2015-01-20 09:08:51 -080030GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gpu) {
bsalomon3318ee72015-03-16 11:56:29 -070031 GrAutoLocaleSetter als("C");
32
joshualitt47bb3822014-10-07 16:43:25 -070033 // create a builder. This will be handed off to effects so they can use it to add
34 // uniforms, varyings, textures, etc
joshualittd8dd47b2015-09-11 11:45:01 -070035 SkAutoTDelete<GrGLProgramBuilder> builder(new GrGLProgramBuilder(gpu, args));
joshualitt47bb3822014-10-07 16:43:25 -070036
37 GrGLProgramBuilder* pb = builder.get();
joshualitt47bb3822014-10-07 16:43:25 -070038
egdaniel37b4d862014-11-03 10:07:07 -080039 // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
joshualitt9b989322014-12-15 14:16:27 -080040 // seed correctly here
41 GrGLSLExpr4 inputColor;
42 GrGLSLExpr4 inputCoverage;
egdaniel37b4d862014-11-03 10:07:07 -080043
joshualitt6c891102015-05-13 08:51:49 -070044 if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) {
halcanary96fcdcc2015-08-27 07:41:13 -070045 return nullptr;
joshualitt6c891102015-05-13 08:51:49 -070046 }
joshualitt47bb3822014-10-07 16:43:25 -070047
joshualitt47bb3822014-10-07 16:43:25 -070048 return pb->finalize();
49}
50
joshualitt47bb3822014-10-07 16:43:25 -070051/////////////////////////////////////////////////////////////////////////////
52
joshualitt873ad0e2015-01-20 09:08:51 -080053GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args)
egdaniel8dcdedc2015-11-11 06:27:20 -080054 : INHERITED(args)
halcanary96fcdcc2015-08-27 07:41:13 -070055 , fGeometryProcessor(nullptr)
56 , fXferProcessor(nullptr)
joshualitt30ba4362014-08-21 20:18:45 -070057 , fGpu(gpu)
cdalton42717652015-06-18 11:54:30 -070058 , fUniforms(kVarsPerBlock)
joshualittd8dd47b2015-09-11 11:45:01 -070059 , fSamplerUniforms(4)
60 , fSeparableVaryingInfos(kVarsPerBlock) {
joshualitt30ba4362014-08-21 20:18:45 -070061}
62
joshualitt74077b92014-10-24 11:26:03 -070063void GrGLProgramBuilder::addVarying(const char* name,
egdaniel8dcdedc2015-11-11 06:27:20 -080064 GrGLSLVarying* varying,
joshualitteb00eab2015-09-15 14:12:22 -070065 GrSLPrecision precision) {
joshualitt74077b92014-10-24 11:26:03 -070066 SkASSERT(varying);
67 if (varying->vsVarying()) {
joshualitteb00eab2015-09-15 14:12:22 -070068 fVS.addVarying(name, precision, varying);
joshualitt74077b92014-10-24 11:26:03 -070069 }
joshualitt873ad0e2015-01-20 09:08:51 -080070 if (this->primitiveProcessor().willUseGeoShader()) {
joshualitteb00eab2015-09-15 14:12:22 -070071 fGS.addVarying(name, precision, varying);
joshualitt74077b92014-10-24 11:26:03 -070072 }
73 if (varying->fsVarying()) {
joshualitteb00eab2015-09-15 14:12:22 -070074 fFS.addVarying(varying, precision);
joshualitt74077b92014-10-24 11:26:03 -070075 }
joshualitt47bb3822014-10-07 16:43:25 -070076}
77
joshualitt71c92602015-01-14 08:12:47 -080078void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Attribute* input,
joshualitt2dd1ae02014-12-03 06:24:10 -080079 const char* output) {
80 GrSLType type = GrVertexAttribTypeToSLType(input->fType);
egdaniel8dcdedc2015-11-11 06:27:20 -080081 GrGLSLVertToFrag v(type);
joshualitt2dd1ae02014-12-03 06:24:10 -080082 this->addVarying(input->fName, &v);
83 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName);
84 fFS.codeAppendf("%s = %s;", output, v.fsIn());
85}
86
joshualittd8dd47b2015-09-11 11:45:01 -070087GrGLProgramBuilder::SeparableVaryingHandle GrGLProgramBuilder::addSeparableVarying(
88 const char* name,
egdaniel8dcdedc2015-11-11 06:27:20 -080089 GrGLSLVertToFrag* v,
joshualittd8dd47b2015-09-11 11:45:01 -070090 GrSLPrecision fsPrecision) {
91 // This call is not used for non-NVPR backends.
92 SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport() &&
93 fArgs.fPrimitiveProcessor->isPathRendering() &&
94 !fArgs.fPrimitiveProcessor->willUseGeoShader() &&
95 fArgs.fPrimitiveProcessor->numAttribs() == 0);
96 this->addVarying(name, v, fsPrecision);
97 SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back();
98 varyingInfo.fVariable = this->getFragmentShaderBuilder()->fInputs.back();
99 varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1;
100 return SeparableVaryingHandle(varyingInfo.fLocation);
kkinnunen7aedda52015-06-29 23:01:28 -0700101}
102
egdanielf3bace92015-11-06 06:57:12 -0800103GrGLSLProgramDataManager::UniformHandle GrGLProgramBuilder::internalAddUniformArray(
bsalomon422f56f2014-12-09 10:18:12 -0800104 uint32_t visibility,
105 GrSLType type,
106 GrSLPrecision precision,
107 const char* name,
egdanielf3bace92015-11-06 06:57:12 -0800108 bool mangleName,
bsalomon422f56f2014-12-09 10:18:12 -0800109 int count,
110 const char** outName) {
joshualitt30ba4362014-08-21 20:18:45 -0700111 SkASSERT(name && strlen(name));
112 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
113 SkASSERT(0 == (~kVisibilityMask & visibility));
114 SkASSERT(0 != visibility);
bsalomon422f56f2014-12-09 10:18:12 -0800115 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type));
joshualitt30ba4362014-08-21 20:18:45 -0700116
117 UniformInfo& uni = fUniforms.push_back();
118 uni.fVariable.setType(type);
egdaniel0d3f0612015-10-21 10:45:48 -0700119 uni.fVariable.setTypeModifier(GrGLSLShaderVar::kUniform_TypeModifier);
joshualitt4973d9d2014-11-08 09:24:25 -0800120 // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use
121 // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB
122 // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then
123 // the names will mismatch. I think the correct solution is to have all GPs which need the
124 // uniform view matrix, they should upload the view matrix in their setData along with regular
125 // uniforms.
126 char prefix = 'u';
127 if ('u' == name[0]) {
128 prefix = '\0';
129 }
egdanielf3bace92015-11-06 06:57:12 -0800130 this->nameVariable(uni.fVariable.accessName(), prefix, name, mangleName);
joshualitt30ba4362014-08-21 20:18:45 -0700131 uni.fVariable.setArrayCount(count);
132 uni.fVisibility = visibility;
bsalomon422f56f2014-12-09 10:18:12 -0800133 uni.fVariable.setPrecision(precision);
joshualitt30ba4362014-08-21 20:18:45 -0700134
bsalomon49f085d2014-09-05 13:34:00 -0700135 if (outName) {
joshualitt30ba4362014-08-21 20:18:45 -0700136 *outName = uni.fVariable.c_str();
137 }
egdaniel018fb622015-10-28 07:26:40 -0700138 return GrGLSLProgramDataManager::UniformHandle(fUniforms.count() - 1);
joshualitt30ba4362014-08-21 20:18:45 -0700139}
140
egdaniel8dcdedc2015-11-11 06:27:20 -0800141void GrGLProgramBuilder::onAppendUniformDecls(ShaderVisibility visibility, SkString* out) const {
joshualitt30ba4362014-08-21 20:18:45 -0700142 for (int i = 0; i < fUniforms.count(); ++i) {
143 if (fUniforms[i].fVisibility & visibility) {
egdanielf5294392015-10-21 07:14:17 -0700144 fUniforms[i].fVariable.appendDecl(this->glslCaps(), out);
joshualitt30ba4362014-08-21 20:18:45 -0700145 out->append(";\n");
146 }
147 }
148}
149
egdanielf5294392015-10-21 07:14:17 -0700150const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const {
egdaniel8dcdedc2015-11-11 06:27:20 -0800151 return this->fGpu->ctxInfo().caps()->glslCaps();
egdanielf5294392015-10-21 07:14:17 -0700152}
153
joshualitt6c891102015-05-13 08:51:49 -0700154bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) {
joshualittabb52a12015-01-13 15:02:10 -0800155 // First we loop over all of the installed processors and collect coord transforms. These will
156 // be sent to the GrGLPrimitiveProcessor in its emitCode function
joshualitt6c891102015-05-13 08:51:49 -0700157 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
158 int totalTextures = primProc.numTextures();
159 const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits();
joshualittb2aa7cb2015-08-05 11:05:22 -0700160
bsalomonac856c92015-08-27 06:30:17 -0700161 for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) {
162 const GrFragmentProcessor& processor = this->pipeline().getFragmentProcessor(i);
joshualitt6c891102015-05-13 08:51:49 -0700163
joshualittb2aa7cb2015-08-05 11:05:22 -0700164 if (!primProc.hasTransformedLocalCoords()) {
bsalomonac856c92015-08-27 06:30:17 -0700165 SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back();
166 processor.gatherCoordTransforms(&procCoords);
joshualittb2aa7cb2015-08-05 11:05:22 -0700167 }
wangyix4b3050b2015-08-04 07:59:37 -0700168
bsalomonac856c92015-08-27 06:30:17 -0700169 totalTextures += processor.numTextures();
joshualitt6c891102015-05-13 08:51:49 -0700170 if (totalTextures >= maxTextureUnits) {
bsalomon682c2692015-05-22 14:01:46 -0700171 GrCapsDebugf(fGpu->caps(), "Program would use too many texture units\n");
joshualitt6c891102015-05-13 08:51:49 -0700172 return false;
173 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800174 }
175
joshualitt9b989322014-12-15 14:16:27 -0800176 this->emitAndInstallProc(primProc, inputColor, inputCoverage);
177
halcanary385fe4d2015-08-26 13:07:48 -0700178 fFragmentProcessors.reset(new GrGLInstalledFragProcs);
bsalomonac856c92015-08-27 06:30:17 -0700179 int numProcs = this->pipeline().numFragmentProcessors();
180 this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors(), inputColor);
181 this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(), numProcs,
bsalomon6be6f7c2015-02-26 13:05:21 -0800182 inputCoverage);
egdaniel8dd688b2015-01-22 10:16:09 -0800183 this->emitAndInstallXferProc(*this->pipeline().getXferProcessor(), *inputColor, *inputCoverage);
joshualitt6c891102015-05-13 08:51:49 -0700184 return true;
joshualitt47bb3822014-10-07 16:43:25 -0700185}
186
joshualitt2dd1ae02014-12-03 06:24:10 -0800187void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset,
188 int numProcs,
189 GrGLSLExpr4* inOut) {
bsalomonac856c92015-08-27 06:30:17 -0700190 for (int i = procOffset; i < numProcs; ++i) {
joshualitta5305a12014-10-10 17:47:00 -0700191 GrGLSLExpr4 output;
bsalomonac856c92015-08-27 06:30:17 -0700192 const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
193 this->emitAndInstallProc(fp, i, *inOut, &output);
joshualitta5305a12014-10-10 17:47:00 -0700194 *inOut = output;
joshualitt30ba4362014-08-21 20:18:45 -0700195 }
joshualitta5305a12014-10-10 17:47:00 -0700196}
joshualitt30ba4362014-08-21 20:18:45 -0700197
joshualitt2dd1ae02014-12-03 06:24:10 -0800198void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) {
199 // create var to hold stage result. If we already have a valid output name, just use that
200 // otherwise create a new mangled one. This name is only valid if we are reordering stages
201 // and have to tell stage exactly where to put its output.
202 SkString outName;
203 if (output->isValid()) {
204 outName = output->c_str();
205 } else {
206 this->nameVariable(&outName, '\0', baseName);
207 }
208 fFS.codeAppendf("vec4 %s;", outName.c_str());
209 *output = outName;
210}
211
joshualitta5305a12014-10-10 17:47:00 -0700212// TODO Processors cannot output zeros because an empty string is all 1s
213// the fix is to allow effects to take the GrGLSLExpr4 directly
bsalomonac856c92015-08-27 06:30:17 -0700214void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp,
joshualitta5305a12014-10-10 17:47:00 -0700215 int index,
joshualitta5305a12014-10-10 17:47:00 -0700216 const GrGLSLExpr4& input,
217 GrGLSLExpr4* output) {
218 // Program builders have a bit of state we need to clear with each effect
219 AutoStageAdvance adv(this);
joshualitt2dd1ae02014-12-03 06:24:10 -0800220 this->nameExpression(output, "output");
joshualitta5305a12014-10-10 17:47:00 -0700221
222 // Enclose custom code in a block to avoid namespace conflicts
223 SkString openBrace;
bsalomonac856c92015-08-27 06:30:17 -0700224 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name());
joshualitta5305a12014-10-10 17:47:00 -0700225 fFS.codeAppend(openBrace.c_str());
226
halcanary96fcdcc2015-08-27 07:41:13 -0700227 this->emitAndInstallProc(fp, index, output->c_str(), input.isOnes() ? nullptr : input.c_str());
joshualitta5305a12014-10-10 17:47:00 -0700228
229 fFS.codeAppend("}");
230}
231
joshualitt9b989322014-12-15 14:16:27 -0800232void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc,
joshualitt2dd1ae02014-12-03 06:24:10 -0800233 GrGLSLExpr4* outputColor,
234 GrGLSLExpr4* outputCoverage) {
235 // Program builders have a bit of state we need to clear with each effect
236 AutoStageAdvance adv(this);
237 this->nameExpression(outputColor, "outputColor");
238 this->nameExpression(outputCoverage, "outputCoverage");
239
240 // Enclose custom code in a block to avoid namespace conflicts
241 SkString openBrace;
242 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
243 fFS.codeAppend(openBrace.c_str());
wangyix150714f2015-07-23 08:02:09 -0700244 fVS.codeAppendf("// Primitive Processor %s\n", proc.name());
joshualitt2dd1ae02014-12-03 06:24:10 -0800245
246 this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str());
247
248 fFS.codeAppend("}");
249}
250
bsalomonac856c92015-08-27 06:30:17 -0700251void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp,
joshualittabb52a12015-01-13 15:02:10 -0800252 int index,
joshualitta5305a12014-10-10 17:47:00 -0700253 const char* outColor,
254 const char* inColor) {
halcanary385fe4d2015-08-26 13:07:48 -0700255 GrGLInstalledFragProc* ifp = new GrGLInstalledFragProc;
joshualitta5305a12014-10-10 17:47:00 -0700256
joshualitteb2a6762014-12-04 11:35:33 -0800257 ifp->fGLProc.reset(fp.createGLInstance());
joshualitta5305a12014-10-10 17:47:00 -0700258
egdaniel7dc4bd02015-10-29 07:57:01 -0700259 SkSTArray<4, GrGLSLTextureSampler> samplers(fp.numTextures());
joshualitta5305a12014-10-10 17:47:00 -0700260 this->emitSamplers(fp, &samplers, ifp);
261
wangyix7c157a92015-07-22 15:08:53 -0700262 GrGLFragmentProcessor::EmitArgs args(this, fp, outColor, inColor, fOutCoords[index], samplers);
263 ifp->fGLProc->emitCode(args);
joshualitta5305a12014-10-10 17:47:00 -0700264
265 // We have to check that effects and the code they emit are consistent, ie if an effect
266 // asks for dst color, then the emit code needs to follow suit
267 verify(fp);
268 fFragmentProcessors->fProcs.push_back(ifp);
269}
270
joshualitt9b989322014-12-15 14:16:27 -0800271void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp,
joshualitt2dd1ae02014-12-03 06:24:10 -0800272 const char* outColor,
273 const char* outCoverage) {
joshualitta5305a12014-10-10 17:47:00 -0700274 SkASSERT(!fGeometryProcessor);
halcanary385fe4d2015-08-26 13:07:48 -0700275 fGeometryProcessor = new GrGLInstalledGeoProc;
joshualitta5305a12014-10-10 17:47:00 -0700276
joshualitt465283c2015-09-11 08:19:35 -0700277 fGeometryProcessor->fGLProc.reset(gp.createGLInstance(*fGpu->glCaps().glslCaps()));
joshualitta5305a12014-10-10 17:47:00 -0700278
egdaniel7dc4bd02015-10-29 07:57:01 -0700279 SkSTArray<4, GrGLSLTextureSampler> samplers(gp.numTextures());
joshualitta5305a12014-10-10 17:47:00 -0700280 this->emitSamplers(gp, &samplers, fGeometryProcessor);
281
joshualitt465283c2015-09-11 08:19:35 -0700282 GrGLGeometryProcessor::EmitArgs args(this, gp, outColor, outCoverage, samplers,
joshualittabb52a12015-01-13 15:02:10 -0800283 fCoordTransforms, &fOutCoords);
joshualittc369e7c2014-10-22 10:56:26 -0700284 fGeometryProcessor->fGLProc->emitCode(args);
joshualitta5305a12014-10-10 17:47:00 -0700285
286 // We have to check that effects and the code they emit are consistent, ie if an effect
287 // asks for dst color, then the emit code needs to follow suit
288 verify(gp);
joshualitt30ba4362014-08-21 20:18:45 -0700289}
290
egdanielc2304142014-12-11 13:15:13 -0800291void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
292 const GrGLSLExpr4& colorIn,
293 const GrGLSLExpr4& coverageIn) {
294 // Program builders have a bit of state we need to clear with each effect
295 AutoStageAdvance adv(this);
296
297 SkASSERT(!fXferProcessor);
halcanary385fe4d2015-08-26 13:07:48 -0700298 fXferProcessor = new GrGLInstalledXferProc;
egdanielc2304142014-12-11 13:15:13 -0800299
300 fXferProcessor->fGLProc.reset(xp.createGLInstance());
301
302 // Enable dual source secondary output if we have one
303 if (xp.hasSecondaryOutput()) {
304 fFS.enableSecondaryOutput();
305 }
306
egdaniel8dcdedc2015-11-11 06:27:20 -0800307 if (this->glslCaps()->mustDeclareFragmentShaderOutput()) {
egdanielc2304142014-12-11 13:15:13 -0800308 fFS.enableCustomOutput();
309 }
310
311 SkString openBrace;
312 openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
313 fFS.codeAppend(openBrace.c_str());
314
egdaniel7dc4bd02015-10-29 07:57:01 -0700315 SkSTArray<4, GrGLSLTextureSampler> samplers(xp.numTextures());
egdanielc2304142014-12-11 13:15:13 -0800316 this->emitSamplers(xp, &samplers, fXferProcessor);
317
318 GrGLXferProcessor::EmitArgs args(this, xp, colorIn.c_str(), coverageIn.c_str(),
319 fFS.getPrimaryColorOutputName(),
320 fFS.getSecondaryColorOutputName(), samplers);
321 fXferProcessor->fGLProc->emitCode(args);
322
323 // We have to check that effects and the code they emit are consistent, ie if an effect
324 // asks for dst color, then the emit code needs to follow suit
325 verify(xp);
326 fFS.codeAppend("}");
327}
328
joshualitt9b989322014-12-15 14:16:27 -0800329void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
joshualitt47bb3822014-10-07 16:43:25 -0700330 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
joshualittfe1233c2014-10-07 12:16:35 -0700331}
332
egdanielc2304142014-12-11 13:15:13 -0800333void GrGLProgramBuilder::verify(const GrXferProcessor& xp) {
egdaniel71e236c2015-01-20 06:34:51 -0800334 SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
egdanielc2304142014-12-11 13:15:13 -0800335}
336
joshualitt47bb3822014-10-07 16:43:25 -0700337void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
338 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
joshualitt47bb3822014-10-07 16:43:25 -0700339}
340
joshualittabb52a12015-01-13 15:02:10 -0800341template <class Proc>
joshualitt47bb3822014-10-07 16:43:25 -0700342void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
egdaniel7dc4bd02015-10-29 07:57:01 -0700343 GrGLSLTextureSampler::TextureSamplerArray* outSamplers,
joshualittabb52a12015-01-13 15:02:10 -0800344 GrGLInstalledProc<Proc>* ip) {
cdalton42717652015-06-18 11:54:30 -0700345 SkDEBUGCODE(ip->fSamplersIdx = fSamplerUniforms.count();)
joshualitt47bb3822014-10-07 16:43:25 -0700346 int numTextures = processor.numTextures();
cdalton42717652015-06-18 11:54:30 -0700347 UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextures);
joshualitt23e280d2014-09-18 12:26:38 -0700348 SkString name;
349 for (int t = 0; t < numTextures; ++t) {
350 name.printf("Sampler%d", t);
cdalton42717652015-06-18 11:54:30 -0700351 localSamplerUniforms[t] = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
352 kSampler2D_GrSLType, kDefault_GrSLPrecision,
353 name.c_str());
egdaniel7dc4bd02015-10-29 07:57:01 -0700354 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLSLTextureSampler,
cdalton42717652015-06-18 11:54:30 -0700355 (localSamplerUniforms[t], processor.textureAccess(t)));
joshualitt23e280d2014-09-18 12:26:38 -0700356 }
357}
358
egdaniel2d721d32015-11-11 13:06:05 -0800359bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
egdaniel574a4c12015-11-02 06:22:44 -0800360 GrGLuint programId,
361 GrGLenum type,
362 SkTDArray<GrGLuint>* shaderIds) {
363 GrGLGpu* gpu = this->gpu();
364 GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
365 programId,
366 type,
367 shader.fCompilerStrings.begin(),
368 shader.fCompilerStringLengths.begin(),
369 shader.fCompilerStrings.count(),
370 gpu->stats());
371
372 if (!shaderId) {
373 return false;
374 }
375
376 *shaderIds->append() = shaderId;
377
378 return true;
379}
380
joshualitt47bb3822014-10-07 16:43:25 -0700381GrGLProgram* GrGLProgramBuilder::finalize() {
382 // verify we can get a program id
383 GrGLuint programID;
384 GL_CALL_RET(programID, CreateProgram());
385 if (0 == programID) {
halcanary96fcdcc2015-08-27 07:41:13 -0700386 return nullptr;
joshualitt30ba4362014-08-21 20:18:45 -0700387 }
388
joshualitt47bb3822014-10-07 16:43:25 -0700389 // compile shaders and bind attributes / uniforms
joshualitt30ba4362014-08-21 20:18:45 -0700390 SkTDArray<GrGLuint> shadersToDelete;
egdaniel574a4c12015-11-02 06:22:44 -0800391 fVS.finalize(kVertex_Visibility);
392 if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &shadersToDelete)) {
jvanverth50530632015-04-27 10:36:27 -0700393 this->cleanupProgram(programID, shadersToDelete);
halcanary96fcdcc2015-08-27 07:41:13 -0700394 return nullptr;
jvanverth50530632015-04-27 10:36:27 -0700395 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800396
jvanverth50530632015-04-27 10:36:27 -0700397 // NVPR actually requires a vertex shader to compile
398 bool useNvpr = primitiveProcessor().isPathRendering();
399 if (!useNvpr) {
egdaniel8dcdedc2015-11-11 06:27:20 -0800400 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
401
402 int vaCount = primProc.numAttribs();
403 for (int i = 0; i < vaCount; i++) {
404 GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
405 }
joshualitt47bb3822014-10-07 16:43:25 -0700406 }
joshualitt9b989322014-12-15 14:16:27 -0800407
egdaniel574a4c12015-11-02 06:22:44 -0800408 fFS.finalize(kFragment_Visibility);
409 if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete)) {
joshualitt9b989322014-12-15 14:16:27 -0800410 this->cleanupProgram(programID, shadersToDelete);
halcanary96fcdcc2015-08-27 07:41:13 -0700411 return nullptr;
joshualitt9b989322014-12-15 14:16:27 -0800412 }
413
kkinnunen7aedda52015-06-29 23:01:28 -0700414 this->bindProgramResourceLocations(programID);
415
joshualitt47bb3822014-10-07 16:43:25 -0700416 GL_CALL(LinkProgram(programID));
joshualitt30ba4362014-08-21 20:18:45 -0700417
418 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
cdalton1acea862015-06-02 13:05:52 -0700419 bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
joshualitt30ba4362014-08-21 20:18:45 -0700420#ifdef SK_DEBUG
421 checkLinked = true;
422#endif
423 if (checkLinked) {
joshualitt47bb3822014-10-07 16:43:25 -0700424 checkLinkStatus(programID);
joshualittfe1233c2014-10-07 12:16:35 -0700425 }
kkinnunen7aedda52015-06-29 23:01:28 -0700426 this->resolveProgramResourceLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700427
joshualitt47bb3822014-10-07 16:43:25 -0700428 this->cleanupShaders(shadersToDelete);
429
430 return this->createProgram(programID);
431}
432
kkinnunen7aedda52015-06-29 23:01:28 -0700433void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
joshualitt7bdd70a2015-10-01 06:28:11 -0700434 if (fGpu->glCaps().bindUniformLocationSupport()) {
kkinnunen7aedda52015-06-29 23:01:28 -0700435 int count = fUniforms.count();
436 for (int i = 0; i < count; ++i) {
437 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
438 fUniforms[i].fLocation = i;
439 }
joshualitt47bb3822014-10-07 16:43:25 -0700440 }
kkinnunen7aedda52015-06-29 23:01:28 -0700441
egdaniel8dcdedc2015-11-11 06:27:20 -0800442 const GrGLCaps& caps = this->gpu()->glCaps();
443 if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
444 GL_CALL(BindFragDataLocation(programID, 0,
egdaniel2d721d32015-11-11 13:06:05 -0800445 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800446 }
447 if (fFS.hasSecondaryOutput() && caps.glslCaps()->mustDeclareFragmentShaderOutput()) {
448 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
egdaniel2d721d32015-11-11 13:06:05 -0800449 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800450 }
joshualittd8dd47b2015-09-11 11:45:01 -0700451
452 // handle NVPR separable varyings
453 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
454 !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
455 return;
456 }
457 int count = fSeparableVaryingInfos.count();
458 for (int i = 0; i < count; ++i) {
459 GL_CALL(BindFragmentInputLocation(programID,
460 i,
461 fSeparableVaryingInfos[i].fVariable.c_str()));
462 fSeparableVaryingInfos[i].fLocation = i;
463 }
joshualitt47bb3822014-10-07 16:43:25 -0700464}
465
466bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
467 GrGLint linked = GR_GL_INIT_ZERO;
468 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
469 if (!linked) {
470 GrGLint infoLen = GR_GL_INIT_ZERO;
471 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
472 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
473 if (infoLen > 0) {
474 // retrieve length even though we don't need it to workaround
475 // bug in chrome cmd buffer param validation.
476 GrGLsizei length = GR_GL_INIT_ZERO;
477 GL_CALL(GetProgramInfoLog(programID,
478 infoLen+1,
479 &length,
480 (char*)log.get()));
kkinnunen297aaf92015-02-19 06:32:12 -0800481 SkDebugf("%s", (char*)log.get());
joshualitt47bb3822014-10-07 16:43:25 -0700482 }
483 SkDEBUGFAIL("Error linking program");
484 GL_CALL(DeleteProgram(programID));
485 programID = 0;
486 }
487 return SkToBool(linked);
488}
489
kkinnunen7aedda52015-06-29 23:01:28 -0700490void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
kkinnunen177519e2015-10-28 06:18:35 -0700491 if (!fGpu->glCaps().bindUniformLocationSupport()) {
kkinnunen7aedda52015-06-29 23:01:28 -0700492 int count = fUniforms.count();
493 for (int i = 0; i < count; ++i) {
494 GrGLint location;
495 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
496 fUniforms[i].fLocation = location;
497 }
kkinnunenec56e452014-08-25 22:21:16 -0700498 }
joshualittd8dd47b2015-09-11 11:45:01 -0700499
500 // handle NVPR separable varyings
501 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
502 !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
503 return;
504 }
505 int count = fSeparableVaryingInfos.count();
506 for (int i = 0; i < count; ++i) {
507 GrGLint location;
508 GL_CALL_RET(location,
509 GetProgramResourceLocation(programID,
510 GR_GL_FRAGMENT_INPUT,
511 fSeparableVaryingInfos[i].fVariable.c_str()));
512 fSeparableVaryingInfos[i].fLocation = location;
513 }
joshualitt30ba4362014-08-21 20:18:45 -0700514}
515
joshualitt47bb3822014-10-07 16:43:25 -0700516void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
517 GL_CALL(DeleteProgram(programID));
518 cleanupShaders(shaderIDs);
519}
520void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
521 for (int i = 0; i < shaderIDs.count(); ++i) {
522 GL_CALL(DeleteShader(shaderIDs[i]));
523 }
524}
525
526GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
halcanary385fe4d2015-08-26 13:07:48 -0700527 return new GrGLProgram(fGpu, this->desc(), fUniformHandles, programID, fUniforms,
joshualittd8dd47b2015-09-11 11:45:01 -0700528 fSeparableVaryingInfos,
halcanary385fe4d2015-08-26 13:07:48 -0700529 fGeometryProcessor, fXferProcessor, fFragmentProcessors.get(),
530 &fSamplerUniforms);
joshualitt47bb3822014-10-07 16:43:25 -0700531}
532
joshualitta5305a12014-10-10 17:47:00 -0700533///////////////////////////////////////////////////////////////////////////////////////////////////
joshualitt47bb3822014-10-07 16:43:25 -0700534
joshualitta5305a12014-10-10 17:47:00 -0700535GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
536 int numProcs = fProcs.count();
bsalomonac856c92015-08-27 06:30:17 -0700537 for (int i = 0; i < numProcs; ++i) {
538 delete fProcs[i];
joshualitt47bb3822014-10-07 16:43:25 -0700539 }
joshualitt30ba4362014-08-21 20:18:45 -0700540}