Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(665)

Side by Side Diff: src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp

Issue 491673002: Initial refactor of shaderbuilder (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
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
8 #include "GrGLFragmentShaderBuilder.h"
9 #include "GrGLShaderStringBuilder.h"
10 #include "GrGLProgramBuilder.h"
11 #include "../GrGpuGL.h"
12
13 //////////////////////////////////////////////////////////////////////////////// ////////////////////
bsalomon 2014/08/21 20:21:01 Having these local, static, private blocks is at o
14 // local /////////////////////////////////////////////////////////////////////// ////////////////////
15 namespace {
16 #define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
17 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
18 // ES2 FS only guarantees mediump and lowp support
19 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar: :kMedium_Precision;
20 static const char kDstCopyColorName[] = "_dstColor";
21 inline const char* declared_color_output_name() { return "fsColorOut"; }
22 inline const char* dual_source_output_name() { return "dualSourceOut"; }
23 inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
24 GrGLStandard standard,
25 SkString* str) {
26 // Desktop GLSL has added precision qualifiers but they don't do anything.
27 if (kGLES_GrGLStandard == standard) {
28 switch (p) {
29 case GrGLShaderVar::kHigh_Precision:
30 str->append("precision highp float;\n");
31 break;
32 case GrGLShaderVar::kMedium_Precision:
33 str->append("precision mediump float;\n");
34 break;
35 case GrGLShaderVar::kLow_Precision:
36 str->append("precision lowp float;\n");
37 break;
38 case GrGLShaderVar::kDefault_Precision:
39 SkFAIL("Default precision now allowed.");
40 default:
41 SkFAIL("Unknown precision value.");
42 }
43 }
44 }
45 }
46
47 //////////////////////////////////////////////////////////////////////////////// ////////////////////
48 // GrGLFragmentShaderBuilder static //////////////////////////////////////////// ////////////////////
49 GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead(
50 const GrTexture* dstCopy, const GrGLCaps& caps) {
51 uint32_t key = kYesDstRead_DstReadKeyBit;
52 if (caps.fbFetchSupport()) {
53 return key;
54 }
55 SkASSERT(NULL != dstCopy);
56 if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->confi g())) {
57 // The fact that the config is alpha-only must be considered when genera ting code.
58 key |= kUseAlphaConfig_DstReadKeyBit;
59 }
60 if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) {
61 key |= kTopLeftOrigin_DstReadKeyBit;
62 }
63 SkASSERT(static_cast<DstReadKey>(key) == key);
64 return static_cast<DstReadKey>(key);
65 }
66
67 GrGLFragmentShaderBuilder::FragPosKey GrGLFragmentShaderBuilder::KeyForFragmentP osition(
68 const GrRenderTarget* dst, const GrGLCaps&) {
69 if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
70 return kTopLeftFragPosRead_FragPosKey;
71 } else {
72 return kBottomLeftFragPosRead_FragPosKey;
73 }
74 }
75
76 // GrGLFragmentShaderBuilder public //////////////////////////////////////////// ///////////////////
77 GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program ,
78 const GrGLProgramDesc& desc )
79 : INHERITED(program)
80 , fHasCustomColorOutput(false)
81 , fHasSecondaryOutput(false)
82 , fSetupFragPosition(false)
83 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFr agPosKey){
84 }
85
86 const char* GrGLFragmentShaderBuilder::dstColor() {
87 if (fProgram->fCodeStage.inStageCode()) {
88 const GrEffect* effect = fProgram->fCodeStage.effectStage()->getEffect() ;
89 if (!effect->willReadDstColor()) {
90 SkDEBUGFAIL("GrGLEffect asked for dst color but its generating GrEff ect "
91 "did not request access.");
92 return "";
93 }
94 }
95
96 GrGpuGL* gpu = fProgram->gpu();
97 if (gpu->glCaps().fbFetchSupport()) {
98 this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeatur e + 1),
99 gpu->glCaps().fbFetchExtensionString());
100 return gpu->glCaps().fbFetchColorName();
101 } else if (fProgram->fUniformHandles.fDstCopySamplerUni.isValid()) {
102 return kDstCopyColorName;
103 } else {
104 return "";
105 }
106 }
107
108 bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
109 switch (feature) {
110 case kStandardDerivatives_GLSLFeature: {
111 GrGpuGL* gpu = fProgram->gpu();
112 if (!gpu->glCaps().shaderDerivativeSupport()) {
113 return false;
114 }
115 if (kGLES_GrGLStandard == gpu->glStandard()) {
116 this->addFeature(1 << kStandardDerivatives_GLSLFeature,
117 "GL_OES_standard_derivatives");
118 }
119 return true;
120 }
121 default:
122 SkFAIL("Unexpected GLSLFeature requested.");
123 return false;
124 }
125 }
126
127 SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(const TransformedCoordsArra y& coords, int index) {
128 if (kVec3f_GrSLType != coords[index].type()) {
129 SkASSERT(kVec2f_GrSLType == coords[index].type());
130 return coords[index].getName();
131 }
132
133 SkString coords2D("coords2D");
134 if (0 != index) {
135 coords2D.appendf("_%i", index);
136 }
137 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;",
138 coords2D.c_str(), coords[index].c_str(), coords[index].c_s tr());
139 return coords2D;
140 }
141
142 const char* GrGLFragmentShaderBuilder::fragmentPosition() {
143 GrGLProgramBuilder::CodeStage* cs = &fProgram->fCodeStage;
144 if (cs->inStageCode()) {
145 const GrEffect* effect = cs->effectStage()->getEffect();
146 if (!effect->willReadFragmentPosition()) {
147 SkDEBUGFAIL("GrGLEffect asked for frag position but its generating G rEffect "
148 "did not request access.");
149 return "";
150 }
151 }
152
153 GrGpuGL* gpu = fProgram->gpu();
154 // We only declare "gl_FragCoord" when we're in the case where we want to us e layout qualifiers
155 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
156 // declaration varies in earlier GLSL specs. So it is simpler to omit it.
157 if (fTopLeftFragPosRead) {
158 fSetupFragPosition = true;
159 return "gl_FragCoord";
160 } else if (gpu->glCaps().fragCoordConventionsSupport()) {
161 if (!fSetupFragPosition) {
162 if (gpu->glslGeneration() < k150_GrGLSLGeneration) {
163 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
164 "GL_ARB_fragment_coord_conventions");
165 }
166 fInputs.push_back().set(kVec4f_GrSLType,
167 GrGLShaderVar::kIn_TypeModifier,
168 "gl_FragCoord",
169 GrGLShaderVar::kDefault_Precision,
170 GrGLShaderVar::kUpperLeft_Origin);
171 fSetupFragPosition = true;
172 }
173 return "gl_FragCoord";
174 } else {
175 static const char* kCoordName = "fragCoordYDown";
176 if (!fSetupFragPosition) {
177 // temporarily change the stage index because we're inserting non-st age code.
178 GrGLProgramBuilder::CodeStage::AutoStageRestore csar(cs, NULL);
179
180 SkASSERT(!fProgram->fUniformHandles.fRTHeightUni.isValid());
181 const char* rtHeightName;
182
183 fProgram->fUniformHandles.fRTHeightUni =
184 fProgram->addUniform(GrGLProgramBuilder::kFragment_Visibilit y,
185 kFloat_GrSLType,
186 "RTHeight",
187 &rtHeightName);
188
189 // Using glFragCoord.zw for the last two components tickles an Adren o driver bug that
190 // causes programs to fail to link. Making this function return a ve c2() didn't fix the
191 // problem but using 1.0 for the last two components does.
192 this->codePrependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoo rd.y, 1.0, "
193 "1.0);\n", kCoordName, rtHeightName);
194 fSetupFragPosition = true;
195 }
196 SkASSERT(fProgram->fUniformHandles.fRTHeightUni.isValid());
197 return kCoordName;
198 }
199 }
200
201 // GrGLFragmentShaderBuilder private /////////////////////////////////////////// ///////////////////
202 void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
203 const char* name,
204 const char** fsInName) {
205 fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name);
206 if (fsInName) {
207 *fsInName = name;
208 }
209 }
210
211 void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) {
212 GrGpuGL* gpu = fProgram->gpu();
213 if (fHasCustomColorOutput) {
214 GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name()) );
215 }
216 if (fHasSecondaryOutput) {
217 GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_ name()));
218 }
219 }
220
221 bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
222 SkTDArray<GrGLuint>* sha derIds) const {
223 GrGpuGL* gpu = fProgram->gpu();
224 SkString fragShaderSrc(GrGetGLSLVersionDecl(gpu->ctxInfo()));
225 fragShaderSrc.append(fExtensions);
226 append_default_precision_qualifier(kDefaultFragmentPrecision,
227 gpu->glStandard(),
228 &fragShaderSrc);
229 fProgram->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &frag ShaderSrc);
230 fProgram->appendDecls(fInputs, &fragShaderSrc);
231 // We shouldn't have declared outputs on 1.10
232 SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty()) ;
233 fProgram->appendDecls(fOutputs, &fragShaderSrc);
234 fragShaderSrc.append(fFunctions);
235 fragShaderSrc.append("void main() {\n");
236 fragShaderSrc.append(fCode);
237 fragShaderSrc.append("}\n");
238
239 GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(),
240 programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc);
241 if (!fragShaderId) {
242 return false;
243 }
244
245 *shaderIds->append() = fragShaderId;
246
247 return true;
248 }
249
250 void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() {
251 const GrGLProgramDesc::KeyHeader& header = fProgram->desc().getHeader();
252 GrGpuGL* gpu = fProgram->gpu();
253
254 ///////////////////////////////////////////////////////////////////////////
255 // emit code to read the dst copy texture, if necessary
256 if (kNoDstRead_DstReadKey != header.fDstReadKey && !gpu->glCaps().fbFetchSup port()) {
257 bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKe y);
258 const char* dstCopyTopLeftName;
259 const char* dstCopyCoordScaleName;
260 const char* dstCopySamplerName;
261 uint32_t configMask;
262 if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
263 configMask = kA_GrColorComponentFlag;
264 } else {
265 configMask = kRGBA_GrColorComponentFlags;
266 }
267 fProgram->fUniformHandles.fDstCopySamplerUni =
268 fProgram->addUniform(GrGLProgramBuilder::kFragment_Visibility,
269 kSampler2D_GrSLType,
270 "DstCopySampler",
271 &dstCopySamplerName);
272 fProgram->fUniformHandles.fDstCopyTopLeftUni =
273 fProgram->addUniform(GrGLProgramBuilder::kFragment_Visibility,
274 kVec2f_GrSLType,
275 "DstCopyUpperLeft",
276 &dstCopyTopLeftName);
277 fProgram->fUniformHandles.fDstCopyScaleUni =
278 fProgram->addUniform(GrGLProgramBuilder::kFragment_Visibility,
279 kVec2f_GrSLType,
280 "DstCopyCoordScale",
281 &dstCopyCoordScaleName);
282 const char* fragPos = fragmentPosition();
283
284 this->codeAppend("// Read color from copy of the destination.\n");
285 this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
286 fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
287 if (!topDown) {
288 this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
289 }
290 this->codeAppendf("vec4 %s = ", kDstCopyColorName);
291 this->appendTextureLookup(dstCopySamplerName,
292 "_dstTexCoord",
293 configMask,
294 "rgba");
295 this->codeAppend(";");
296 }
297
298 if (k110_GrGLSLGeneration != gpu->glslGeneration()) {
299 fOutputs.push_back().set(kVec4f_GrSLType,
300 GrGLShaderVar::kOut_TypeModifier,
301 declared_color_output_name());
302 fHasCustomColorOutput = true;
303 }
304 }
305
306 void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputCol or, const GrGLSLExpr4& inputCoverage) {
307 const GrGLProgramDesc::KeyHeader& header = fProgram->desc().getHeader();
308
309 ///////////////////////////////////////////////////////////////////////////
310 // write the secondary color output if necessary
311 if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutpu t)) {
312 const char* secondaryOutputName = this->enableSecondaryOutput();
313
314 // default coeff to ones for kCoverage_DualSrcOutput
315 GrGLSLExpr4 coeff(1);
316 if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCov erageOutput) {
317 // Get (1-A) into coeff
318 coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
319 } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput ==
320 header.fCoverageOutput){
321 // Get (1-RGBA) into coeff
322 coeff = GrGLSLExpr4(1) - inputColor;
323 }
324 // Get coeff * coverage into modulate and then write that to the dual so urce output.
325 codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage) .c_str());
326 }
327
328 ///////////////////////////////////////////////////////////////////////////
329 // combine color and coverage as frag color
330
331 // Get "color * coverage" into fragColor
332 GrGLSLExpr4 fragColor = inputColor * inputCoverage;
333 // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
334 if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutpu t) {
335 GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;
336
337 GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor());
338
339 fragColor = fragColor + dstContribution;
340 }
341 codeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str());
342 }
343
344 const char* GrGLFragmentShaderBuilder::enableSecondaryOutput() {
345 if (!fHasSecondaryOutput) {
346 fOutputs.push_back().set(kVec4f_GrSLType,
347 GrGLShaderVar::kOut_TypeModifier,
348 dual_source_output_name());
349 fHasSecondaryOutput = true;
350 }
351 return dual_source_output_name();
352 }
353
354 const char* GrGLFragmentShaderBuilder::getColorOutputName() const {
355 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor" ;
356 }
357
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698