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

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

Powered by Google App Engine
This is Rietveld 408576698