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

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 //////////////////////////////////////////////////////////////////////////////// ////////////////////
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 ==
84 desc.getHeader().fFragPosKey){
85 }
86
87 const char* GrGLFragmentShaderBuilder::dstColor() {
88 if (fProgram->fCodeStage.inStageCode()) {
89 const GrEffect* effect = fProgram->fCodeStage.effectStage()->getEffect() ;
90 if (!effect->willReadDstColor()) {
91 SkDEBUGFAIL("GrGLEffect asked for dst color but its generating GrEff ect "
92 "did not request access.");
93 return "";
94 }
95 }
96
97 GrGpuGL* gpu = fProgram->gpu();
98 if (gpu->glCaps().fbFetchSupport()) {
99 this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeatur e + 1),
100 gpu->glCaps().fbFetchExtensionString());
101 return gpu->glCaps().fbFetchColorName();
102 } else if (fProgram->fUniformHandles.fDstCopySamplerUni.isValid()) {
103 return kDstCopyColorName;
104 } else {
105 return "";
106 }
107 }
108
109 bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
110 switch (feature) {
111 case kStandardDerivatives_GLSLFeature: {
112 GrGpuGL* gpu = fProgram->gpu();
113 if (!gpu->glCaps().shaderDerivativeSupport()) {
114 return false;
115 }
116 if (kGLES_GrGLStandard == gpu->glStandard()) {
117 this->addFeature(1 << kStandardDerivatives_GLSLFeature,
118 "GL_OES_standard_derivatives");
119 }
120 return true;
121 }
122 default:
123 SkFAIL("Unexpected GLSLFeature requested.");
124 return false;
125 }
126 }
127
128 SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(const TransformedCoordsArra y& coords, int index) {
129 if (kVec3f_GrSLType != coords[index].type()) {
130 SkASSERT(kVec2f_GrSLType == coords[index].type());
131 return coords[index].getName();
132 }
133
134 SkString coords2D("coords2D");
135 if (0 != index) {
136 coords2D.appendf("_%i", index);
137 }
138 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;",
139 coords2D.c_str(), coords[index].c_str(), coords[index].c_s tr());
140 return coords2D;
141 }
142
143 const char* GrGLFragmentShaderBuilder::fragmentPosition() {
144 GrGLProgramBuilder::CodeStage* cs = &fProgram->fCodeStage;
145 if (cs->inStageCode()) {
146 const GrEffect* effect = cs->effectStage()->getEffect();
147 if (!effect->willReadFragmentPosition()) {
148 SkDEBUGFAIL("GrGLEffect asked for frag position but its generating G rEffect "
149 "did not request access.");
150 return "";
151 }
152 }
153
154 GrGpuGL* gpu = fProgram->gpu();
155 // We only declare "gl_FragCoord" when we're in the case where we want to us e layout qualifiers
156 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
157 // declaration varies in earlier GLSL specs. So it is simpler to omit it.
158 if (fTopLeftFragPosRead) {
159 fSetupFragPosition = true;
160 return "gl_FragCoord";
161 } else if (gpu->glCaps().fragCoordConventionsSupport()) {
162 if (!fSetupFragPosition) {
163 if (gpu->glslGeneration() < k150_GrGLSLGeneration) {
164 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
165 "GL_ARB_fragment_coord_conventions");
166 }
167 GrGLShaderVar t = GrGLShaderVar();
168 t.set(kVec4f_GrSLType,
169 GrGLShaderVar::kIn_TypeModifier,
170 "gl_FragCoord",
171 GrGLShaderVar::kDefault_Precision,
172 GrGLShaderVar::kUpperLeft_Origin);
173 this->addInput(t);
174 fSetupFragPosition = true;
175 }
176 return "gl_FragCoord";
177 } else {
178 static const char* kCoordName = "fragCoordYDown";
179 if (!fSetupFragPosition) {
180 // temporarily change the stage index because we're inserting non-st age code.
181 GrGLProgramBuilder::CodeStage::AutoStageRestore csar(cs, NULL);
182
183 SkASSERT(!fProgram->fUniformHandles.fRTHeightUni.isValid());
184 const char* rtHeightName;
185
186 fProgram->fUniformHandles.fRTHeightUni =
187 fProgram->addUniform(GrGLProgramBuilder::kFragment_Visibility, k Float_GrSLType,
188 "RTHeight", &rtHeightName);
189
190 // Using glFragCoord.zw for the last two components tickles an Adren o driver bug that
191 // causes programs to fail to link. Making this function return a ve c2() didn't fix the
192 // problem but using 1.0 for the last two components does.
193 this->codePrependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoo rd.y, 1.0, "
194 "1.0);\n", kCoordName, rtHeightName);
195 fSetupFragPosition = true;
196 }
197 SkASSERT(fProgram->fUniformHandles.fRTHeightUni.isValid());
198 return kCoordName;
199 }
200 }
201
202 // GrGLFragmentShaderBuilder private /////////////////////////////////////////// ///////////////////
203 void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
204 const char* name,
205 const char** fsInName) {
206 fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name);
207 if (fsInName) {
208 *fsInName = name;
209 }
210 }
211
212 void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) {
213 GrGpuGL* gpu = fProgram->gpu();
214 if (fHasCustomColorOutput) {
215 GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name()) );
216 }
217 if (fHasSecondaryOutput) {
218 GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_ name()));
219 }
220 }
221
222 bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTD Array<GrGLuint>* shaderIds) 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 = GrGLShaderStringBuilder::attachShader(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 // emit code to read the dst copy texture, if necessary
255 if (kNoDstRead_DstReadKey != header.fDstReadKey && !gpu->glCaps().fbFetchSup port()) {
256 bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKe y);
257 const char* dstCopyTopLeftName;
258 const char* dstCopyCoordScaleName;
259 const char* dstCopySamplerName;
260 uint32_t configMask;
261 if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
262 configMask = kA_GrColorComponentFlag;
263 } else {
264 configMask = kRGBA_GrColorComponentFlags;
265 }
266 fProgram->fUniformHandles.fDstCopySamplerUni =
267 fProgram->addUniform(GrGLProgramBuilder::kFragment_Visibility, kSamp ler2D_GrSLType, "DstCopySampler",
268 &dstCopySamplerName);
269 fProgram->fUniformHandles.fDstCopyTopLeftUni =
270 fProgram->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2 f_GrSLType, "DstCopyUpperLeft",
271 &dstCopyTopLeftName);
272 fProgram->fUniformHandles.fDstCopyScaleUni =
273 fProgram->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2 f_GrSLType, "DstCopyCoordScale",
274 &dstCopyCoordScaleName);
275 const char* fragPos = fragmentPosition();
276
277 this->codeAppend("// Read color from copy of the destination.\n");
278 this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
279 fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
280 if (!topDown) {
281 this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
282 }
283 this->codeAppendf("vec4 %s = ", kDstCopyColorName);
284 this->appendTextureLookup(dstCopySamplerName,
285 "_dstTexCoord",
286 configMask,
287 "rgba");
288 this->codeAppend(";");
289 }
290
291 if (k110_GrGLSLGeneration != gpu->glslGeneration()) {
292 fOutputs.push_back().set(kVec4f_GrSLType,
293 GrGLShaderVar::kOut_TypeModifier,
294 declared_color_output_name());
295 fHasCustomColorOutput = true;
296 }
297 }
298
299 void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputCol or, const GrGLSLExpr4& inputCoverage) {
300 const GrGLProgramDesc::KeyHeader& header = fProgram->desc().getHeader();
301 ///////////////////////////////////////////////////////////////////////////
302 // write the secondary color output if necessary
303 if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutpu t)) {
304 const char* secondaryOutputName = this->enableSecondaryOutput();
305
306 // default coeff to ones for kCoverage_DualSrcOutput
307 GrGLSLExpr4 coeff(1);
308 if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCov erageOutput) {
309 // Get (1-A) into coeff
310 coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
311 } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput ==
312 header.fCoverageOutput){
313 // Get (1-RGBA) into coeff
314 coeff = GrGLSLExpr4(1) - inputColor;
315 }
316 // Get coeff * coverage into modulate and then write that to the dual so urce output.
317 codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage) .c_str());
318 }
319
320 ///////////////////////////////////////////////////////////////////////////
321 // combine color and coverage as frag color
322
323 // Get "color * coverage" into fragColor
324 GrGLSLExpr4 fragColor = inputColor * inputCoverage;
325 // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
326 if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutpu t) {
327 GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;
328
329 GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor());
330
331 fragColor = fragColor + dstContribution;
332 }
333 codeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str());
334 }
335
336 const char* GrGLFragmentShaderBuilder::enableSecondaryOutput() {
337 if (!fHasSecondaryOutput) {
338 fOutputs.push_back().set(kVec4f_GrSLType,
339 GrGLShaderVar::kOut_TypeModifier,
340 dual_source_output_name());
341 fHasSecondaryOutput = true;
342 }
343 return dual_source_output_name();
344 }
345
346 const char* GrGLFragmentShaderBuilder::getColorOutputName() const {
347 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor" ;
348 }
349
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698