aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/glsl
diff options
context:
space:
mode:
authorGravatar cdalton <cdalton@nvidia.com>2016-02-22 07:55:44 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-02-22 07:55:44 -0800
commit33ad701bc30387127c427fb1e38c781d5de33491 (patch)
tree09ab0b0a1c0ce1475f1c5a6c0ea6c35cb944e21f /src/gpu/glsl
parent23e7af0e8ab8377b28e1399b4950def672284724 (diff)
Add gl_SampleMask functionality to fragment builders
Diffstat (limited to 'src/gpu/glsl')
-rw-r--r--src/gpu/glsl/GrGLSL.cpp2
-rw-r--r--src/gpu/glsl/GrGLSL.h8
-rwxr-xr-xsrc/gpu/glsl/GrGLSLCaps.cpp6
-rwxr-xr-xsrc/gpu/glsl/GrGLSLCaps.h14
-rw-r--r--src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp42
-rw-r--r--src/gpu/glsl/GrGLSLFragmentShaderBuilder.h28
-rw-r--r--src/gpu/glsl/GrGLSLShaderBuilder.cpp10
-rw-r--r--src/gpu/glsl/GrGLSLShaderBuilder.h8
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,