Chromium Code Reviews| 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" |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 35 // uniforms, varyings, textures, etc | 35 // uniforms, varyings, textures, etc |
| 36 SkAutoTDelete<GrGLProgramBuilder> builder(new GrGLProgramBuilder(gpu, args)) ; | 36 SkAutoTDelete<GrGLProgramBuilder> builder(new GrGLProgramBuilder(gpu, args)) ; |
| 37 | 37 |
| 38 GrGLProgramBuilder* pb = builder.get(); | 38 GrGLProgramBuilder* pb = builder.get(); |
| 39 | 39 |
| 40 // TODO: Once all stages can handle taking a float or vec4 and correctly han dling them we can | 40 // TODO: Once all stages can handle taking a float or vec4 and correctly han dling them we can |
| 41 // seed correctly here | 41 // seed correctly here |
| 42 GrGLSLExpr4 inputColor; | 42 GrGLSLExpr4 inputColor; |
| 43 GrGLSLExpr4 inputCoverage; | 43 GrGLSLExpr4 inputCoverage; |
| 44 | 44 |
| 45 if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { | 45 if (!pb->emitAndInstallProcs(&inputColor, |
| 46 &inputCoverage, | |
| 47 gpu->glCaps().maxFragmentTextureUnits())) { | |
| 46 return nullptr; | 48 return nullptr; |
| 47 } | 49 } |
| 48 | 50 |
| 49 return pb->finalize(); | 51 return pb->finalize(); |
| 50 } | 52 } |
| 51 | 53 |
| 52 ///////////////////////////////////////////////////////////////////////////// | 54 ///////////////////////////////////////////////////////////////////////////// |
| 53 | 55 |
| 54 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) | 56 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) |
| 55 : INHERITED(args) | 57 : INHERITED(args) |
| 56 , fGeometryProcessor(nullptr) | |
| 57 , fXferProcessor(nullptr) | |
| 58 , fGpu(gpu) | 58 , fGpu(gpu) |
| 59 , fSamplerUniforms(4) | 59 , fSamplerUniforms(4) |
| 60 , fVaryingHandler(this) | 60 , fVaryingHandler(this) |
| 61 , fUniformHandler(this) { | 61 , fUniformHandler(this) { |
| 62 } | 62 } |
| 63 | 63 |
| 64 const GrCaps* GrGLProgramBuilder::caps() const { | |
| 65 return fGpu->caps(); | |
| 66 } | |
| 64 const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const { | 67 const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const { |
|
bsalomon
2016/01/13 17:49:19
\n
egdaniel
2016/01/13 19:59:49
Done.
| |
| 65 return this->fGpu->ctxInfo().caps()->glslCaps(); | 68 return fGpu->ctxInfo().caps()->glslCaps(); |
| 66 } | |
| 67 | |
| 68 bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr 4* inputCoverage) { | |
| 69 // First we loop over all of the installed processors and collect coord tran sforms. These will | |
| 70 // be sent to the GrGLSLPrimitiveProcessor in its emitCode function | |
| 71 const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); | |
| 72 int totalTextures = primProc.numTextures(); | |
| 73 const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits(); | |
| 74 | |
| 75 for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) { | |
| 76 const GrFragmentProcessor& processor = this->pipeline().getFragmentProce ssor(i); | |
| 77 | |
| 78 if (!primProc.hasTransformedLocalCoords()) { | |
| 79 SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransfor ms.push_back(); | |
| 80 processor.gatherCoordTransforms(&procCoords); | |
| 81 } | |
| 82 | |
| 83 totalTextures += processor.numTextures(); | |
| 84 if (totalTextures >= maxTextureUnits) { | |
| 85 GrCapsDebugf(fGpu->caps(), "Program would use too many texture units \n"); | |
| 86 return false; | |
| 87 } | |
| 88 } | |
| 89 | |
| 90 this->emitAndInstallProc(primProc, inputColor, inputCoverage); | |
| 91 | |
| 92 fFragmentProcessors.reset(new GrGLInstalledFragProcs); | |
| 93 int numProcs = this->pipeline().numFragmentProcessors(); | |
| 94 this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors (), inputColor); | |
| 95 this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(), numProcs, | |
| 96 inputCoverage); | |
| 97 this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColo r, *inputCoverage, | |
| 98 this->pipeline().ignoresCoverage()); | |
| 99 this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOu tput()); | |
| 100 return true; | |
| 101 } | |
| 102 | |
| 103 void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, | |
| 104 int numProcs, | |
| 105 GrGLSLExpr4* inOut) { | |
| 106 for (int i = procOffset; i < numProcs; ++i) { | |
| 107 GrGLSLExpr4 output; | |
| 108 const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i) ; | |
| 109 this->emitAndInstallProc(fp, i, *inOut, &output); | |
| 110 *inOut = output; | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseNam e) { | |
| 115 // create var to hold stage result. If we already have a valid output name, just use that | |
| 116 // otherwise create a new mangled one. This name is only valid if we are re ordering stages | |
| 117 // and have to tell stage exactly where to put its output. | |
| 118 SkString outName; | |
| 119 if (output->isValid()) { | |
| 120 outName = output->c_str(); | |
| 121 } else { | |
| 122 this->nameVariable(&outName, '\0', baseName); | |
| 123 } | |
| 124 fFS.codeAppendf("vec4 %s;", outName.c_str()); | |
| 125 *output = outName; | |
| 126 } | |
| 127 | |
| 128 // TODO Processors cannot output zeros because an empty string is all 1s | |
| 129 // the fix is to allow effects to take the GrGLSLExpr4 directly | |
| 130 void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp, | |
| 131 int index, | |
| 132 const GrGLSLExpr4& input, | |
| 133 GrGLSLExpr4* output) { | |
| 134 // Program builders have a bit of state we need to clear with each effect | |
| 135 AutoStageAdvance adv(this); | |
| 136 this->nameExpression(output, "output"); | |
| 137 | |
| 138 // Enclose custom code in a block to avoid namespace conflicts | |
| 139 SkString openBrace; | |
| 140 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name()); | |
| 141 fFS.codeAppend(openBrace.c_str()); | |
| 142 | |
| 143 this->emitAndInstallProc(fp, index, output->c_str(), input.isOnes() ? nullpt r : input.c_str()); | |
| 144 | |
| 145 fFS.codeAppend("}"); | |
| 146 } | |
| 147 | |
| 148 void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc, | |
| 149 GrGLSLExpr4* outputColor, | |
| 150 GrGLSLExpr4* outputCoverage) { | |
| 151 // Program builders have a bit of state we need to clear with each effect | |
| 152 AutoStageAdvance adv(this); | |
| 153 this->nameExpression(outputColor, "outputColor"); | |
| 154 this->nameExpression(outputCoverage, "outputCoverage"); | |
| 155 | |
| 156 // Enclose custom code in a block to avoid namespace conflicts | |
| 157 SkString openBrace; | |
| 158 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); | |
| 159 fFS.codeAppend(openBrace.c_str()); | |
| 160 fVS.codeAppendf("// Primitive Processor %s\n", proc.name()); | |
| 161 | |
| 162 this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str() ); | |
| 163 | |
| 164 fFS.codeAppend("}"); | |
| 165 } | |
| 166 | |
| 167 void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp, | |
| 168 int index, | |
| 169 const char* outColor, | |
| 170 const char* inColor) { | |
| 171 GrGLInstalledFragProc* ifp = new GrGLInstalledFragProc; | |
| 172 | |
| 173 ifp->fGLProc.reset(fp.createGLSLInstance()); | |
| 174 | |
| 175 SkSTArray<4, GrGLSLTextureSampler> samplers(fp.numTextures()); | |
| 176 this->emitSamplers(fp, &samplers, ifp); | |
| 177 | |
| 178 GrGLSLFragmentProcessor::EmitArgs args(&fFS, | |
| 179 &fUniformHandler, | |
| 180 this->glslCaps(), | |
| 181 fp, | |
| 182 outColor, | |
| 183 inColor, | |
| 184 fOutCoords[index], | |
| 185 samplers); | |
| 186 ifp->fGLProc->emitCode(args); | |
| 187 | |
| 188 // We have to check that effects and the code they emit are consistent, ie i f an effect | |
| 189 // asks for dst color, then the emit code needs to follow suit | |
| 190 verify(fp); | |
| 191 fFragmentProcessors->fProcs.push_back(ifp); | |
| 192 } | |
| 193 | |
| 194 void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp, | |
| 195 const char* outColor, | |
| 196 const char* outCoverage) { | |
| 197 SkASSERT(!fGeometryProcessor); | |
| 198 fGeometryProcessor = new GrGLInstalledGeoProc; | |
| 199 | |
| 200 fGeometryProcessor->fGLProc.reset(gp.createGLSLInstance(*fGpu->glCaps().glsl Caps())); | |
| 201 | |
| 202 SkSTArray<4, GrGLSLTextureSampler> samplers(gp.numTextures()); | |
| 203 this->emitSamplers(gp, &samplers, fGeometryProcessor); | |
| 204 | |
| 205 GrGLSLGeometryProcessor::EmitArgs args(&fVS, | |
| 206 &fFS, | |
| 207 &fVaryingHandler, | |
| 208 &fUniformHandler, | |
| 209 this->glslCaps(), | |
| 210 gp, | |
| 211 outColor, | |
| 212 outCoverage, | |
| 213 samplers, | |
| 214 fCoordTransforms, | |
| 215 &fOutCoords); | |
| 216 fGeometryProcessor->fGLProc->emitCode(args); | |
| 217 | |
| 218 // We have to check that effects and the code they emit are consistent, ie i f an effect | |
| 219 // asks for dst color, then the emit code needs to follow suit | |
| 220 verify(gp); | |
| 221 } | |
| 222 | |
| 223 void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp, | |
| 224 const GrGLSLExpr4& colorIn, | |
| 225 const GrGLSLExpr4& coverageIn, | |
| 226 bool ignoresCoverage) { | |
| 227 // Program builders have a bit of state we need to clear with each effect | |
| 228 AutoStageAdvance adv(this); | |
| 229 | |
| 230 SkASSERT(!fXferProcessor); | |
| 231 fXferProcessor = new GrGLInstalledXferProc; | |
| 232 | |
| 233 fXferProcessor->fGLProc.reset(xp.createGLSLInstance()); | |
| 234 | |
| 235 // Enable dual source secondary output if we have one | |
| 236 if (xp.hasSecondaryOutput()) { | |
| 237 fFS.enableSecondaryOutput(); | |
| 238 } | |
| 239 | |
| 240 if (this->glslCaps()->mustDeclareFragmentShaderOutput()) { | |
| 241 fFS.enableCustomOutput(); | |
| 242 } | |
| 243 | |
| 244 SkString openBrace; | |
| 245 openBrace.printf("{ // Xfer Processor: %s\n", xp.name()); | |
| 246 fFS.codeAppend(openBrace.c_str()); | |
| 247 | |
| 248 SkSTArray<4, GrGLSLTextureSampler> samplers(xp.numTextures()); | |
| 249 this->emitSamplers(xp, &samplers, fXferProcessor); | |
| 250 | |
| 251 GrGLSLXferProcessor::EmitArgs args(&fFS, | |
| 252 &fUniformHandler, | |
| 253 this->glslCaps(), | |
| 254 xp, colorIn.c_str(), | |
| 255 ignoresCoverage ? nullptr : coverageIn.c_ str(), | |
| 256 fFS.getPrimaryColorOutputName(), | |
| 257 fFS.getSecondaryColorOutputName(), | |
| 258 samplers); | |
| 259 fXferProcessor->fGLProc->emitCode(args); | |
| 260 | |
| 261 // We have to check that effects and the code they emit are consistent, ie i f an effect | |
| 262 // asks for dst color, then the emit code needs to follow suit | |
| 263 verify(xp); | |
| 264 fFS.codeAppend("}"); | |
| 265 } | |
| 266 | |
| 267 void GrGLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) { | |
| 268 // Swizzle the fragment shader outputs if necessary. | |
| 269 GrSwizzle swizzle; | |
| 270 swizzle.setFromKey(this->desc().header().fOutputSwizzle); | |
| 271 if (swizzle != GrSwizzle::RGBA()) { | |
| 272 fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(), | |
| 273 fFS.getPrimaryColorOutputName(), | |
| 274 swizzle.c_str()); | |
| 275 if (hasSecondaryOutput) { | |
| 276 fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(), | |
| 277 fFS.getSecondaryColorOutputName(), | |
| 278 swizzle.c_str()); | |
| 279 } | |
| 280 } | |
| 281 } | |
| 282 | |
| 283 void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) { | |
| 284 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); | |
| 285 } | |
| 286 | |
| 287 void GrGLProgramBuilder::verify(const GrXferProcessor& xp) { | |
| 288 SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor()); | |
| 289 } | |
| 290 | |
| 291 void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) { | |
| 292 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition()); | |
| 293 } | 69 } |
| 294 | 70 |
| 295 static GrSLType get_sampler_type(const GrTextureAccess& access) { | 71 static GrSLType get_sampler_type(const GrTextureAccess& access) { |
| 296 GrGLTexture* glTexture = static_cast<GrGLTexture*>(access.getTexture()); | 72 GrGLTexture* glTexture = static_cast<GrGLTexture*>(access.getTexture()); |
| 297 if (glTexture->target() == GR_GL_TEXTURE_EXTERNAL) { | 73 if (glTexture->target() == GR_GL_TEXTURE_EXTERNAL) { |
| 298 return kSamplerExternal_GrSLType; | 74 return kSamplerExternal_GrSLType; |
| 299 } else { | 75 } else { |
| 300 SkASSERT(glTexture->target() == GR_GL_TEXTURE_2D); | 76 SkASSERT(glTexture->target() == GR_GL_TEXTURE_2D); |
| 301 return kSampler2D_GrSLType; | 77 return kSampler2D_GrSLType; |
| 302 } | 78 } |
| 303 } | 79 } |
| 304 | 80 |
| 305 template <class Proc> | |
| 306 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, | 81 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, |
| 307 GrGLSLTextureSampler::TextureSamplerArray* outSamplers, | 82 GrGLSLTextureSampler::TextureSamplerArra y* outSamplers) { |
|
bsalomon
2016/01/13 17:49:19
rm two spaces?
egdaniel
2016/01/13 19:59:49
Done.
| |
| 308 GrGLInstalledProc<Proc>* ip) { | |
| 309 SkDEBUGCODE(ip->fSamplersIdx = fSamplerUniforms.count();) | |
| 310 int numTextures = processor.numTextures(); | 83 int numTextures = processor.numTextures(); |
| 311 UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextur es); | 84 UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextur es); |
| 312 SkString name; | 85 SkString name; |
| 313 for (int t = 0; t < numTextures; ++t) { | 86 for (int t = 0; t < numTextures; ++t) { |
| 314 name.printf("Sampler%d", t); | 87 name.printf("Sampler%d", t); |
| 315 GrSLType samplerType = get_sampler_type(processor.textureAccess(t)); | 88 GrSLType samplerType = get_sampler_type(processor.textureAccess(t)); |
| 316 localSamplerUniforms[t] = | 89 localSamplerUniforms[t] = |
| 317 fUniformHandler.addUniform(GrGLSLUniformHandler::kFragment_Visibilit y, | 90 fUniformHandler.addUniform(GrGLSLUniformHandler::kFragment_Visibilit y, |
| 318 samplerType, kDefault_GrSLPrecision, | 91 samplerType, kDefault_GrSLPrecision, |
| 319 name.c_str()); | 92 name.c_str()); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 484 | 257 |
| 485 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { | 258 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { |
| 486 return new GrGLProgram(fGpu, | 259 return new GrGLProgram(fGpu, |
| 487 this->desc(), | 260 this->desc(), |
| 488 fUniformHandles, | 261 fUniformHandles, |
| 489 programID, | 262 programID, |
| 490 fUniformHandler.fUniforms, | 263 fUniformHandler.fUniforms, |
| 491 fVaryingHandler.fPathProcVaryingInfos, | 264 fVaryingHandler.fPathProcVaryingInfos, |
| 492 fGeometryProcessor, | 265 fGeometryProcessor, |
| 493 fXferProcessor, | 266 fXferProcessor, |
| 494 fFragmentProcessors.get(), | 267 fFragmentProcessors, |
| 495 &fSamplerUniforms); | 268 &fSamplerUniforms); |
| 496 } | 269 } |
| 497 | 270 |
| 498 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 499 | |
| 500 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { | |
| 501 int numProcs = fProcs.count(); | |
| 502 for (int i = 0; i < numProcs; ++i) { | |
| 503 delete fProcs[i]; | |
| 504 } | |
| 505 } | |
| OLD | NEW |