blob: 79cb2cab83c474ab9576b87c7180164aa1a5b0f1 [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"
egdaniel5d8f69f2016-09-07 07:24:12 -070013#include "GrProgramDesc.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050014#include "GrShaderCaps.h"
bsalomon7f9b2e42016-01-12 13:29:26 -080015#include "GrSwizzle.h"
joshualitt30ba4362014-08-21 20:18:45 -070016#include "GrTexture.h"
Hal Canary95e3c052017-01-11 12:44:43 -050017#include "SkAutoMalloc.h"
Derek Sollenberger488f0d62017-03-03 15:48:33 -050018#include "SkATrace.h"
joshualitt30ba4362014-08-21 20:18:45 -070019#include "SkTraceEvent.h"
joshualitte7afc2d2015-09-11 10:44:13 -070020#include "gl/GrGLGpu.h"
joshualitte7afc2d2015-09-11 10:44:13 -070021#include "gl/GrGLProgram.h"
22#include "gl/GrGLSLPrettyPrint.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
egdaniel0e1853c2016-03-17 11:35:45 -070032GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrPipeline& pipeline,
33 const GrPrimitiveProcessor& primProc,
Ethan Nicholas38657112017-02-09 17:01:22 -050034 GrProgramDesc* desc,
egdaniel0e1853c2016-03-17 11:35:45 -070035 GrGLGpu* gpu) {
Robert Phillipsa91e0b72017-05-01 13:12:20 -040036 SkASSERT(!pipeline.isBad() && !primProc.isBad());
37
Derek Sollenberger488f0d62017-03-03 15:48:33 -050038 ATRACE_ANDROID_FRAMEWORK("Shader Compile");
bsalomon3318ee72015-03-16 11:56:29 -070039 GrAutoLocaleSetter als("C");
40
joshualitt47bb3822014-10-07 16:43:25 -070041 // create a builder. This will be handed off to effects so they can use it to add
42 // uniforms, varyings, textures, etc
egdaniel0e1853c2016-03-17 11:35:45 -070043 GrGLProgramBuilder builder(gpu, pipeline, primProc, desc);
joshualitt47bb3822014-10-07 16:43:25 -070044
Ethan Nicholas2983f402017-05-08 09:36:08 -040045 if (!builder.emitAndInstallProcs()) {
egdanielc1e71012016-01-20 07:53:51 -080046 builder.cleanupFragmentProcessors();
halcanary96fcdcc2015-08-27 07:41:13 -070047 return nullptr;
joshualitt6c891102015-05-13 08:51:49 -070048 }
joshualitt47bb3822014-10-07 16:43:25 -070049
egdanielc1e71012016-01-20 07:53:51 -080050 return builder.finalize();
joshualitt47bb3822014-10-07 16:43:25 -070051}
52
joshualitt47bb3822014-10-07 16:43:25 -070053/////////////////////////////////////////////////////////////////////////////
54
egdaniel0e1853c2016-03-17 11:35:45 -070055GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
56 const GrPipeline& pipeline,
57 const GrPrimitiveProcessor& primProc,
Ethan Nicholas38657112017-02-09 17:01:22 -050058 GrProgramDesc* desc)
egdaniel0e1853c2016-03-17 11:35:45 -070059 : INHERITED(pipeline, primProc, desc)
joshualitt30ba4362014-08-21 20:18:45 -070060 , fGpu(gpu)
egdaniel7ea439b2015-12-03 09:20:44 -080061 , fVaryingHandler(this)
62 , fUniformHandler(this) {
joshualitt30ba4362014-08-21 20:18:45 -070063}
64
egdanielfa896322016-01-13 12:19:30 -080065const GrCaps* GrGLProgramBuilder::caps() const {
66 return fGpu->caps();
67}
68
egdaniel2d721d32015-11-11 13:06:05 -080069bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
egdaniel574a4c12015-11-02 06:22:44 -080070 GrGLuint programId,
71 GrGLenum type,
Ethan Nicholas941e7e22016-12-12 15:33:30 -050072 SkTDArray<GrGLuint>* shaderIds,
73 const SkSL::Program::Settings& settings,
74 SkSL::Program::Inputs* outInputs) {
egdaniel574a4c12015-11-02 06:22:44 -080075 GrGLGpu* gpu = this->gpu();
76 GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
77 programId,
78 type,
79 shader.fCompilerStrings.begin(),
80 shader.fCompilerStringLengths.begin(),
81 shader.fCompilerStrings.count(),
Ethan Nicholas941e7e22016-12-12 15:33:30 -050082 gpu->stats(),
83 settings,
84 outInputs);
egdaniel574a4c12015-11-02 06:22:44 -080085
86 if (!shaderId) {
87 return false;
88 }
89
90 *shaderIds->append() = shaderId;
Ethan Nicholas38657112017-02-09 17:01:22 -050091 if (outInputs->fFlipY) {
92 GrProgramDesc* d = this->desc();
93 d->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
94 this->pipeline().getRenderTarget()->origin()));
95 d->finalize();
96 }
egdaniel574a4c12015-11-02 06:22:44 -080097
98 return true;
99}
100
joshualitt47bb3822014-10-07 16:43:25 -0700101GrGLProgram* GrGLProgramBuilder::finalize() {
102 // verify we can get a program id
103 GrGLuint programID;
104 GL_CALL_RET(programID, CreateProgram());
105 if (0 == programID) {
egdanielfa896322016-01-13 12:19:30 -0800106 this->cleanupFragmentProcessors();
halcanary96fcdcc2015-08-27 07:41:13 -0700107 return nullptr;
joshualitt30ba4362014-08-21 20:18:45 -0700108 }
109
egdaniel9f1d4152016-02-10 09:50:38 -0800110 this->finalizeShaders();
111
joshualitt47bb3822014-10-07 16:43:25 -0700112 // compile shaders and bind attributes / uniforms
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500113 SkSL::Program::Settings settings;
114 settings.fCaps = this->gpu()->glCaps().shaderCaps();
115 settings.fFlipY = this->pipeline().getRenderTarget()->origin() != kTopLeft_GrSurfaceOrigin;
116 SkSL::Program::Inputs inputs;
joshualitt30ba4362014-08-21 20:18:45 -0700117 SkTDArray<GrGLuint> shadersToDelete;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500118 if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &shadersToDelete,
119 settings, &inputs)) {
jvanverth50530632015-04-27 10:36:27 -0700120 this->cleanupProgram(programID, shadersToDelete);
halcanary96fcdcc2015-08-27 07:41:13 -0700121 return nullptr;
jvanverth50530632015-04-27 10:36:27 -0700122 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800123
jvanverth50530632015-04-27 10:36:27 -0700124 // NVPR actually requires a vertex shader to compile
csmartdalton276cc412016-11-21 11:55:00 -0700125 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
126 bool useNvpr = primProc.isPathRendering();
jvanverth50530632015-04-27 10:36:27 -0700127 if (!useNvpr) {
egdaniel8dcdedc2015-11-11 06:27:20 -0800128 int vaCount = primProc.numAttribs();
129 for (int i = 0; i < vaCount; i++) {
130 GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
131 }
joshualitt47bb3822014-10-07 16:43:25 -0700132 }
joshualitt9b989322014-12-15 14:16:27 -0800133
csmartdalton276cc412016-11-21 11:55:00 -0700134 if (primProc.willUseGeoShader() &&
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500135 !this->compileAndAttachShaders(fGS, programID, GR_GL_GEOMETRY_SHADER, &shadersToDelete,
136 settings, &inputs)) {
csmartdalton276cc412016-11-21 11:55:00 -0700137 this->cleanupProgram(programID, shadersToDelete);
138 return nullptr;
139 }
140
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500141 if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete,
142 settings, &inputs)) {
joshualitt9b989322014-12-15 14:16:27 -0800143 this->cleanupProgram(programID, shadersToDelete);
halcanary96fcdcc2015-08-27 07:41:13 -0700144 return nullptr;
joshualitt9b989322014-12-15 14:16:27 -0800145 }
146
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500147 if (inputs.fRTHeight) {
148 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
149 }
150
kkinnunen7aedda52015-06-29 23:01:28 -0700151 this->bindProgramResourceLocations(programID);
152
joshualitt47bb3822014-10-07 16:43:25 -0700153 GL_CALL(LinkProgram(programID));
joshualitt30ba4362014-08-21 20:18:45 -0700154
155 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
cdalton1acea862015-06-02 13:05:52 -0700156 bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
joshualitt30ba4362014-08-21 20:18:45 -0700157#ifdef SK_DEBUG
158 checkLinked = true;
159#endif
160 if (checkLinked) {
joshualitt47bb3822014-10-07 16:43:25 -0700161 checkLinkStatus(programID);
joshualittfe1233c2014-10-07 12:16:35 -0700162 }
kkinnunen7aedda52015-06-29 23:01:28 -0700163 this->resolveProgramResourceLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700164
joshualitt47bb3822014-10-07 16:43:25 -0700165 this->cleanupShaders(shadersToDelete);
166
167 return this->createProgram(programID);
168}
169
kkinnunen7aedda52015-06-29 23:01:28 -0700170void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800171 fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
kkinnunen7aedda52015-06-29 23:01:28 -0700172
egdaniel8dcdedc2015-11-11 06:27:20 -0800173 const GrGLCaps& caps = this->gpu()->glCaps();
174 if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
175 GL_CALL(BindFragDataLocation(programID, 0,
egdaniel2d721d32015-11-11 13:06:05 -0800176 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800177 }
Brian Salomon1edc5b92016-11-29 13:43:46 -0500178 if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
egdaniel8dcdedc2015-11-11 06:27:20 -0800179 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
egdaniel2d721d32015-11-11 13:06:05 -0800180 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800181 }
joshualittd8dd47b2015-09-11 11:45:01 -0700182
183 // handle NVPR separable varyings
184 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
185 !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
186 return;
187 }
egdaniel0eafe792015-11-20 14:01:22 -0800188 int count = fVaryingHandler.fPathProcVaryingInfos.count();
joshualittd8dd47b2015-09-11 11:45:01 -0700189 for (int i = 0; i < count; ++i) {
egdaniel0eafe792015-11-20 14:01:22 -0800190 GL_CALL(BindFragmentInputLocation(programID, i,
191 fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
192 fVaryingHandler.fPathProcVaryingInfos[i].fLocation = i;
joshualittd8dd47b2015-09-11 11:45:01 -0700193 }
joshualitt47bb3822014-10-07 16:43:25 -0700194}
195
196bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
197 GrGLint linked = GR_GL_INIT_ZERO;
198 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
199 if (!linked) {
200 GrGLint infoLen = GR_GL_INIT_ZERO;
201 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
202 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
203 if (infoLen > 0) {
204 // retrieve length even though we don't need it to workaround
205 // bug in chrome cmd buffer param validation.
206 GrGLsizei length = GR_GL_INIT_ZERO;
207 GL_CALL(GetProgramInfoLog(programID,
208 infoLen+1,
209 &length,
210 (char*)log.get()));
kkinnunen297aaf92015-02-19 06:32:12 -0800211 SkDebugf("%s", (char*)log.get());
joshualitt47bb3822014-10-07 16:43:25 -0700212 }
213 SkDEBUGFAIL("Error linking program");
214 GL_CALL(DeleteProgram(programID));
215 programID = 0;
216 }
217 return SkToBool(linked);
218}
219
kkinnunen7aedda52015-06-29 23:01:28 -0700220void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800221 fUniformHandler.getUniformLocations(programID, fGpu->glCaps());
joshualittd8dd47b2015-09-11 11:45:01 -0700222
223 // handle NVPR separable varyings
224 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
kkinnunen7bdb05d2016-01-25 00:47:23 -0800225 fGpu->glPathRendering()->shouldBindFragmentInputs()) {
joshualittd8dd47b2015-09-11 11:45:01 -0700226 return;
227 }
egdaniel0eafe792015-11-20 14:01:22 -0800228 int count = fVaryingHandler.fPathProcVaryingInfos.count();
joshualittd8dd47b2015-09-11 11:45:01 -0700229 for (int i = 0; i < count; ++i) {
230 GrGLint location;
egdaniel0eafe792015-11-20 14:01:22 -0800231 GL_CALL_RET(location, GetProgramResourceLocation(
232 programID,
233 GR_GL_FRAGMENT_INPUT,
234 fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
235 fVaryingHandler.fPathProcVaryingInfos[i].fLocation = location;
joshualittd8dd47b2015-09-11 11:45:01 -0700236 }
joshualitt30ba4362014-08-21 20:18:45 -0700237}
238
joshualitt47bb3822014-10-07 16:43:25 -0700239void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
240 GL_CALL(DeleteProgram(programID));
egdanielfa896322016-01-13 12:19:30 -0800241 this->cleanupShaders(shaderIDs);
242 this->cleanupFragmentProcessors();
joshualitt47bb3822014-10-07 16:43:25 -0700243}
244void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
245 for (int i = 0; i < shaderIDs.count(); ++i) {
246 GL_CALL(DeleteShader(shaderIDs[i]));
247 }
248}
249
250GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800251 return new GrGLProgram(fGpu,
Ethan Nicholas38657112017-02-09 17:01:22 -0500252 *this->desc(),
egdaniel7ea439b2015-12-03 09:20:44 -0800253 fUniformHandles,
254 programID,
255 fUniformHandler.fUniforms,
egdaniel09aa1fc2016-04-20 07:09:46 -0700256 fUniformHandler.fSamplers,
Greg Danielbc5d4d72017-05-05 10:28:42 -0400257 fUniformHandler.fTexelBuffers,
Brian Salomonf9f45122016-11-29 11:59:17 -0500258 fUniformHandler.fImageStorages,
egdaniel0eafe792015-11-20 14:01:22 -0800259 fVaryingHandler.fPathProcVaryingInfos,
egdaniel7ea439b2015-12-03 09:20:44 -0800260 fGeometryProcessor,
261 fXferProcessor,
egdaniel09aa1fc2016-04-20 07:09:46 -0700262 fFragmentProcessors);
joshualitt47bb3822014-10-07 16:43:25 -0700263}