aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/glsl
diff options
context:
space:
mode:
authorGravatar cdalton <cdalton@nvidia.com>2016-03-07 13:58:26 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-03-07 13:58:26 -0800
commit28f45b949acc746849100fbe112ee5280f0594c9 (patch)
treeb350d442680ef996ab6097433ab0cf960d3680b6 /src/gpu/glsl
parentb3b13b7edeabad4c8e53b0d309b0a44668d1e68f (diff)
Add "sample locations" feature to GrProcessor
Adds a "sample locations" feature to GrProcessor. When enabled, this allows a processor to know inside the shader where all the samples are located. Also adds various infastructure to query, cache, and identify multisample data. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1717393002 Review URL: https://codereview.chromium.org/1717393002
Diffstat (limited to 'src/gpu/glsl')
-rw-r--r--src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp88
-rw-r--r--src/gpu/glsl/GrGLSLFragmentShaderBuilder.h56
-rw-r--r--src/gpu/glsl/GrGLSLProgramBuilder.cpp2
3 files changed, 103 insertions, 43 deletions
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index e6717a9e4d..166e474434 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -7,6 +7,7 @@
#include "GrGLSLFragmentShaderBuilder.h"
#include "GrRenderTarget.h"
+#include "GrRenderTargetPriv.h"
#include "gl/GrGLGpu.h"
#include "glsl/GrGLSL.h"
#include "glsl/GrGLSLCaps.h"
@@ -16,6 +17,18 @@
const char* GrGLSLFragmentShaderBuilder::kDstTextureColorName = "_dstColor";
+static const char* sample_offset_array_name(GrGLSLFPFragmentBuilder::Coordinates coords) {
+ static const char* kArrayNames[] = {
+ "deviceSpaceSampleOffsets",
+ "windowSpaceSampleOffsets"
+ };
+ return kArrayNames[coords];
+
+ GR_STATIC_ASSERT(0 == GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates);
+ GR_STATIC_ASSERT(1 == GrGLSLFPFragmentBuilder::kGLSLWindow_Coordinates);
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(kArrayNames) == GrGLSLFPFragmentBuilder::kLast_Coordinates + 1);
+}
+
static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
SkASSERT(GrBlendEquationIsAdvanced(equation));
@@ -57,23 +70,21 @@ static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation);
}
-GrGLSLFragmentShaderBuilder::FragPosKey
-GrGLSLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst) {
- if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
- return kTopLeftFragPosRead_FragPosKey;
- } else {
- return kBottomLeftFragPosRead_FragPosKey;
- }
+uint8_t GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(GrSurfaceOrigin origin) {
+ SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin == origin);
+ return origin;
+
+ GR_STATIC_ASSERT(1 == kTopLeft_GrSurfaceOrigin);
+ GR_STATIC_ASSERT(2 == kBottomLeft_GrSurfaceOrigin);
}
-GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program,
- uint8_t fragPosKey)
+GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program)
: GrGLSLFragmentBuilder(program)
, fSetupFragPosition(false)
- , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey)
, fHasCustomColorOutput(false)
, fCustomColorOutputIndex(-1)
, fHasSecondaryOutput(false)
+ , fUsedSampleOffsetArrays(0)
, fHasInitializedSampleMask(false) {
fSubstageIndices.push_back(0);
#ifdef SK_DEBUG
@@ -82,10 +93,6 @@ GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* p
#endif
}
-bool GrGLSLFragmentShaderBuilder::hasFragmentPosition() const {
- return 0 != fProgramBuilder->header().fFragPosKey;
-}
-
bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
const GrGLSLCaps& glslCaps = *fProgramBuilder->glslCaps();
switch (feature) {
@@ -135,14 +142,13 @@ SkString GrGLSLFragmentShaderBuilder::ensureFSCoords2D(const GrGLSLTransformedCo
}
const char* GrGLSLFragmentShaderBuilder::fragmentPosition() {
- SkASSERT(this->hasFragmentPosition());
SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kFragmentPosition_RequiredFeature;)
const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps();
// We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
// to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
// declaration varies in earlier GLSL specs. So it is simpler to omit it.
- if (fTopLeftFragPosRead) {
+ if (kTopLeft_GrSurfaceOrigin == this->getSurfaceOrigin()) {
fSetupFragPosition = true;
return "gl_FragCoord";
} else if (const char* extension = glslCaps->fragCoordConventionsExtensionString()) {
@@ -183,6 +189,17 @@ const char* GrGLSLFragmentShaderBuilder::fragmentPosition() {
}
}
+void GrGLSLFragmentShaderBuilder::appendOffsetToSample(const char* sampleIdx, Coordinates coords) {
+ SkASSERT(fProgramBuilder->header().fSamplePatternKey);
+ SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kSampleLocations_RequiredFeature);
+ if (kTopLeft_GrSurfaceOrigin == this->getSurfaceOrigin()) {
+ // With a top left origin, device and window space are equal, so we only use device coords.
+ coords = kSkiaDevice_Coordinates;
+ }
+ this->codeAppendf("%s[%s]", sample_offset_array_name(coords), sampleIdx);
+ fUsedSampleOffsetArrays |= (1 << coords);
+}
+
void GrGLSLFragmentShaderBuilder::maskSampleCoverage(const char* mask, bool invert) {
const GrGLSLCaps& glslCaps = *fProgramBuilder->glslCaps();
if (!glslCaps.sampleVariablesSupport()) {
@@ -314,11 +331,50 @@ const char* GrGLSLFragmentShaderBuilder::getSecondaryColorOutputName() const {
: "gl_SecondaryFragColorEXT";
}
+GrSurfaceOrigin GrGLSLFragmentShaderBuilder::getSurfaceOrigin() const {
+ SkASSERT(fProgramBuilder->header().fSurfaceOriginKey);
+ return static_cast<GrSurfaceOrigin>(fProgramBuilder->header().fSurfaceOriginKey);
+
+ GR_STATIC_ASSERT(1 == kTopLeft_GrSurfaceOrigin);
+ GR_STATIC_ASSERT(2 == kBottomLeft_GrSurfaceOrigin);
+}
+
void GrGLSLFragmentShaderBuilder::onFinalize() {
fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision,
*fProgramBuilder->glslCaps(),
&this->precisionQualifier());
+ if (fUsedSampleOffsetArrays & (1 << kSkiaDevice_Coordinates)) {
+ this->defineSampleOffsetArray(sample_offset_array_name(kSkiaDevice_Coordinates),
+ SkMatrix::MakeTrans(-0.5f, -0.5f));
+ }
+ if (fUsedSampleOffsetArrays & (1 << kGLSLWindow_Coordinates)) {
+ // With a top left origin, device and window space are equal, so we only use device coords.
+ SkASSERT(kBottomLeft_GrSurfaceOrigin == this->getSurfaceOrigin());
+ SkMatrix m;
+ m.setScale(1, -1);
+ m.preTranslate(-0.5f, -0.5f);
+ this->defineSampleOffsetArray(sample_offset_array_name(kGLSLWindow_Coordinates), m);
+ }
+}
+
+void GrGLSLFragmentShaderBuilder::defineSampleOffsetArray(const char* name, const SkMatrix& m) {
+ SkASSERT(fProgramBuilder->caps()->sampleLocationsSupport());
+ const GrPipeline& pipeline = fProgramBuilder->pipeline();
+ const GrRenderTargetPriv& rtp = pipeline.getRenderTarget()->renderTargetPriv();
+ const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipeline.getStencil());
+ SkSTArray<16, SkPoint, true> offsets;
+ offsets.push_back_n(specs.fEffectiveSampleCnt);
+ m.mapPoints(offsets.begin(), specs.fSampleLocations.get(), specs.fEffectiveSampleCnt);
+ this->definitions().append("const ");
+ if (fProgramBuilder->glslCaps()->usesPrecisionModifiers()) {
+ this->definitions().append("highp ");
+ }
+ this->definitions().appendf("vec2 %s[] = vec2[](", name);
+ for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
+ this->definitions().appendf("vec2(%f, %f)", offsets[i].x(), offsets[i].y());
+ this->definitions().append(i + 1 != specs.fEffectiveSampleCnt ? ", " : ");\n");
+ }
}
void GrGLSLFragmentShaderBuilder::onBeforeChildProcEmitCode() {
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
index 57b8ee91c6..614b04f54b 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
@@ -68,6 +68,23 @@ public:
/** Appease the compiler; the derived class initializes GrGLSLFragmentBuilder. */
GrGLSLFPFragmentBuilder() : GrGLSLFragmentBuilder(nullptr) {}
+ enum Coordinates {
+ kSkiaDevice_Coordinates,
+ kGLSLWindow_Coordinates,
+
+ kLast_Coordinates = kGLSLWindow_Coordinates
+ };
+
+ /**
+ * Appends the offset from the center of the pixel to a specified sample.
+ *
+ * @param sampleIdx GLSL expression of the sample index.
+ * @param Coordinates Coordinate space in which to emit the offset.
+ *
+ * A processor must call setWillUseSampleLocations in its constructor before using this method.
+ */
+ virtual void appendOffsetToSample(const char* sampleIdx, Coordinates) = 0;
+
/**
* 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.
@@ -138,14 +155,11 @@ public:
*/
class GrGLSLFragmentShaderBuilder : public GrGLSLPPFragmentBuilder, public GrGLSLXPFragmentBuilder {
public:
- typedef uint8_t FragPosKey;
-
- /** Returns a key for reading the fragment location. This should only be called if there is an
- effect that will requires the fragment position. If the fragment position is not required,
- the key is 0. */
- static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst);
+ /** Returns a nonzero key for a surface's origin. This should only be called if a processor will
+ use the fragment position and/or sample locations. */
+ static uint8_t KeyForSurfaceOrigin(GrSurfaceOrigin);
- GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program, uint8_t fragPosKey);
+ GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program);
// Shared GrGLSLFragmentBuilder interface.
bool enableFeature(GLSLFeature) override;
@@ -154,6 +168,7 @@ public:
const char* fragmentPosition() override;
// GrGLSLFPFragmentBuilder interface.
+ void appendOffsetToSample(const char* sampleIdx, Coordinates) override;
void maskSampleCoverage(const char* mask, bool invert = false) override;
void overrideSampleCoverage(const char* mask) override;
const SkString& getMangleString() const override { return fMangleString; }
@@ -167,8 +182,6 @@ public:
void enableAdvancedBlendEquationIfNeeded(GrBlendEquation) override;
private:
- bool hasFragmentPosition() const;
-
// Private public interface, used by GrGLProgramBuilder to build a fragment shader
void enableCustomOutput();
void enableSecondaryOutput();
@@ -189,19 +202,10 @@ private:
static const char* DeclaredColorOutputName() { return "fsColorOut"; }
static const char* DeclaredSecondaryColorOutputName() { return "fsSecondaryColorOut"; }
- /*
- * An internal call for GrGLProgramBuilder to use to add varyings to the vertex shader
- */
- void addVarying(GrGLSLVarying*, GrSLPrecision);
+ GrSurfaceOrigin getSurfaceOrigin() const;
void onFinalize() override;
-
- // Interpretation of FragPosKey when generating code
- enum {
- kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed.
- kTopLeftFragPosRead_FragPosKey = 0x1,// Read frag pos relative to top-left.
- kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left.
- };
+ void defineSampleOffsetArray(const char* name, const SkMatrix&);
static const char* kDstTextureColorName;
@@ -225,12 +229,12 @@ private:
*/
SkString fMangleString;
- bool fSetupFragPosition;
- bool fTopLeftFragPosRead;
- bool fHasCustomColorOutput;
- int fCustomColorOutputIndex;
- bool fHasSecondaryOutput;
- bool fHasInitializedSampleMask;
+ bool fSetupFragPosition;
+ bool fHasCustomColorOutput;
+ int fCustomColorOutputIndex;
+ bool fHasSecondaryOutput;
+ uint8_t fUsedSampleOffsetArrays;
+ bool fHasInitializedSampleMask;
#ifdef SK_DEBUG
// some state to verify shaders and effects are consistent, this is reset between effects by
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 417e924a0e..b9eaca4153 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -18,7 +18,7 @@ const int GrGLSLProgramBuilder::kVarsPerBlock = 8;
GrGLSLProgramBuilder::GrGLSLProgramBuilder(const DrawArgs& args)
: fVS(this)
, fGS(this)
- , fFS(this, args.fDesc->header().fFragPosKey)
+ , fFS(this)
, fStageIndex(-1)
, fArgs(args)
, fGeometryProcessor(nullptr)