OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrGLProgramBuilder.h" | 8 #include "GrGLProgramBuilder.h" |
9 | 9 |
10 #include "GrAutoLocaleSetter.h" | 10 #include "GrAutoLocaleSetter.h" |
11 #include "GrCoordTransform.h" | 11 #include "GrCoordTransform.h" |
12 #include "GrGLProgramBuilder.h" | 12 #include "GrGLProgramBuilder.h" |
13 #include "GrTexture.h" | 13 #include "GrTexture.h" |
14 #include "SkRTConf.h" | 14 #include "SkRTConf.h" |
15 #include "SkTraceEvent.h" | 15 #include "SkTraceEvent.h" |
16 #include "gl/GrGLFragmentProcessor.h" | 16 #include "gl/GrGLFragmentProcessor.h" |
17 #include "gl/GrGLGeometryProcessor.h" | 17 #include "gl/GrGLGeometryProcessor.h" |
18 #include "gl/GrGLGpu.h" | 18 #include "gl/GrGLGpu.h" |
19 #include "gl/GrGLProgram.h" | 19 #include "gl/GrGLProgram.h" |
20 #include "gl/GrGLSLPrettyPrint.h" | 20 #include "gl/GrGLSLPrettyPrint.h" |
21 #include "gl/GrGLXferProcessor.h" | 21 #include "gl/GrGLXferProcessor.h" |
22 #include "gl/builders/GrGLShaderStringBuilder.h" | 22 #include "gl/builders/GrGLShaderStringBuilder.h" |
23 #include "glsl/GrGLSLCaps.h" | 23 #include "glsl/GrGLSLCaps.h" |
24 #include "glsl/GrGLSLProgramDataManager.h" | 24 #include "glsl/GrGLSLProgramDataManager.h" |
25 #include "glsl/GrGLSLTextureSampler.h" | 25 #include "glsl/GrGLSLTextureSampler.h" |
26 | 26 |
27 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) | 27 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) |
28 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) | 28 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) |
29 | 29 |
30 const int GrGLProgramBuilder::kVarsPerBlock = 8; | |
31 | |
32 GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp
u) { | 30 GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp
u) { |
33 GrAutoLocaleSetter als("C"); | 31 GrAutoLocaleSetter als("C"); |
34 | 32 |
35 // create a builder. This will be handed off to effects so they can use it
to add | 33 // create a builder. This will be handed off to effects so they can use it
to add |
36 // uniforms, varyings, textures, etc | 34 // uniforms, varyings, textures, etc |
37 SkAutoTDelete<GrGLProgramBuilder> builder(new GrGLProgramBuilder(gpu, args))
; | 35 SkAutoTDelete<GrGLProgramBuilder> builder(new GrGLProgramBuilder(gpu, args))
; |
38 | 36 |
39 GrGLProgramBuilder* pb = builder.get(); | 37 GrGLProgramBuilder* pb = builder.get(); |
40 | 38 |
41 // TODO: Once all stages can handle taking a float or vec4 and correctly han
dling them we can | 39 // TODO: Once all stages can handle taking a float or vec4 and correctly han
dling them we can |
42 // seed correctly here | 40 // seed correctly here |
43 GrGLSLExpr4 inputColor; | 41 GrGLSLExpr4 inputColor; |
44 GrGLSLExpr4 inputCoverage; | 42 GrGLSLExpr4 inputCoverage; |
45 | 43 |
46 if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { | 44 if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { |
47 return nullptr; | 45 return nullptr; |
48 } | 46 } |
49 | 47 |
50 return pb->finalize(); | 48 return pb->finalize(); |
51 } | 49 } |
52 | 50 |
53 ///////////////////////////////////////////////////////////////////////////// | 51 ///////////////////////////////////////////////////////////////////////////// |
54 | 52 |
55 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) | 53 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) |
56 : fVS(this) | 54 : INHERITED(args) |
57 , fGS(this) | |
58 , fFS(this, args.fDesc->header().fFragPosKey) | |
59 , fStageIndex(-1) | |
60 , fGeometryProcessor(nullptr) | 55 , fGeometryProcessor(nullptr) |
61 , fXferProcessor(nullptr) | 56 , fXferProcessor(nullptr) |
62 , fArgs(args) | |
63 , fGpu(gpu) | 57 , fGpu(gpu) |
64 , fUniforms(kVarsPerBlock) | 58 , fUniforms(kVarsPerBlock) |
65 , fSamplerUniforms(4) | 59 , fSamplerUniforms(4) |
66 , fSeparableVaryingInfos(kVarsPerBlock) { | 60 , fSeparableVaryingInfos(kVarsPerBlock) { |
67 } | 61 } |
68 | 62 |
69 void GrGLProgramBuilder::addVarying(const char* name, | 63 void GrGLProgramBuilder::addVarying(const char* name, |
70 GrGLVarying* varying, | 64 GrGLSLVarying* varying, |
71 GrSLPrecision precision) { | 65 GrSLPrecision precision) { |
72 SkASSERT(varying); | 66 SkASSERT(varying); |
73 if (varying->vsVarying()) { | 67 if (varying->vsVarying()) { |
74 fVS.addVarying(name, precision, varying); | 68 fVS.addVarying(name, precision, varying); |
75 } | 69 } |
76 if (this->primitiveProcessor().willUseGeoShader()) { | 70 if (this->primitiveProcessor().willUseGeoShader()) { |
77 fGS.addVarying(name, precision, varying); | 71 fGS.addVarying(name, precision, varying); |
78 } | 72 } |
79 if (varying->fsVarying()) { | 73 if (varying->fsVarying()) { |
80 fFS.addVarying(varying, precision); | 74 fFS.addVarying(varying, precision); |
81 } | 75 } |
82 } | 76 } |
83 | 77 |
84 void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Att
ribute* input, | 78 void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Att
ribute* input, |
85 const char* output) { | 79 const char* output) { |
86 GrSLType type = GrVertexAttribTypeToSLType(input->fType); | 80 GrSLType type = GrVertexAttribTypeToSLType(input->fType); |
87 GrGLVertToFrag v(type); | 81 GrGLSLVertToFrag v(type); |
88 this->addVarying(input->fName, &v); | 82 this->addVarying(input->fName, &v); |
89 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); | 83 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); |
90 fFS.codeAppendf("%s = %s;", output, v.fsIn()); | 84 fFS.codeAppendf("%s = %s;", output, v.fsIn()); |
91 } | 85 } |
92 | 86 |
93 GrGLProgramBuilder::SeparableVaryingHandle GrGLProgramBuilder::addSeparableVaryi
ng( | 87 GrGLProgramBuilder::SeparableVaryingHandle GrGLProgramBuilder::addSeparableVaryi
ng( |
94 const ch
ar* name, | 88 const ch
ar* name, |
95 GrGLVert
ToFrag* v, | 89 GrGLSLVe
rtToFrag* v, |
96 GrSLPrec
ision fsPrecision) { | 90 GrSLPrec
ision fsPrecision) { |
97 // This call is not used for non-NVPR backends. | 91 // This call is not used for non-NVPR backends. |
98 SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport() && | 92 SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport() && |
99 fArgs.fPrimitiveProcessor->isPathRendering() && | 93 fArgs.fPrimitiveProcessor->isPathRendering() && |
100 !fArgs.fPrimitiveProcessor->willUseGeoShader() && | 94 !fArgs.fPrimitiveProcessor->willUseGeoShader() && |
101 fArgs.fPrimitiveProcessor->numAttribs() == 0); | 95 fArgs.fPrimitiveProcessor->numAttribs() == 0); |
102 this->addVarying(name, v, fsPrecision); | 96 this->addVarying(name, v, fsPrecision); |
103 SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back(); | 97 SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back(); |
104 varyingInfo.fVariable = this->getFragmentShaderBuilder()->fInputs.back(); | 98 varyingInfo.fVariable = this->getFragmentShaderBuilder()->fInputs.back(); |
105 varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1; | 99 varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1; |
106 return SeparableVaryingHandle(varyingInfo.fLocation); | 100 return SeparableVaryingHandle(varyingInfo.fLocation); |
107 } | 101 } |
108 | 102 |
109 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na
me, bool mangle) { | |
110 if ('\0' == prefix) { | |
111 *out = name; | |
112 } else { | |
113 out->printf("%c%s", prefix, name); | |
114 } | |
115 if (mangle) { | |
116 if (out->endsWith('_')) { | |
117 // Names containing "__" are reserved. | |
118 out->append("x"); | |
119 } | |
120 out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str()); | |
121 } | |
122 } | |
123 | |
124 GrGLSLProgramDataManager::UniformHandle GrGLProgramBuilder::internalAddUniformAr
ray( | 103 GrGLSLProgramDataManager::UniformHandle GrGLProgramBuilder::internalAddUniformAr
ray( |
125 uint32_t visibil
ity, | 104 uint32_t visibil
ity, |
126 GrSLType type, | 105 GrSLType type, |
127 GrSLPrecision pr
ecision, | 106 GrSLPrecision pr
ecision, |
128 const char* name
, | 107 const char* name
, |
129 bool mangleName, | 108 bool mangleName, |
130 int count, | 109 int count, |
131 const char** out
Name) { | 110 const char** out
Name) { |
132 SkASSERT(name && strlen(name)); | 111 SkASSERT(name && strlen(name)); |
133 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr
agment_Visibility); | 112 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr
agment_Visibility); |
(...skipping 18 matching lines...) Expand all Loading... |
152 uni.fVariable.setArrayCount(count); | 131 uni.fVariable.setArrayCount(count); |
153 uni.fVisibility = visibility; | 132 uni.fVisibility = visibility; |
154 uni.fVariable.setPrecision(precision); | 133 uni.fVariable.setPrecision(precision); |
155 | 134 |
156 if (outName) { | 135 if (outName) { |
157 *outName = uni.fVariable.c_str(); | 136 *outName = uni.fVariable.c_str(); |
158 } | 137 } |
159 return GrGLSLProgramDataManager::UniformHandle(fUniforms.count() - 1); | 138 return GrGLSLProgramDataManager::UniformHandle(fUniforms.count() - 1); |
160 } | 139 } |
161 | 140 |
162 void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility, | 141 void GrGLProgramBuilder::onAppendUniformDecls(ShaderVisibility visibility, |
163 SkString* out) const { | 142 SkString* out) const { |
164 for (int i = 0; i < fUniforms.count(); ++i) { | 143 for (int i = 0; i < fUniforms.count(); ++i) { |
165 if (fUniforms[i].fVisibility & visibility) { | 144 if (fUniforms[i].fVisibility & visibility) { |
166 fUniforms[i].fVariable.appendDecl(this->glslCaps(), out); | 145 fUniforms[i].fVariable.appendDecl(this->glslCaps(), out); |
167 out->append(";\n"); | 146 out->append(";\n"); |
168 } | 147 } |
169 } | 148 } |
170 } | 149 } |
171 | 150 |
172 const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { | |
173 return fGpu->ctxInfo(); | |
174 } | |
175 | |
176 const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const { | 151 const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const { |
177 return this->ctxInfo().caps()->glslCaps(); | 152 return this->fGpu->ctxInfo().caps()->glslCaps(); |
178 } | 153 } |
179 | 154 |
180 bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr
4* inputCoverage) { | 155 bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr
4* inputCoverage) { |
181 // First we loop over all of the installed processors and collect coord tran
sforms. These will | 156 // First we loop over all of the installed processors and collect coord tran
sforms. These will |
182 // be sent to the GrGLPrimitiveProcessor in its emitCode function | 157 // be sent to the GrGLPrimitiveProcessor in its emitCode function |
183 const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); | 158 const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); |
184 int totalTextures = primProc.numTextures(); | 159 int totalTextures = primProc.numTextures(); |
185 const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits(); | 160 const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits(); |
186 | 161 |
187 for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) { | 162 for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) { |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 SkASSERT(!fXferProcessor); | 298 SkASSERT(!fXferProcessor); |
324 fXferProcessor = new GrGLInstalledXferProc; | 299 fXferProcessor = new GrGLInstalledXferProc; |
325 | 300 |
326 fXferProcessor->fGLProc.reset(xp.createGLInstance()); | 301 fXferProcessor->fGLProc.reset(xp.createGLInstance()); |
327 | 302 |
328 // Enable dual source secondary output if we have one | 303 // Enable dual source secondary output if we have one |
329 if (xp.hasSecondaryOutput()) { | 304 if (xp.hasSecondaryOutput()) { |
330 fFS.enableSecondaryOutput(); | 305 fFS.enableSecondaryOutput(); |
331 } | 306 } |
332 | 307 |
333 if (this->ctxInfo().caps()->glslCaps()->mustDeclareFragmentShaderOutput()) { | 308 if (this->glslCaps()->mustDeclareFragmentShaderOutput()) { |
334 fFS.enableCustomOutput(); | 309 fFS.enableCustomOutput(); |
335 } | 310 } |
336 | 311 |
337 SkString openBrace; | 312 SkString openBrace; |
338 openBrace.printf("{ // Xfer Processor: %s\n", xp.name()); | 313 openBrace.printf("{ // Xfer Processor: %s\n", xp.name()); |
339 fFS.codeAppend(openBrace.c_str()); | 314 fFS.codeAppend(openBrace.c_str()); |
340 | 315 |
341 SkSTArray<4, GrGLSLTextureSampler> samplers(xp.numTextures()); | 316 SkSTArray<4, GrGLSLTextureSampler> samplers(xp.numTextures()); |
342 this->emitSamplers(xp, &samplers, fXferProcessor); | 317 this->emitSamplers(xp, &samplers, fXferProcessor); |
343 | 318 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 SkTDArray<GrGLuint> shadersToDelete; | 391 SkTDArray<GrGLuint> shadersToDelete; |
417 fVS.finalize(kVertex_Visibility); | 392 fVS.finalize(kVertex_Visibility); |
418 if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &sha
dersToDelete)) { | 393 if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &sha
dersToDelete)) { |
419 this->cleanupProgram(programID, shadersToDelete); | 394 this->cleanupProgram(programID, shadersToDelete); |
420 return nullptr; | 395 return nullptr; |
421 } | 396 } |
422 | 397 |
423 // NVPR actually requires a vertex shader to compile | 398 // NVPR actually requires a vertex shader to compile |
424 bool useNvpr = primitiveProcessor().isPathRendering(); | 399 bool useNvpr = primitiveProcessor().isPathRendering(); |
425 if (!useNvpr) { | 400 if (!useNvpr) { |
426 fVS.bindVertexAttributes(programID); | 401 const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); |
| 402 |
| 403 int vaCount = primProc.numAttribs(); |
| 404 for (int i = 0; i < vaCount; i++) { |
| 405 GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName
)); |
| 406 } |
427 } | 407 } |
428 | 408 |
429 fFS.finalize(kFragment_Visibility); | 409 fFS.finalize(kFragment_Visibility); |
430 if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &s
hadersToDelete)) { | 410 if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &s
hadersToDelete)) { |
431 this->cleanupProgram(programID, shadersToDelete); | 411 this->cleanupProgram(programID, shadersToDelete); |
432 return nullptr; | 412 return nullptr; |
433 } | 413 } |
434 | 414 |
435 this->bindProgramResourceLocations(programID); | 415 this->bindProgramResourceLocations(programID); |
436 | 416 |
(...skipping 16 matching lines...) Expand all Loading... |
453 | 433 |
454 void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) { | 434 void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) { |
455 if (fGpu->glCaps().bindUniformLocationSupport()) { | 435 if (fGpu->glCaps().bindUniformLocationSupport()) { |
456 int count = fUniforms.count(); | 436 int count = fUniforms.count(); |
457 for (int i = 0; i < count; ++i) { | 437 for (int i = 0; i < count; ++i) { |
458 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_s
tr())); | 438 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_s
tr())); |
459 fUniforms[i].fLocation = i; | 439 fUniforms[i].fLocation = i; |
460 } | 440 } |
461 } | 441 } |
462 | 442 |
463 fFS.bindFragmentShaderLocations(programID); | 443 const GrGLCaps& caps = this->gpu()->glCaps(); |
| 444 if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) { |
| 445 GL_CALL(BindFragDataLocation(programID, 0, |
| 446 GrGLFragmentShaderBuilder::DeclaredColorOut
putName())); |
| 447 } |
| 448 if (fFS.hasSecondaryOutput() && caps.glslCaps()->mustDeclareFragmentShaderOu
tput()) { |
| 449 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, |
| 450 GrGLFragmentShaderBuilder::DeclaredSecondary
ColorOutputName())); |
| 451 } |
464 | 452 |
465 // handle NVPR separable varyings | 453 // handle NVPR separable varyings |
466 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() || | 454 if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() || |
467 !fGpu->glPathRendering()->shouldBindFragmentInputs()) { | 455 !fGpu->glPathRendering()->shouldBindFragmentInputs()) { |
468 return; | 456 return; |
469 } | 457 } |
470 int count = fSeparableVaryingInfos.count(); | 458 int count = fSeparableVaryingInfos.count(); |
471 for (int i = 0; i < count; ++i) { | 459 for (int i = 0; i < count; ++i) { |
472 GL_CALL(BindFragmentInputLocation(programID, | 460 GL_CALL(BindFragmentInputLocation(programID, |
473 i, | 461 i, |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
544 } | 532 } |
545 | 533 |
546 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 534 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
547 | 535 |
548 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { | 536 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { |
549 int numProcs = fProcs.count(); | 537 int numProcs = fProcs.count(); |
550 for (int i = 0; i < numProcs; ++i) { | 538 for (int i = 0; i < numProcs; ++i) { |
551 delete fProcs[i]; | 539 delete fProcs[i]; |
552 } | 540 } |
553 } | 541 } |
OLD | NEW |