| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 "glsl/GrGLSLProgramBuilder.h" | 8 #include "glsl/GrGLSLProgramBuilder.h" |
| 9 | 9 |
| 10 #include "GrPipeline.h" | 10 #include "GrPipeline.h" |
| 11 #include "glsl/GrGLSLFragmentProcessor.h" | 11 #include "glsl/GrGLSLFragmentProcessor.h" |
| 12 #include "glsl/GrGLSLGeometryProcessor.h" | 12 #include "glsl/GrGLSLGeometryProcessor.h" |
| 13 #include "glsl/GrGLSLVarying.h" | 13 #include "glsl/GrGLSLVarying.h" |
| 14 #include "glsl/GrGLSLXferProcessor.h" | 14 #include "glsl/GrGLSLXferProcessor.h" |
| 15 | 15 |
| 16 const int GrGLSLProgramBuilder::kVarsPerBlock = 8; | 16 const int GrGLSLProgramBuilder::kVarsPerBlock = 8; |
| 17 | 17 |
| 18 GrGLSLProgramBuilder::GrGLSLProgramBuilder(const DrawArgs& args) | 18 GrGLSLProgramBuilder::GrGLSLProgramBuilder(const DrawArgs& args) |
| 19 : fVS(this) | 19 : fVS(this) |
| 20 , fGS(this) | 20 , fGS(this) |
| 21 , fFS(this) | 21 , fFS(this) |
| 22 , fStageIndex(-1) | 22 , fStageIndex(-1) |
| 23 , fArgs(args) | 23 , fArgs(args) |
| 24 , fGeometryProcessor(nullptr) | 24 , fGeometryProcessor(nullptr) |
| 25 , fXferProcessor(nullptr) { | 25 , fXferProcessor(nullptr) |
| 26 , fSamplerUniforms(4) |
| 27 , fNumVertexSamplers(0) |
| 28 , fNumGeometrySamplers(0) |
| 29 , fNumFragmentSamplers(0) { |
| 30 } |
| 31 |
| 32 void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders, |
| 33 uint32_t featureBit, |
| 34 const char* extensionName) { |
| 35 if (shaders & kVertex_GrShaderFlag) { |
| 36 fVS.addFeature(featureBit, extensionName); |
| 37 } |
| 38 if (shaders & kGeometry_GrShaderFlag) { |
| 39 SkASSERT(this->glslCaps()->geometryShaderSupport()); |
| 40 fGS.addFeature(featureBit, extensionName); |
| 41 } |
| 42 if (shaders & kFragment_GrShaderFlag) { |
| 43 fFS.addFeature(featureBit, extensionName); |
| 44 } |
| 26 } | 45 } |
| 27 | 46 |
| 28 bool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, | 47 bool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, |
| 29 GrGLSLExpr4* inputCoverage, | 48 GrGLSLExpr4* inputCoverage) { |
| 30 int maxTextures) { | |
| 31 // First we loop over all of the installed processors and collect coord tran
sforms. These will | 49 // First we loop over all of the installed processors and collect coord tran
sforms. These will |
| 32 // be sent to the GrGLSLPrimitiveProcessor in its emitCode function | 50 // be sent to the GrGLSLPrimitiveProcessor in its emitCode function |
| 33 const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); | 51 const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); |
| 34 int totalTextures = primProc.numTextures(); | |
| 35 | 52 |
| 36 for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) { | 53 for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) { |
| 37 const GrFragmentProcessor& processor = this->pipeline().getFragmentProce
ssor(i); | 54 const GrFragmentProcessor& processor = this->pipeline().getFragmentProce
ssor(i); |
| 38 | 55 |
| 39 if (!primProc.hasTransformedLocalCoords()) { | 56 if (!primProc.hasTransformedLocalCoords()) { |
| 40 SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransfor
ms.push_back(); | 57 SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransfor
ms.push_back(); |
| 41 processor.gatherCoordTransforms(&procCoords); | 58 processor.gatherCoordTransforms(&procCoords); |
| 42 } | 59 } |
| 43 | |
| 44 totalTextures += processor.numTextures(); | |
| 45 if (totalTextures >= maxTextures) { | |
| 46 GrCapsDebugf(this->caps(), "Program would use too many texture units
\n"); | |
| 47 return false; | |
| 48 } | |
| 49 } | 60 } |
| 50 | 61 |
| 51 this->emitAndInstallPrimProc(primProc, inputColor, inputCoverage); | 62 this->emitAndInstallPrimProc(primProc, inputColor, inputCoverage); |
| 52 | 63 |
| 53 int numProcs = this->pipeline().numFragmentProcessors(); | 64 int numProcs = this->pipeline().numFragmentProcessors(); |
| 54 this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors
(), inputColor); | 65 this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors
(), inputColor); |
| 55 this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(),
numProcs, | 66 this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(),
numProcs, |
| 56 inputCoverage); | 67 inputCoverage); |
| 57 if (primProc.getPixelLocalStorageState() != | 68 if (primProc.getPixelLocalStorageState() != |
| 58 GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) { | 69 GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) { |
| 59 this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *input
Color, | 70 this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *input
Color, |
| 60 *inputCoverage, this->pipeline().ignoresCov
erage(), | 71 *inputCoverage, this->pipeline().ignoresCov
erage(), |
| 61 primProc.getPixelLocalStorageState()); | 72 primProc.getPixelLocalStorageState()); |
| 62 this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSeconda
ryOutput()); | 73 this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSeconda
ryOutput()); |
| 63 } | 74 } |
| 64 return true; | 75 |
| 76 return this->checkSamplerCounts(); |
| 65 } | 77 } |
| 66 | 78 |
| 67 void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
oc, | 79 void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
oc, |
| 68 GrGLSLExpr4* outputColor, | 80 GrGLSLExpr4* outputColor, |
| 69 GrGLSLExpr4* outputCoverage) { | 81 GrGLSLExpr4* outputCoverage) { |
| 70 // Program builders have a bit of state we need to clear with each effect | 82 // Program builders have a bit of state we need to clear with each effect |
| 71 AutoStageAdvance adv(this); | 83 AutoStageAdvance adv(this); |
| 72 this->nameExpression(outputColor, "outputColor"); | 84 this->nameExpression(outputColor, "outputColor"); |
| 73 this->nameExpression(outputCoverage, "outputCoverage"); | 85 this->nameExpression(outputCoverage, "outputCoverage"); |
| 74 | 86 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 samplers, | 203 samplers, |
| 192 usePLSDstRead); | 204 usePLSDstRead); |
| 193 fXferProcessor->emitCode(args); | 205 fXferProcessor->emitCode(args); |
| 194 | 206 |
| 195 // We have to check that effects and the code they emit are consistent, ie i
f an effect | 207 // We have to check that effects and the code they emit are consistent, ie i
f an effect |
| 196 // asks for dst color, then the emit code needs to follow suit | 208 // asks for dst color, then the emit code needs to follow suit |
| 197 SkDEBUGCODE(verify(xp);) | 209 SkDEBUGCODE(verify(xp);) |
| 198 fFS.codeAppend("}"); | 210 fFS.codeAppend("}"); |
| 199 } | 211 } |
| 200 | 212 |
| 213 void GrGLSLProgramBuilder::emitSamplers(const GrProcessor& processor, |
| 214 GrGLSLTextureSampler::TextureSamplerArra
y* outSamplers) { |
| 215 int numTextures = processor.numTextures(); |
| 216 UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextur
es); |
| 217 SkString name; |
| 218 for (int t = 0; t < numTextures; ++t) { |
| 219 const GrTextureAccess& access = processor.textureAccess(t); |
| 220 GrShaderFlags visibility = access.getVisibility(); |
| 221 if (visibility & kVertex_GrShaderFlag) { |
| 222 ++fNumVertexSamplers; |
| 223 } |
| 224 if (visibility & kGeometry_GrShaderFlag) { |
| 225 SkASSERT(this->primitiveProcessor().willUseGeoShader()); |
| 226 ++fNumGeometrySamplers; |
| 227 } |
| 228 if (visibility & kFragment_GrShaderFlag) { |
| 229 ++fNumFragmentSamplers; |
| 230 } |
| 231 GrSLType samplerType = access.getTexture()->samplerType(); |
| 232 if (kSamplerExternal_GrSLType == samplerType) { |
| 233 const char* externalFeatureString = this->glslCaps()->externalTextur
eExtensionString(); |
| 234 // We shouldn't ever create a GrGLTexture that requires external sam
pler type |
| 235 SkASSERT(externalFeatureString); |
| 236 this->addFeature(visibility, |
| 237 1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPriv
ateFeature, |
| 238 externalFeatureString); |
| 239 } |
| 240 name.printf("Sampler%d", t); |
| 241 localSamplerUniforms[t] = this->uniformHandler()->addUniform(access.getV
isibility(), |
| 242 samplerType
, |
| 243 kDefault_Gr
SLPrecision, |
| 244 name.c_str(
)); |
| 245 outSamplers->emplace_back(localSamplerUniforms[t], access); |
| 246 } |
| 247 } |
| 248 |
| 201 void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) { | 249 void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) { |
| 202 // Swizzle the fragment shader outputs if necessary. | 250 // Swizzle the fragment shader outputs if necessary. |
| 203 GrSwizzle swizzle; | 251 GrSwizzle swizzle; |
| 204 swizzle.setFromKey(this->desc().header().fOutputSwizzle); | 252 swizzle.setFromKey(this->desc().header().fOutputSwizzle); |
| 205 if (swizzle != GrSwizzle::RGBA()) { | 253 if (swizzle != GrSwizzle::RGBA()) { |
| 206 fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(), | 254 fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(), |
| 207 fFS.getPrimaryColorOutputName(), | 255 fFS.getPrimaryColorOutputName(), |
| 208 swizzle.c_str()); | 256 swizzle.c_str()); |
| 209 if (hasSecondaryOutput) { | 257 if (hasSecondaryOutput) { |
| 210 fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(), | 258 fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(), |
| 211 fFS.getSecondaryColorOutputName(), | 259 fFS.getSecondaryColorOutputName(), |
| 212 swizzle.c_str()); | 260 swizzle.c_str()); |
| 213 } | 261 } |
| 214 } | 262 } |
| 215 } | 263 } |
| 216 | 264 |
| 265 bool GrGLSLProgramBuilder::checkSamplerCounts() { |
| 266 const GrGLSLCaps& glslCaps = *this->glslCaps(); |
| 267 if (fNumVertexSamplers > glslCaps.maxVertexSamplers()) { |
| 268 GrCapsDebugf(this->caps(), "Program would use too many vertex samplers\n
"); |
| 269 return false; |
| 270 } |
| 271 if (fNumGeometrySamplers > glslCaps.maxGeometrySamplers()) { |
| 272 GrCapsDebugf(this->caps(), "Program would use too many geometry samplers
\n"); |
| 273 return false; |
| 274 } |
| 275 if (fNumFragmentSamplers > glslCaps.maxFragmentSamplers()) { |
| 276 GrCapsDebugf(this->caps(), "Program would use too many fragment samplers
\n"); |
| 277 return false; |
| 278 } |
| 279 // If the same sampler is used in two different shaders, it counts as two co
mbined samplers. |
| 280 int numCombinedSamplers = fNumVertexSamplers + fNumGeometrySamplers + fNumFr
agmentSamplers; |
| 281 if (numCombinedSamplers > glslCaps.maxCombinedSamplers()) { |
| 282 GrCapsDebugf(this->caps(), "Program would use too many combined samplers
\n"); |
| 283 return false; |
| 284 } |
| 285 return true; |
| 286 } |
| 287 |
| 217 #ifdef SK_DEBUG | 288 #ifdef SK_DEBUG |
| 218 void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) { | 289 void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) { |
| 219 SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures()); | 290 SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures()); |
| 220 } | 291 } |
| 221 | 292 |
| 222 void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) { | 293 void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) { |
| 223 SkASSERT(fFS.usedProcessorFeatures() == xp.requiredFeatures()); | 294 SkASSERT(fFS.usedProcessorFeatures() == xp.requiredFeatures()); |
| 224 SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor()); | 295 SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor()); |
| 225 } | 296 } |
| 226 | 297 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 delete fFragmentProcessors[i]; | 359 delete fFragmentProcessors[i]; |
| 289 } | 360 } |
| 290 } | 361 } |
| 291 | 362 |
| 292 void GrGLSLProgramBuilder::finalizeShaders() { | 363 void GrGLSLProgramBuilder::finalizeShaders() { |
| 293 this->varyingHandler()->finalize(); | 364 this->varyingHandler()->finalize(); |
| 294 fVS.finalize(kVertex_GrShaderFlag); | 365 fVS.finalize(kVertex_GrShaderFlag); |
| 295 fFS.finalize(kFragment_GrShaderFlag); | 366 fFS.finalize(kFragment_GrShaderFlag); |
| 296 | 367 |
| 297 } | 368 } |
| OLD | NEW |