diff options
author | 2016-03-07 13:58:26 -0800 | |
---|---|---|
committer | 2016-03-07 13:58:26 -0800 | |
commit | 28f45b949acc746849100fbe112ee5280f0594c9 (patch) | |
tree | b350d442680ef996ab6097433ab0cf960d3680b6 /src/gpu/glsl | |
parent | b3b13b7edeabad4c8e53b0d309b0a44668d1e68f (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.cpp | 88 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLFragmentShaderBuilder.h | 56 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLProgramBuilder.cpp | 2 |
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) |