blob: c3e81fb358982c6ba2f1a8fa3ac1e06b1cdf7b7e [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"
joshualitt30ba4362014-08-21 20:18:45 -070018#include "SkTraceEvent.h"
joshualitte7afc2d2015-09-11 10:44:13 -070019#include "gl/GrGLGpu.h"
joshualitte7afc2d2015-09-11 10:44:13 -070020#include "gl/GrGLProgram.h"
21#include "gl/GrGLSLPrettyPrint.h"
egdaniel574a4c12015-11-02 06:22:44 -080022#include "gl/builders/GrGLShaderStringBuilder.h"
egdaniel64c47282015-11-13 06:54:19 -080023#include "glsl/GrGLSLFragmentProcessor.h"
egdaniele659a582015-11-13 09:55:43 -080024#include "glsl/GrGLSLGeometryProcessor.h"
egdaniel018fb622015-10-28 07:26:40 -070025#include "glsl/GrGLSLProgramDataManager.h"
egdanielfa4cc8b2015-11-13 08:34:52 -080026#include "glsl/GrGLSLXferProcessor.h"
joshualitt30ba4362014-08-21 20:18:45 -070027
joshualitt30ba4362014-08-21 20:18:45 -070028#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
29#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
30
egdaniel0e1853c2016-03-17 11:35:45 -070031GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrPipeline& pipeline,
32 const GrPrimitiveProcessor& primProc,
Ethan Nicholascae3a4c2017-02-02 10:43:58 -050033 const GrProgramDesc& desc,
egdaniel0e1853c2016-03-17 11:35:45 -070034 GrGLGpu* gpu) {
bsalomon3318ee72015-03-16 11:56:29 -070035 GrAutoLocaleSetter als("C");
36
joshualitt47bb3822014-10-07 16:43:25 -070037 // create a builder. This will be handed off to effects so they can use it to add
38 // uniforms, varyings, textures, etc
egdaniel0e1853c2016-03-17 11:35:45 -070039 GrGLProgramBuilder builder(gpu, pipeline, primProc, desc);
joshualitt47bb3822014-10-07 16:43:25 -070040
egdaniel37b4d862014-11-03 10:07:07 -080041 // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
joshualitt9b989322014-12-15 14:16:27 -080042 // seed correctly here
43 GrGLSLExpr4 inputColor;
44 GrGLSLExpr4 inputCoverage;
egdaniel37b4d862014-11-03 10:07:07 -080045
cdalton9c3f1432016-03-11 10:07:37 -080046 if (!builder.emitAndInstallProcs(&inputColor, &inputCoverage)) {
egdanielc1e71012016-01-20 07:53:51 -080047 builder.cleanupFragmentProcessors();
halcanary96fcdcc2015-08-27 07:41:13 -070048 return nullptr;
joshualitt6c891102015-05-13 08:51:49 -070049 }
joshualitt47bb3822014-10-07 16:43:25 -070050
egdanielc1e71012016-01-20 07:53:51 -080051 return builder.finalize();
joshualitt47bb3822014-10-07 16:43:25 -070052}
53
joshualitt47bb3822014-10-07 16:43:25 -070054/////////////////////////////////////////////////////////////////////////////
55
egdaniel0e1853c2016-03-17 11:35:45 -070056GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
57 const GrPipeline& pipeline,
58 const GrPrimitiveProcessor& primProc,
Ethan Nicholascae3a4c2017-02-02 10:43:58 -050059 const GrProgramDesc& desc)
egdaniel0e1853c2016-03-17 11:35:45 -070060 : INHERITED(pipeline, primProc, desc)
joshualitt30ba4362014-08-21 20:18:45 -070061 , fGpu(gpu)
egdaniel7ea439b2015-12-03 09:20:44 -080062 , fVaryingHandler(this)
63 , fUniformHandler(this) {
joshualitt30ba4362014-08-21 20:18:45 -070064}
65
egdanielfa896322016-01-13 12:19:30 -080066const GrCaps* GrGLProgramBuilder::caps() const {
67 return fGpu->caps();
68}
69
egdaniel2d721d32015-11-11 13:06:05 -080070bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
egdaniel574a4c12015-11-02 06:22:44 -080071 GrGLuint programId,
72 GrGLenum type,
Ethan Nicholas941e7e22016-12-12 15:33:30 -050073 SkTDArray<GrGLuint>* shaderIds,
74 const SkSL::Program::Settings& settings,
75 SkSL::Program::Inputs* outInputs) {
egdaniel574a4c12015-11-02 06:22:44 -080076 GrGLGpu* gpu = this->gpu();
77 GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
78 programId,
79 type,
80 shader.fCompilerStrings.begin(),
81 shader.fCompilerStringLengths.begin(),
82 shader.fCompilerStrings.count(),
Ethan Nicholas941e7e22016-12-12 15:33:30 -050083 gpu->stats(),
84 settings,
85 outInputs);
egdaniel574a4c12015-11-02 06:22:44 -080086
87 if (!shaderId) {
88 return false;
89 }
90
91 *shaderIds->append() = shaderId;
92
93 return true;
94}
95
joshualitt47bb3822014-10-07 16:43:25 -070096GrGLProgram* GrGLProgramBuilder::finalize() {
97 // verify we can get a program id
98 GrGLuint programID;
99 GL_CALL_RET(programID, CreateProgram());
100 if (0 == programID) {
egdanielfa896322016-01-13 12:19:30 -0800101 this->cleanupFragmentProcessors();
halcanary96fcdcc2015-08-27 07:41:13 -0700102 return nullptr;
joshualitt30ba4362014-08-21 20:18:45 -0700103 }
104
egdaniel9f1d4152016-02-10 09:50:38 -0800105 this->finalizeShaders();
106
joshualitt47bb3822014-10-07 16:43:25 -0700107 // compile shaders and bind attributes / uniforms
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500108 SkSL::Program::Settings settings;
109 settings.fCaps = this->gpu()->glCaps().shaderCaps();
110 settings.fFlipY = this->pipeline().getRenderTarget()->origin() != kTopLeft_GrSurfaceOrigin;
111 SkSL::Program::Inputs inputs;
joshualitt30ba4362014-08-21 20:18:45 -0700112 SkTDArray<GrGLuint> shadersToDelete;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500113 if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &shadersToDelete,
114 settings, &inputs)) {
jvanverth50530632015-04-27 10:36:27 -0700115 this->cleanupProgram(programID, shadersToDelete);
halcanary96fcdcc2015-08-27 07:41:13 -0700116 return nullptr;
jvanverth50530632015-04-27 10:36:27 -0700117 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800118
jvanverth50530632015-04-27 10:36:27 -0700119 // NVPR actually requires a vertex shader to compile
csmartdalton276cc412016-11-21 11:55:00 -0700120 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
121 bool useNvpr = primProc.isPathRendering();
jvanverth50530632015-04-27 10:36:27 -0700122 if (!useNvpr) {
egdaniel8dcdedc2015-11-11 06:27:20 -0800123 int vaCount = primProc.numAttribs();
124 for (int i = 0; i < vaCount; i++) {
125 GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
126 }
joshualitt47bb3822014-10-07 16:43:25 -0700127 }
joshualitt9b989322014-12-15 14:16:27 -0800128
csmartdalton276cc412016-11-21 11:55:00 -0700129 if (primProc.willUseGeoShader() &&
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500130 !this->compileAndAttachShaders(fGS, programID, GR_GL_GEOMETRY_SHADER, &shadersToDelete,
131 settings, &inputs)) {
csmartdalton276cc412016-11-21 11:55:00 -0700132 this->cleanupProgram(programID, shadersToDelete);
133 return nullptr;
134 }
135
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500136 if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete,
137 settings, &inputs)) {
joshualitt9b989322014-12-15 14:16:27 -0800138 this->cleanupProgram(programID, shadersToDelete);
halcanary96fcdcc2015-08-27 07:41:13 -0700139 return nullptr;
joshualitt9b989322014-12-15 14:16:27 -0800140 }
141
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500142 if (inputs.fRTHeight) {
143 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
144 }
145
kkinnunen7aedda52015-06-29 23:01:28 -0700146 this->bindProgramResourceLocations(programID);
147
joshualitt47bb3822014-10-07 16:43:25 -0700148 GL_CALL(LinkProgram(programID));
joshualitt30ba4362014-08-21 20:18:45 -0700149
150 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
cdalton1acea862015-06-02 13:05:52 -0700151 bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
joshualitt30ba4362014-08-21 20:18:45 -0700152#ifdef SK_DEBUG
153 checkLinked = true;
154#endif
155 if (checkLinked) {
joshualitt47bb3822014-10-07 16:43:25 -0700156 checkLinkStatus(programID);
joshualittfe1233c2014-10-07 12:16:35 -0700157 }
kkinnunen7aedda52015-06-29 23:01:28 -0700158 this->resolveProgramResourceLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700159
joshualitt47bb3822014-10-07 16:43:25 -0700160 this->cleanupShaders(shadersToDelete);
161
162 return this->createProgram(programID);
163}
164
kkinnunen7aedda52015-06-29 23:01:28 -0700165void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800166 fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
kkinnunen7aedda52015-06-29 23:01:28 -0700167
egdaniel8dcdedc2015-11-11 06:27:20 -0800168 const GrGLCaps& caps = this->gpu()->glCaps();
169 if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
170 GL_CALL(BindFragDataLocation(programID, 0,
egdaniel2d721d32015-11-11 13:06:05 -0800171 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800172 }
Brian Salomon1edc5b92016-11-29 13:43:46 -0500173 if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
egdaniel8dcdedc2015-11-11 06:27:20 -0800174 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
egdaniel2d721d32015-11-11 13:06:05 -0800175 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800176 }
joshualittd8dd47b2015-09-11 11:45:01 -0700177
178 // handle NVPR separable varyings
179 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
180 !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
181 return;
182 }
egdaniel0eafe792015-11-20 14:01:22 -0800183 int count = fVaryingHandler.fPathProcVaryingInfos.count();
joshualittd8dd47b2015-09-11 11:45:01 -0700184 for (int i = 0; i < count; ++i) {
egdaniel0eafe792015-11-20 14:01:22 -0800185 GL_CALL(BindFragmentInputLocation(programID, i,
186 fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
187 fVaryingHandler.fPathProcVaryingInfos[i].fLocation = i;
joshualittd8dd47b2015-09-11 11:45:01 -0700188 }
joshualitt47bb3822014-10-07 16:43:25 -0700189}
190
191bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
192 GrGLint linked = GR_GL_INIT_ZERO;
193 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
194 if (!linked) {
195 GrGLint infoLen = GR_GL_INIT_ZERO;
196 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
197 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
198 if (infoLen > 0) {
199 // retrieve length even though we don't need it to workaround
200 // bug in chrome cmd buffer param validation.
201 GrGLsizei length = GR_GL_INIT_ZERO;
202 GL_CALL(GetProgramInfoLog(programID,
203 infoLen+1,
204 &length,
205 (char*)log.get()));
kkinnunen297aaf92015-02-19 06:32:12 -0800206 SkDebugf("%s", (char*)log.get());
joshualitt47bb3822014-10-07 16:43:25 -0700207 }
208 SkDEBUGFAIL("Error linking program");
209 GL_CALL(DeleteProgram(programID));
210 programID = 0;
211 }
212 return SkToBool(linked);
213}
214
kkinnunen7aedda52015-06-29 23:01:28 -0700215void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800216 fUniformHandler.getUniformLocations(programID, fGpu->glCaps());
joshualittd8dd47b2015-09-11 11:45:01 -0700217
218 // handle NVPR separable varyings
219 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
kkinnunen7bdb05d2016-01-25 00:47:23 -0800220 fGpu->glPathRendering()->shouldBindFragmentInputs()) {
joshualittd8dd47b2015-09-11 11:45:01 -0700221 return;
222 }
egdaniel0eafe792015-11-20 14:01:22 -0800223 int count = fVaryingHandler.fPathProcVaryingInfos.count();
joshualittd8dd47b2015-09-11 11:45:01 -0700224 for (int i = 0; i < count; ++i) {
225 GrGLint location;
egdaniel0eafe792015-11-20 14:01:22 -0800226 GL_CALL_RET(location, GetProgramResourceLocation(
227 programID,
228 GR_GL_FRAGMENT_INPUT,
229 fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
230 fVaryingHandler.fPathProcVaryingInfos[i].fLocation = location;
joshualittd8dd47b2015-09-11 11:45:01 -0700231 }
joshualitt30ba4362014-08-21 20:18:45 -0700232}
233
joshualitt47bb3822014-10-07 16:43:25 -0700234void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
235 GL_CALL(DeleteProgram(programID));
egdanielfa896322016-01-13 12:19:30 -0800236 this->cleanupShaders(shaderIDs);
237 this->cleanupFragmentProcessors();
joshualitt47bb3822014-10-07 16:43:25 -0700238}
239void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
240 for (int i = 0; i < shaderIDs.count(); ++i) {
241 GL_CALL(DeleteShader(shaderIDs[i]));
242 }
243}
244
245GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800246 return new GrGLProgram(fGpu,
Ethan Nicholascae3a4c2017-02-02 10:43:58 -0500247 this->desc(),
egdaniel7ea439b2015-12-03 09:20:44 -0800248 fUniformHandles,
249 programID,
250 fUniformHandler.fUniforms,
egdaniel09aa1fc2016-04-20 07:09:46 -0700251 fUniformHandler.fSamplers,
Brian Salomonf9f45122016-11-29 11:59:17 -0500252 fUniformHandler.fImageStorages,
egdaniel0eafe792015-11-20 14:01:22 -0800253 fVaryingHandler.fPathProcVaryingInfos,
egdaniel7ea439b2015-12-03 09:20:44 -0800254 fGeometryProcessor,
255 fXferProcessor,
egdaniel09aa1fc2016-04-20 07:09:46 -0700256 fFragmentProcessors);
joshualitt47bb3822014-10-07 16:43:25 -0700257}