diff options
author | 2016-02-22 07:55:44 -0800 | |
---|---|---|
committer | 2016-02-22 07:55:44 -0800 | |
commit | 33ad701bc30387127c427fb1e38c781d5de33491 (patch) | |
tree | 09ab0b0a1c0ce1475f1c5a6c0ea6c35cb944e21f /src/gpu/glsl | |
parent | 23e7af0e8ab8377b28e1399b4950def672284724 (diff) |
Add gl_SampleMask functionality to fragment builders
Adds methods for overriding and masking a fragment's sample mask.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1690963003
Committed: https://skia.googlesource.com/skia/+/533cefe5b9c7cec2592fc7ca00ee4cf69a26c094
Review URL: https://codereview.chromium.org/1690963003
Diffstat (limited to 'src/gpu/glsl')
-rw-r--r-- | src/gpu/glsl/GrGLSL.cpp | 2 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSL.h | 8 | ||||
-rwxr-xr-x | src/gpu/glsl/GrGLSLCaps.cpp | 6 | ||||
-rwxr-xr-x | src/gpu/glsl/GrGLSLCaps.h | 14 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp | 42 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLFragmentShaderBuilder.h | 28 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLShaderBuilder.cpp | 10 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLShaderBuilder.h | 8 |
8 files changed, 111 insertions, 7 deletions
diff --git a/src/gpu/glsl/GrGLSL.cpp b/src/gpu/glsl/GrGLSL.cpp index 2de81ddd60..bec4784db2 100644 --- a/src/gpu/glsl/GrGLSL.cpp +++ b/src/gpu/glsl/GrGLSL.cpp @@ -17,7 +17,9 @@ bool GrGLSLSupportsNamedFragmentShaderOutputs(GrGLSLGeneration gen) { case k140_GrGLSLGeneration: case k150_GrGLSLGeneration: case k330_GrGLSLGeneration: + case k400_GrGLSLGeneration: case k310es_GrGLSLGeneration: + case k320es_GrGLSLGeneration: return true; } return false; diff --git a/src/gpu/glsl/GrGLSL.h b/src/gpu/glsl/GrGLSL.h index 6fc8f83c7a..b13113a289 100644 --- a/src/gpu/glsl/GrGLSL.h +++ b/src/gpu/glsl/GrGLSL.h @@ -37,9 +37,17 @@ enum GrGLSLGeneration { */ k330_GrGLSLGeneration, /** + * Desktop GLSL 4.00 + */ + k400_GrGLSLGeneration, + /** * ES GLSL 3.10 only TODO Make GLSLCap objects to make this more granular */ k310es_GrGLSLGeneration, + /** + * ES GLSL 3.20 + */ + k320es_GrGLSLGeneration, }; bool GrGLSLSupportsNamedFragmentShaderOutputs(GrGLSLGeneration); diff --git a/src/gpu/glsl/GrGLSLCaps.cpp b/src/gpu/glsl/GrGLSLCaps.cpp index ba99be57e2..0aa3e4ffea 100755 --- a/src/gpu/glsl/GrGLSLCaps.cpp +++ b/src/gpu/glsl/GrGLSLCaps.cpp @@ -25,12 +25,15 @@ GrGLSLCaps::GrGLSLCaps(const GrContextOptions& options) { fMustForceNegatedAtanParamToFloat = false; fFlatInterpolationSupport = false; fNoPerspectiveInterpolationSupport = false; + fSampleVariablesSupport = false; + fSampleMaskOverrideCoverageSupport = false; fVersionDeclString = nullptr; fShaderDerivativeExtensionString = nullptr; fFragCoordConventionsExtensionString = nullptr; fSecondaryOutputExtensionString = nullptr; fExternalTextureExtensionString = nullptr; fNoPerspectiveInterpolationExtensionString = nullptr; + fSampleVariablesExtensionString = nullptr; fFBFetchColorName = nullptr; fFBFetchExtensionString = nullptr; fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction; @@ -64,6 +67,9 @@ SkString GrGLSLCaps::dump() const { r.appendf("Flat interpolation support: %s\n", (fFlatInterpolationSupport ? "YES" : "NO")); r.appendf("No perspective interpolation support: %s\n", (fNoPerspectiveInterpolationSupport ? "YES" : "NO")); + r.appendf("Sample variables support: %s\n", (fSampleVariablesSupport ? "YES" : "NO")); + r.appendf("Sample mask override coverage support: %s\n", (fSampleMaskOverrideCoverageSupport ? + "YES" : "NO")); r.appendf("Advanced blend equation interaction: %s\n", kAdvBlendEqInteractionStr[fAdvBlendEqInteraction]); return r; diff --git a/src/gpu/glsl/GrGLSLCaps.h b/src/gpu/glsl/GrGLSLCaps.h index 2f87f66850..914b0dbb4c 100755 --- a/src/gpu/glsl/GrGLSLCaps.h +++ b/src/gpu/glsl/GrGLSLCaps.h @@ -58,6 +58,10 @@ public: bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; } + bool sampleVariablesSupport() const { return fSampleVariablesSupport; } + + bool sampleMaskOverrideCoverageSupport() const { return fSampleMaskOverrideCoverageSupport; } + AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; } bool mustEnableAdvBlendEqs() const { @@ -88,7 +92,7 @@ public: SkASSERT(this->shaderDerivativeSupport()); return fShaderDerivativeExtensionString; } - + // Returns the string of an extension that will do all necessary coord transfomations needed // when reading the fragment position. If such an extension does not exisits, this function // returns a nullptr, and all transforms of the frag position must be done manually in the @@ -114,6 +118,11 @@ public: return fNoPerspectiveInterpolationExtensionString; } + const char* sampleVariablesExtensionString() const { + SkASSERT(this->sampleVariablesSupport()); + return fSampleVariablesExtensionString; + } + /** * Given a texture's config, this determines what swizzle must be appended to accesses to the * texture in generated shader code. Swizzling may be implemented in texture parameters or a @@ -148,6 +157,8 @@ private: bool fCanUseAnyFunctionInShader : 1; bool fFlatInterpolationSupport : 1; bool fNoPerspectiveInterpolationSupport : 1; + bool fSampleVariablesSupport : 1; + bool fSampleMaskOverrideCoverageSupport : 1; // Used for specific driver bug work arounds bool fCanUseMinAndAbsTogether : 1; @@ -160,6 +171,7 @@ private: const char* fSecondaryOutputExtensionString; const char* fExternalTextureExtensionString; const char* fNoPerspectiveInterpolationExtensionString; + const char* fSampleVariablesExtensionString; const char* fFBFetchColorName; const char* fFBFetchExtensionString; diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp index 4277cf4a76..44db57e68d 100644 --- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp +++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp @@ -74,6 +74,7 @@ GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* p , fHasCustomColorOutput(false) , fCustomColorOutputIndex(-1) , fHasSecondaryOutput(false) + , fHasInitializedSampleMask(false) , fHasReadDstColor(false) , fHasReadFragmentPosition(false) { fSubstageIndices.push_back(0); @@ -169,6 +170,47 @@ const char* GrGLSLFragmentShaderBuilder::fragmentPosition() { } } +void GrGLSLFragmentShaderBuilder::maskSampleCoverage(const char* mask, bool invert) { + const GrGLSLCaps& glslCaps = *fProgramBuilder->glslCaps(); + if (!glslCaps.sampleVariablesSupport()) { + SkDEBUGFAIL("Attempted to mask sample coverage without support."); + return; + } + if (const char* extension = glslCaps.sampleVariablesExtensionString()) { + this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension); + } + if (!fHasInitializedSampleMask) { + this->codePrependf("gl_SampleMask[0] = -1;"); + fHasInitializedSampleMask = true; + } + if (invert) { + this->codeAppendf("gl_SampleMask[0] &= ~(%s);", mask); + } else { + this->codeAppendf("gl_SampleMask[0] &= %s;", mask); + } +} + +void GrGLSLFragmentShaderBuilder::overrideSampleCoverage(const char* mask) { + const GrGLSLCaps& glslCaps = *fProgramBuilder->glslCaps(); + if (!glslCaps.sampleMaskOverrideCoverageSupport()) { + SkDEBUGFAIL("Attempted to override sample coverage without support."); + return; + } + SkASSERT(glslCaps.sampleVariablesSupport()); + if (const char* extension = glslCaps.sampleVariablesExtensionString()) { + this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension); + } + if (this->addFeature(1 << kSampleMaskOverrideCoverage_GLSLPrivateFeature, + "GL_NV_sample_mask_override_coverage")) { + // Redeclare gl_SampleMask with layout(override_coverage) if we haven't already. + fOutputs.push_back().set(kInt_GrSLType, GrShaderVar::kOut_TypeModifier, + "gl_SampleMask", 1, kHigh_GrSLPrecision, + "override_coverage"); + } + this->codeAppendf("gl_SampleMask[0] = %s;", mask); + fHasInitializedSampleMask = true; +} + const char* GrGLSLFragmentShaderBuilder::dstColor() { fHasReadDstColor = true; diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h index 4dab6f2a09..b9816af71a 100644 --- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h +++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h @@ -67,6 +67,17 @@ public: GrGLSLFPFragmentBuilder() : GrGLSLFragmentBuilder(nullptr) {} /** + * Subtracts sample coverage from the fragment. Any sample whose corresponding bit is not found + * in the mask will not be written out to the framebuffer. + * + * @param mask int that contains the sample mask. Bit N corresponds to the Nth sample. + * @param invert perform a bit-wise NOT on the provided mask before applying it? + * + * Requires GLSL support for sample variables. + */ + virtual void maskSampleCoverage(const char* mask, bool invert = false) = 0; + + /** * Fragment procs with child procs should call these functions before/after calling emitCode * on a child proc. */ @@ -83,6 +94,20 @@ class GrGLSLPPFragmentBuilder : public GrGLSLFPFragmentBuilder { public: /** Appease the compiler; the derived class initializes GrGLSLFragmentBuilder. */ GrGLSLPPFragmentBuilder() : GrGLSLFragmentBuilder(nullptr) {} + + /** + * Overrides the fragment's sample coverage. The provided mask determines which samples will now + * be written out to the framebuffer. Note that this mask can be reduced by a future call to + * maskSampleCoverage. + * + * If a primitive processor uses this method, it must guarantee that every codepath through the + * shader overrides the sample mask at some point. + * + * @param mask int that contains the new coverage mask. Bit N corresponds to the Nth sample. + * + * Requires NV_sample_mask_override_coverage. + */ + virtual void overrideSampleCoverage(const char* mask) = 0; }; /* @@ -127,6 +152,8 @@ public: const char* fragmentPosition() override; // GrGLSLFPFragmentBuilder interface. + void maskSampleCoverage(const char* mask, bool invert = false) override; + void overrideSampleCoverage(const char* mask) override; const SkString& getMangleString() const override { return fMangleString; } void onBeforeChildProcEmitCode() override; void onAfterChildProcEmitCode() override; @@ -197,6 +224,7 @@ private: bool fHasCustomColorOutput; int fCustomColorOutputIndex; bool fHasSecondaryOutput; + bool fHasInitializedSampleMask; // some state to verify shaders and effects are consistent, this is reset between effects by // the program creator diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.cpp b/src/gpu/glsl/GrGLSLShaderBuilder.cpp index c94a85534f..30bf86d210 100644 --- a/src/gpu/glsl/GrGLSLShaderBuilder.cpp +++ b/src/gpu/glsl/GrGLSLShaderBuilder.cpp @@ -112,11 +112,13 @@ void GrGLSLShaderBuilder::appendTextureLookupAndModulate(const char* modulation, this->codeAppend((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str()); } -void GrGLSLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) { - if (!(featureBit & fFeaturesAddedMask)) { - this->extensions().appendf("#extension %s: require\n", extensionName); - fFeaturesAddedMask |= featureBit; +bool GrGLSLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) { + if (featureBit & fFeaturesAddedMask) { + return false; } + this->extensions().appendf("#extension %s: require\n", extensionName); + fFeaturesAddedMask |= featureBit; + return true; } void GrGLSLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const { diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h index bc3b4ca717..7bfc610bde 100644 --- a/src/gpu/glsl/GrGLSLShaderBuilder.h +++ b/src/gpu/glsl/GrGLSLShaderBuilder.h @@ -152,13 +152,17 @@ protected: kExternalTexture_GLSLPrivateFeature, kFramebufferFetch_GLSLPrivateFeature, kNoPerspectiveInterpolation_GLSLPrivateFeature, - kLastGLSLPrivateFeature = kNoPerspectiveInterpolation_GLSLPrivateFeature + kSampleVariables_GLSLPrivateFeature, + kSampleMaskOverrideCoverage_GLSLPrivateFeature, + kLastGLSLPrivateFeature = kSampleMaskOverrideCoverage_GLSLPrivateFeature }; /* * A general function which enables an extension in a shader if the feature bit is not present + * + * @return true if the feature bit was not yet present, false otherwise. */ - void addFeature(uint32_t featureBit, const char* extensionName); + bool addFeature(uint32_t featureBit, const char* extensionName); enum InterfaceQualifier { kOut_InterfaceQualifier, |