aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/glsl/GrGLSLProgramBuilder.cpp
diff options
context:
space:
mode:
authorGravatar cdalton <cdalton@nvidia.com>2016-03-11 10:07:37 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-03-11 10:07:37 -0800
commit9c3f14327a38e79ab7d0cf30dfd9bf89676fde06 (patch)
treef4695cc85cf19bf471ed8c956083f2234f18d4e1 /src/gpu/glsl/GrGLSLProgramBuilder.cpp
parent6b563156eb7ce05b51997695ec9ab2aedcc2e6b1 (diff)
Add support for vertex and geometry shader textures
Adds a visibility bitfield to GrTextureAccess that controls in which shaders the texture should be accessible. Also adds caps and validation to ensure we don't exceed texture limits. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1782583002 Review URL: https://codereview.chromium.org/1782583002
Diffstat (limited to 'src/gpu/glsl/GrGLSLProgramBuilder.cpp')
-rw-r--r--src/gpu/glsl/GrGLSLProgramBuilder.cpp93
1 files changed, 82 insertions, 11 deletions
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index b9eaca4153..bc0208321c 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -22,16 +22,33 @@ GrGLSLProgramBuilder::GrGLSLProgramBuilder(const DrawArgs& args)
, fStageIndex(-1)
, fArgs(args)
, fGeometryProcessor(nullptr)
- , fXferProcessor(nullptr) {
+ , fXferProcessor(nullptr)
+ , fSamplerUniforms(4)
+ , fNumVertexSamplers(0)
+ , fNumGeometrySamplers(0)
+ , fNumFragmentSamplers(0) {
+}
+
+void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders,
+ uint32_t featureBit,
+ const char* extensionName) {
+ if (shaders & kVertex_GrShaderFlag) {
+ fVS.addFeature(featureBit, extensionName);
+ }
+ if (shaders & kGeometry_GrShaderFlag) {
+ SkASSERT(this->glslCaps()->geometryShaderSupport());
+ fGS.addFeature(featureBit, extensionName);
+ }
+ if (shaders & kFragment_GrShaderFlag) {
+ fFS.addFeature(featureBit, extensionName);
+ }
}
bool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor,
- GrGLSLExpr4* inputCoverage,
- int maxTextures) {
+ GrGLSLExpr4* inputCoverage) {
// First we loop over all of the installed processors and collect coord transforms. These will
// be sent to the GrGLSLPrimitiveProcessor in its emitCode function
const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
- int totalTextures = primProc.numTextures();
for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) {
const GrFragmentProcessor& processor = this->pipeline().getFragmentProcessor(i);
@@ -40,12 +57,6 @@ bool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor,
SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back();
processor.gatherCoordTransforms(&procCoords);
}
-
- totalTextures += processor.numTextures();
- if (totalTextures >= maxTextures) {
- GrCapsDebugf(this->caps(), "Program would use too many texture units\n");
- return false;
- }
}
this->emitAndInstallPrimProc(primProc, inputColor, inputCoverage);
@@ -61,7 +72,8 @@ bool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor,
primProc.getPixelLocalStorageState());
this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput());
}
- return true;
+
+ return this->checkSamplerCounts();
}
void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& proc,
@@ -198,6 +210,42 @@ void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
fFS.codeAppend("}");
}
+void GrGLSLProgramBuilder::emitSamplers(const GrProcessor& processor,
+ GrGLSLTextureSampler::TextureSamplerArray* outSamplers) {
+ int numTextures = processor.numTextures();
+ UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextures);
+ SkString name;
+ for (int t = 0; t < numTextures; ++t) {
+ const GrTextureAccess& access = processor.textureAccess(t);
+ GrShaderFlags visibility = access.getVisibility();
+ if (visibility & kVertex_GrShaderFlag) {
+ ++fNumVertexSamplers;
+ }
+ if (visibility & kGeometry_GrShaderFlag) {
+ SkASSERT(this->primitiveProcessor().willUseGeoShader());
+ ++fNumGeometrySamplers;
+ }
+ if (visibility & kFragment_GrShaderFlag) {
+ ++fNumFragmentSamplers;
+ }
+ GrSLType samplerType = access.getTexture()->samplerType();
+ if (kSamplerExternal_GrSLType == samplerType) {
+ const char* externalFeatureString = this->glslCaps()->externalTextureExtensionString();
+ // We shouldn't ever create a GrGLTexture that requires external sampler type
+ SkASSERT(externalFeatureString);
+ this->addFeature(visibility,
+ 1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPrivateFeature,
+ externalFeatureString);
+ }
+ name.printf("Sampler%d", t);
+ localSamplerUniforms[t] = this->uniformHandler()->addUniform(access.getVisibility(),
+ samplerType,
+ kDefault_GrSLPrecision,
+ name.c_str());
+ outSamplers->emplace_back(localSamplerUniforms[t], access);
+ }
+}
+
void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
// Swizzle the fragment shader outputs if necessary.
GrSwizzle swizzle;
@@ -214,6 +262,29 @@ void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
}
}
+bool GrGLSLProgramBuilder::checkSamplerCounts() {
+ const GrGLSLCaps& glslCaps = *this->glslCaps();
+ if (fNumVertexSamplers > glslCaps.maxVertexSamplers()) {
+ GrCapsDebugf(this->caps(), "Program would use too many vertex samplers\n");
+ return false;
+ }
+ if (fNumGeometrySamplers > glslCaps.maxGeometrySamplers()) {
+ GrCapsDebugf(this->caps(), "Program would use too many geometry samplers\n");
+ return false;
+ }
+ if (fNumFragmentSamplers > glslCaps.maxFragmentSamplers()) {
+ GrCapsDebugf(this->caps(), "Program would use too many fragment samplers\n");
+ return false;
+ }
+ // If the same sampler is used in two different shaders, it counts as two combined samplers.
+ int numCombinedSamplers = fNumVertexSamplers + fNumGeometrySamplers + fNumFragmentSamplers;
+ if (numCombinedSamplers > glslCaps.maxCombinedSamplers()) {
+ GrCapsDebugf(this->caps(), "Program would use too many combined samplers\n");
+ return false;
+ }
+ return true;
+}
+
#ifdef SK_DEBUG
void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures());