blob: 1c5cf25eb78903b02f2d000e7b56814c2cbb64d2 [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"
bsalomon7f9b2e42016-01-12 13:29:26 -080013#include "GrSwizzle.h"
joshualitt30ba4362014-08-21 20:18:45 -070014#include "GrTexture.h"
joshualitt30ba4362014-08-21 20:18:45 -070015#include "SkRTConf.h"
16#include "SkTraceEvent.h"
joshualitte7afc2d2015-09-11 10:44:13 -070017#include "gl/GrGLGpu.h"
joshualitte7afc2d2015-09-11 10:44:13 -070018#include "gl/GrGLProgram.h"
19#include "gl/GrGLSLPrettyPrint.h"
egdaniel574a4c12015-11-02 06:22:44 -080020#include "gl/builders/GrGLShaderStringBuilder.h"
joshualitte7afc2d2015-09-11 10:44:13 -070021#include "glsl/GrGLSLCaps.h"
egdaniel64c47282015-11-13 06:54:19 -080022#include "glsl/GrGLSLFragmentProcessor.h"
egdaniele659a582015-11-13 09:55:43 -080023#include "glsl/GrGLSLGeometryProcessor.h"
egdaniel018fb622015-10-28 07:26:40 -070024#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7dc4bd02015-10-29 07:57:01 -070025#include "glsl/GrGLSLTextureSampler.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
joshualitt873ad0e2015-01-20 09:08:51 -080031GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gpu) {
bsalomon3318ee72015-03-16 11:56:29 -070032 GrAutoLocaleSetter als("C");
33
joshualitt47bb3822014-10-07 16:43:25 -070034 // create a builder. This will be handed off to effects so they can use it to add
35 // uniforms, varyings, textures, etc
egdanielc1e71012016-01-20 07:53:51 -080036 GrGLProgramBuilder builder(gpu, args);
joshualitt47bb3822014-10-07 16:43:25 -070037
egdaniel37b4d862014-11-03 10:07:07 -080038 // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
joshualitt9b989322014-12-15 14:16:27 -080039 // seed correctly here
40 GrGLSLExpr4 inputColor;
41 GrGLSLExpr4 inputCoverage;
egdaniel37b4d862014-11-03 10:07:07 -080042
cdalton9c3f1432016-03-11 10:07:37 -080043 if (!builder.emitAndInstallProcs(&inputColor, &inputCoverage)) {
egdanielc1e71012016-01-20 07:53:51 -080044 builder.cleanupFragmentProcessors();
halcanary96fcdcc2015-08-27 07:41:13 -070045 return nullptr;
joshualitt6c891102015-05-13 08:51:49 -070046 }
joshualitt47bb3822014-10-07 16:43:25 -070047
egdanielc1e71012016-01-20 07:53:51 -080048 return builder.finalize();
joshualitt47bb3822014-10-07 16:43:25 -070049}
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)
joshualitt30ba4362014-08-21 20:18:45 -070055 , fGpu(gpu)
egdaniel7ea439b2015-12-03 09:20:44 -080056 , fVaryingHandler(this)
57 , fUniformHandler(this) {
joshualitt30ba4362014-08-21 20:18:45 -070058}
59
egdanielfa896322016-01-13 12:19:30 -080060const GrCaps* GrGLProgramBuilder::caps() const {
61 return fGpu->caps();
62}
63
egdanielf5294392015-10-21 07:14:17 -070064const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const {
egdanielfa896322016-01-13 12:19:30 -080065 return fGpu->ctxInfo().caps()->glslCaps();
joshualitt47bb3822014-10-07 16:43:25 -070066}
67
egdaniel2d721d32015-11-11 13:06:05 -080068bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
egdaniel574a4c12015-11-02 06:22:44 -080069 GrGLuint programId,
70 GrGLenum type,
71 SkTDArray<GrGLuint>* shaderIds) {
72 GrGLGpu* gpu = this->gpu();
73 GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
74 programId,
75 type,
76 shader.fCompilerStrings.begin(),
77 shader.fCompilerStringLengths.begin(),
78 shader.fCompilerStrings.count(),
79 gpu->stats());
80
81 if (!shaderId) {
82 return false;
83 }
84
85 *shaderIds->append() = shaderId;
86
87 return true;
88}
89
joshualitt47bb3822014-10-07 16:43:25 -070090GrGLProgram* GrGLProgramBuilder::finalize() {
91 // verify we can get a program id
92 GrGLuint programID;
93 GL_CALL_RET(programID, CreateProgram());
94 if (0 == programID) {
egdanielfa896322016-01-13 12:19:30 -080095 this->cleanupFragmentProcessors();
halcanary96fcdcc2015-08-27 07:41:13 -070096 return nullptr;
joshualitt30ba4362014-08-21 20:18:45 -070097 }
98
egdaniel9f1d4152016-02-10 09:50:38 -080099 this->finalizeShaders();
100
joshualitt47bb3822014-10-07 16:43:25 -0700101 // compile shaders and bind attributes / uniforms
joshualitt30ba4362014-08-21 20:18:45 -0700102 SkTDArray<GrGLuint> shadersToDelete;
egdaniel574a4c12015-11-02 06:22:44 -0800103 if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &shadersToDelete)) {
jvanverth50530632015-04-27 10:36:27 -0700104 this->cleanupProgram(programID, shadersToDelete);
halcanary96fcdcc2015-08-27 07:41:13 -0700105 return nullptr;
jvanverth50530632015-04-27 10:36:27 -0700106 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800107
jvanverth50530632015-04-27 10:36:27 -0700108 // NVPR actually requires a vertex shader to compile
109 bool useNvpr = primitiveProcessor().isPathRendering();
110 if (!useNvpr) {
egdaniel8dcdedc2015-11-11 06:27:20 -0800111 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
112
113 int vaCount = primProc.numAttribs();
114 for (int i = 0; i < vaCount; i++) {
115 GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
116 }
joshualitt47bb3822014-10-07 16:43:25 -0700117 }
joshualitt9b989322014-12-15 14:16:27 -0800118
egdaniel574a4c12015-11-02 06:22:44 -0800119 if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete)) {
joshualitt9b989322014-12-15 14:16:27 -0800120 this->cleanupProgram(programID, shadersToDelete);
halcanary96fcdcc2015-08-27 07:41:13 -0700121 return nullptr;
joshualitt9b989322014-12-15 14:16:27 -0800122 }
123
kkinnunen7aedda52015-06-29 23:01:28 -0700124 this->bindProgramResourceLocations(programID);
125
joshualitt47bb3822014-10-07 16:43:25 -0700126 GL_CALL(LinkProgram(programID));
joshualitt30ba4362014-08-21 20:18:45 -0700127
128 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
cdalton1acea862015-06-02 13:05:52 -0700129 bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
joshualitt30ba4362014-08-21 20:18:45 -0700130#ifdef SK_DEBUG
131 checkLinked = true;
132#endif
133 if (checkLinked) {
joshualitt47bb3822014-10-07 16:43:25 -0700134 checkLinkStatus(programID);
joshualittfe1233c2014-10-07 12:16:35 -0700135 }
kkinnunen7aedda52015-06-29 23:01:28 -0700136 this->resolveProgramResourceLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700137
joshualitt47bb3822014-10-07 16:43:25 -0700138 this->cleanupShaders(shadersToDelete);
139
140 return this->createProgram(programID);
141}
142
kkinnunen7aedda52015-06-29 23:01:28 -0700143void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800144 fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
kkinnunen7aedda52015-06-29 23:01:28 -0700145
egdaniel8dcdedc2015-11-11 06:27:20 -0800146 const GrGLCaps& caps = this->gpu()->glCaps();
147 if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
148 GL_CALL(BindFragDataLocation(programID, 0,
egdaniel2d721d32015-11-11 13:06:05 -0800149 GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800150 }
151 if (fFS.hasSecondaryOutput() && caps.glslCaps()->mustDeclareFragmentShaderOutput()) {
152 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
egdaniel2d721d32015-11-11 13:06:05 -0800153 GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
egdaniel8dcdedc2015-11-11 06:27:20 -0800154 }
joshualittd8dd47b2015-09-11 11:45:01 -0700155
156 // handle NVPR separable varyings
157 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
158 !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
159 return;
160 }
egdaniel0eafe792015-11-20 14:01:22 -0800161 int count = fVaryingHandler.fPathProcVaryingInfos.count();
joshualittd8dd47b2015-09-11 11:45:01 -0700162 for (int i = 0; i < count; ++i) {
egdaniel0eafe792015-11-20 14:01:22 -0800163 GL_CALL(BindFragmentInputLocation(programID, i,
164 fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
165 fVaryingHandler.fPathProcVaryingInfos[i].fLocation = i;
joshualittd8dd47b2015-09-11 11:45:01 -0700166 }
joshualitt47bb3822014-10-07 16:43:25 -0700167}
168
169bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
170 GrGLint linked = GR_GL_INIT_ZERO;
171 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
172 if (!linked) {
173 GrGLint infoLen = GR_GL_INIT_ZERO;
174 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
175 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
176 if (infoLen > 0) {
177 // retrieve length even though we don't need it to workaround
178 // bug in chrome cmd buffer param validation.
179 GrGLsizei length = GR_GL_INIT_ZERO;
180 GL_CALL(GetProgramInfoLog(programID,
181 infoLen+1,
182 &length,
183 (char*)log.get()));
kkinnunen297aaf92015-02-19 06:32:12 -0800184 SkDebugf("%s", (char*)log.get());
joshualitt47bb3822014-10-07 16:43:25 -0700185 }
186 SkDEBUGFAIL("Error linking program");
187 GL_CALL(DeleteProgram(programID));
188 programID = 0;
189 }
190 return SkToBool(linked);
191}
192
kkinnunen7aedda52015-06-29 23:01:28 -0700193void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800194 fUniformHandler.getUniformLocations(programID, fGpu->glCaps());
joshualittd8dd47b2015-09-11 11:45:01 -0700195
196 // handle NVPR separable varyings
197 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
kkinnunen7bdb05d2016-01-25 00:47:23 -0800198 fGpu->glPathRendering()->shouldBindFragmentInputs()) {
joshualittd8dd47b2015-09-11 11:45:01 -0700199 return;
200 }
egdaniel0eafe792015-11-20 14:01:22 -0800201 int count = fVaryingHandler.fPathProcVaryingInfos.count();
joshualittd8dd47b2015-09-11 11:45:01 -0700202 for (int i = 0; i < count; ++i) {
203 GrGLint location;
egdaniel0eafe792015-11-20 14:01:22 -0800204 GL_CALL_RET(location, GetProgramResourceLocation(
205 programID,
206 GR_GL_FRAGMENT_INPUT,
207 fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
208 fVaryingHandler.fPathProcVaryingInfos[i].fLocation = location;
joshualittd8dd47b2015-09-11 11:45:01 -0700209 }
joshualitt30ba4362014-08-21 20:18:45 -0700210}
211
joshualitt47bb3822014-10-07 16:43:25 -0700212void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
213 GL_CALL(DeleteProgram(programID));
egdanielfa896322016-01-13 12:19:30 -0800214 this->cleanupShaders(shaderIDs);
215 this->cleanupFragmentProcessors();
joshualitt47bb3822014-10-07 16:43:25 -0700216}
217void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
218 for (int i = 0; i < shaderIDs.count(); ++i) {
219 GL_CALL(DeleteShader(shaderIDs[i]));
220 }
221}
222
223GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
egdaniel7ea439b2015-12-03 09:20:44 -0800224 return new GrGLProgram(fGpu,
225 this->desc(),
226 fUniformHandles,
227 programID,
228 fUniformHandler.fUniforms,
egdaniel0eafe792015-11-20 14:01:22 -0800229 fVaryingHandler.fPathProcVaryingInfos,
egdaniel7ea439b2015-12-03 09:20:44 -0800230 fGeometryProcessor,
231 fXferProcessor,
egdanielfa896322016-01-13 12:19:30 -0800232 fFragmentProcessors,
halcanary385fe4d2015-08-26 13:07:48 -0700233 &fSamplerUniforms);
joshualitt47bb3822014-10-07 16:43:25 -0700234}
235