From de4d301881e7fd084f1f0b359ec6f9b2bf8bd4c5 Mon Sep 17 00:00:00 2001 From: Ethan Nicholas Date: Thu, 19 Jan 2017 16:58:02 -0500 Subject: [PATCH] Replaced all calls to fragmentPosition() with sk_FragCoord BUG=skia: Change-Id: I179576e148ea6caf6e1c40f0a216421898bcb35d Reviewed-on: https://skia-review.googlesource.com/5941 Commit-Queue: Ethan Nicholas Reviewed-by: Brian Salomon --- include/gpu/GrProcessor.h | 4 +- src/effects/GrCircleBlurFragmentProcessor.cpp | 8 +-- src/effects/SkBlurMaskFilter.cpp | 10 +-- src/effects/SkLightingImageFilter.cpp | 16 ++--- src/effects/SkRRectsGaussianEdgeMaskFilter.cpp | 5 +- src/gpu/GrProgramDesc.cpp | 9 +-- src/gpu/GrProgramDesc.h | 6 ++ src/gpu/GrXferProcessor.cpp | 1 - src/gpu/effects/GrConvexPolyEffect.cpp | 29 ++++---- src/gpu/effects/GrDitherEffect.cpp | 5 +- src/gpu/effects/GrOvalEffect.cpp | 16 ++--- src/gpu/effects/GrRRectEffect.cpp | 94 +++++++++++++------------- src/gpu/effects/GrTextureDomain.cpp | 4 +- src/gpu/gl/GrGLGpuProgramCache.cpp | 9 ++- src/gpu/gl/builders/GrGLProgramBuilder.cpp | 13 +++- src/gpu/gl/builders/GrGLProgramBuilder.h | 7 +- src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp | 5 -- src/gpu/glsl/GrGLSLFragmentShaderBuilder.h | 6 -- src/gpu/glsl/GrGLSLProgramBuilder.cpp | 4 +- src/gpu/glsl/GrGLSLProgramBuilder.h | 8 +-- src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp | 4 +- src/gpu/glsl/GrGLSLXferProcessor.cpp | 5 +- src/gpu/ops/GrDrawOp.h | 3 - src/gpu/ops/GrPLSPathRenderer.cpp | 8 +-- src/gpu/vk/GrVkPipelineStateBuilder.cpp | 23 +++++-- src/gpu/vk/GrVkPipelineStateBuilder.h | 11 +-- src/gpu/vk/GrVkPipelineStateCache.cpp | 9 ++- src/sksl/README | 4 +- src/sksl/SkSLIRGenerator.cpp | 13 ++-- src/sksl/ir/SkSLProgram.h | 9 ++- tests/ImageStorageTest.cpp | 4 +- tests/SkSLErrorTest.cpp | 9 +++ 32 files changed, 187 insertions(+), 174 deletions(-) diff --git a/include/gpu/GrProcessor.h b/include/gpu/GrProcessor.h index 32995c3..f933c9a 100644 --- a/include/gpu/GrProcessor.h +++ b/include/gpu/GrProcessor.h @@ -103,8 +103,7 @@ public: */ enum RequiredFeatures { kNone_RequiredFeatures = 0, - kFragmentPosition_RequiredFeature = 1 << 0, - kSampleLocations_RequiredFeature = 1 << 1 + kSampleLocations_RequiredFeature = 1 << 0 }; GR_DECL_BITFIELD_OPS_FRIENDS(RequiredFeatures); @@ -146,7 +145,6 @@ protected: * must call these methods from its constructor. Otherwise, requests to use these features will * be denied. */ - void setWillReadFragmentPosition() { fRequiredFeatures |= kFragmentPosition_RequiredFeature; } void setWillUseSampleLocations() { fRequiredFeatures |= kSampleLocations_RequiredFeature; } void combineRequiredFeatures(const GrProcessor& other) { diff --git a/src/effects/GrCircleBlurFragmentProcessor.cpp b/src/effects/GrCircleBlurFragmentProcessor.cpp index 329529d..d3eb325 100644 --- a/src/effects/GrCircleBlurFragmentProcessor.cpp +++ b/src/effects/GrCircleBlurFragmentProcessor.cpp @@ -47,7 +47,6 @@ void GrCircleBlurFragmentProcessor::GLSLProcessor::emitCode(EmitArgs& args) { &dataName); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - const char *fragmentPos = fragBuilder->fragmentPosition(); if (args.fInputColor) { fragBuilder->codeAppendf("vec4 src=%s;", args.fInputColor); @@ -57,9 +56,9 @@ void GrCircleBlurFragmentProcessor::GLSLProcessor::emitCode(EmitArgs& args) { // We just want to compute "(length(vec) - %s.z + 0.5) * %s.w" but need to rearrange // for precision. - fragBuilder->codeAppendf("vec2 vec = vec2( (%s.x - %s.x) * %s.w , (%s.y - %s.y) * %s.w );", - fragmentPos, dataName, dataName, - fragmentPos, dataName, dataName); + fragBuilder->codeAppendf("vec2 vec = vec2( (sk_FragCoord.x - %s.x) * %s.w, " + "(sk_FragCoord.y - %s.y) * %s.w );", + dataName, dataName, dataName, dataName); fragBuilder->codeAppendf("float dist = length(vec) + (0.5 - %s.z) * %s.w;", dataName, dataName); @@ -95,7 +94,6 @@ GrCircleBlurFragmentProcessor::GrCircleBlurFragmentProcessor(const SkRect& circl , fBlurProfileSampler(blurProfile, GrSamplerParams::kBilerp_FilterMode) { this->initClassID(); this->addTextureSampler(&fBlurProfileSampler); - this->setWillReadFragmentPosition(); } GrGLSLFragmentProcessor* GrCircleBlurFragmentProcessor::onCreateGLSLInstance() const { diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index fa4cb33..aff0a32 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -904,7 +904,6 @@ void GrGLRectBlurEffect::emitCode(EmitArgs& args) { &profileSizeName); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - const char *fragmentPos = fragBuilder->fragmentPosition(); if (args.fInputColor) { fragBuilder->codeAppendf("vec4 src=%s;", args.fInputColor); @@ -912,8 +911,8 @@ void GrGLRectBlurEffect::emitCode(EmitArgs& args) { fragBuilder->codeAppendf("vec4 src=vec4(1);"); } - fragBuilder->codeAppendf("%s vec2 translatedPos = %s.xy - %s.xy;", precisionString.c_str(), - fragmentPos, rectName); + fragBuilder->codeAppendf("%s vec2 translatedPos = sk_FragCoord.xy - %s.xy;", + precisionString.c_str(), rectName); fragBuilder->codeAppendf("%s float width = %s.z - %s.x;", precisionString.c_str(), rectName, rectName); fragBuilder->codeAppendf("%s float height = %s.w - %s.y;", precisionString.c_str(), rectName, @@ -983,7 +982,6 @@ GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *b , fPrecision(precision) { this->initClassID(); this->addTextureSampler(&fBlurProfileSampler); - this->setWillReadFragmentPosition(); } void GrRectBlurEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, @@ -1214,7 +1212,6 @@ GrRRectBlurEffect::GrRRectBlurEffect(float sigma, const SkRRect& rrect, GrTextur fNinePatchSampler(ninePatchTexture) { this->initClassID(); this->addTextureSampler(&fNinePatchSampler); - this->setWillReadFragmentPosition(); } bool GrRRectBlurEffect::onIsEqual(const GrFragmentProcessor& other) const { @@ -1280,12 +1277,11 @@ void GrGLRRectBlurEffect::emitCode(EmitArgs& args) { &blurRadiusName); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - const char* fragmentPos = fragBuilder->fragmentPosition(); // warp the fragment position to the appropriate part of the 9patch blur texture fragBuilder->codeAppendf("vec2 rectCenter = (%s.xy + %s.zw)/2.0;", rectName, rectName); - fragBuilder->codeAppendf("vec2 translatedFragPos = %s.xy - %s.xy;", fragmentPos, rectName); + fragBuilder->codeAppendf("vec2 translatedFragPos = sk_FragCoord.xy - %s.xy;", rectName); fragBuilder->codeAppendf("float threshold = %s + 2.0*%s;", cornerRadiusName, blurRadiusName); fragBuilder->codeAppendf("vec2 middle = %s.zw - %s.xy - 2.0*threshold;", rectName, rectName); diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp index 1d710bf..53c85bd 100644 --- a/src/effects/SkLightingImageFilter.cpp +++ b/src/effects/SkLightingImageFilter.cpp @@ -770,8 +770,6 @@ public: virtual bool isEqual(const SkImageFilterLight& other) const { return fColor == other.fColor; } - // Called to know whether the generated GrGLLight will require access to the fragment position. - virtual bool requiresFragmentPosition() const = 0; virtual SkImageFilterLight* transform(const SkMatrix& matrix) const = 0; // Defined below SkLight's subclasses. @@ -820,7 +818,6 @@ public: return nullptr; #endif } - bool requiresFragmentPosition() const override { return false; } bool isEqual(const SkImageFilterLight& other) const override { if (other.type() != kDistant_LightType) { @@ -879,7 +876,6 @@ public: return nullptr; #endif } - bool requiresFragmentPosition() const override { return true; } bool isEqual(const SkImageFilterLight& other) const override { if (other.type() != kPoint_LightType) { return false; @@ -993,7 +989,6 @@ public: return nullptr; #endif } - bool requiresFragmentPosition() const override { return true; } LightType type() const override { return kSpot_LightType; } const SkPoint3& location() const { return fLocation; } const SkPoint3& target() const { return fTarget; } @@ -1714,9 +1709,6 @@ GrLightingEffect::GrLightingEffect(GrTexture* texture, , fBoundaryMode(boundaryMode) , fDomain(create_domain(texture, srcBounds, GrTextureDomain::kDecal_Mode)) { fLight->ref(); - if (light->requiresFragmentPosition()) { - this->setWillReadFragmentPosition(); - } } GrLightingEffect::~GrLightingEffect() { @@ -2097,8 +2089,8 @@ void GrGLPointLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler, fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec3f_GrSLType, kDefault_GrSLPrecision, "LightLocation", &loc); - fragBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))", - loc, fragBuilder->fragmentPosition(), z); + fragBuilder->codeAppendf("normalize(%s - vec3(sk_FragCoord.xy, %s))", + loc, z); } /////////////////////////////////////////////////////////////////////////////// @@ -2124,8 +2116,8 @@ void GrGLSpotLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler, kVec3f_GrSLType, kDefault_GrSLPrecision, "LightLocation", &location); - fragBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))", - location, fragBuilder->fragmentPosition(), z); + fragBuilder->codeAppendf("normalize(%s - vec3(sk_FragCoord.xy, %s))", + location, z); } void GrGLSpotLight::emitLightColor(GrGLSLUniformHandler* uniformHandler, diff --git a/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp b/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp index 978dbff..53df9e2 100644 --- a/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp +++ b/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp @@ -211,7 +211,6 @@ public: , fSecond(second) , fRadius(radius) { this->initClassID(); - this->setWillReadFragmentPosition(); fFirstMode = ComputeMode(fFirst); fSecondMode = ComputeMode(fSecond); @@ -235,8 +234,8 @@ public: // Positive distance is towards the center of the circle. // Map all the cases to the lower right quadrant. - fragBuilder->codeAppendf("vec2 delta = abs(%s.xy - %s.%s);", - fragBuilder->fragmentPosition(), posName, indices); + fragBuilder->codeAppendf("vec2 delta = abs(sk_FragCoord.xy - %s.%s);", + posName, indices); switch (mode) { case kCircle_Mode: diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp index 87a4a27..080ba5e 100644 --- a/src/gpu/GrProgramDesc.cpp +++ b/src/gpu/GrProgramDesc.cpp @@ -195,14 +195,9 @@ bool GrProgramDesc::Build(GrProgramDesc* desc, // make sure any padding in the header is zeroed. memset(header, 0, kHeaderSize); - GrRenderTarget* rt = pipeline.getRenderTarget(); + header->fSurfaceOriginKey = 0; - if (requiredFeatures & (GrProcessor::kFragmentPosition_RequiredFeature | - GrProcessor::kSampleLocations_RequiredFeature)) { - header->fSurfaceOriginKey = GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(rt->origin()); - } else { - header->fSurfaceOriginKey = 0; - } + GrRenderTarget* rt = pipeline.getRenderTarget(); if (requiredFeatures & GrProcessor::kSampleLocations_RequiredFeature) { SkASSERT(pipeline.isHWAntialiasState()); diff --git a/src/gpu/GrProgramDesc.h b/src/gpu/GrProgramDesc.h index 2a26f2d..a20cdfc 100644 --- a/src/gpu/GrProgramDesc.h +++ b/src/gpu/GrProgramDesc.h @@ -12,6 +12,7 @@ #include "GrTypesPriv.h" #include "SkOpts.h" #include "SkTArray.h" +#include "glsl/GrGLSLFragmentShaderBuilder.h" class GrShaderCaps; class GrPipeline; @@ -80,6 +81,11 @@ public: return !(*this == other); } + void setSurfaceOriginKey(int key) { + KeyHeader* header = this->atOffset(); + header->fSurfaceOriginKey = key; + } + static bool Less(const GrProgramDesc& a, const GrProgramDesc& b) { SkASSERT(SkIsAlign4(a.keyLength())); int l = a.keyLength() >> 2; diff --git a/src/gpu/GrXferProcessor.cpp b/src/gpu/GrXferProcessor.cpp index c2a16b8..7de0d77 100644 --- a/src/gpu/GrXferProcessor.cpp +++ b/src/gpu/GrXferProcessor.cpp @@ -27,7 +27,6 @@ GrXferProcessor::GrXferProcessor(const DstTexture* dstTexture, fDstTexture.reset(dstTexture->texture()); fDstTextureOffset = dstTexture->offset(); this->addTextureSampler(&fDstTexture); - this->setWillReadFragmentPosition(); } } diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp index a64e5cb..65ed87b 100644 --- a/src/gpu/effects/GrConvexPolyEffect.cpp +++ b/src/gpu/effects/GrConvexPolyEffect.cpp @@ -34,7 +34,6 @@ private: AARectEffect(GrPrimitiveEdgeType edgeType, const SkRect& rect) : fRect(rect), fEdgeType(edgeType) { this->initClassID(); - this->setWillReadFragmentPosition(); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; @@ -113,24 +112,27 @@ void GLAARectEffect::emitCode(EmitArgs& args) { &rectName); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - const char* fragmentPos = fragBuilder->fragmentPosition(); if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) { // The amount of coverage removed in x and y by the edges is computed as a pair of negative // numbers, xSub and ySub. fragBuilder->codeAppend("\t\tfloat xSub, ySub;\n"); - fragBuilder->codeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName); - fragBuilder->codeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos); - fragBuilder->codeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName); - fragBuilder->codeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos); + fragBuilder->codeAppendf("\t\txSub = min(sk_FragCoord.x - %s.x, 0.0);\n", rectName); + fragBuilder->codeAppendf("\t\txSub += min(%s.z - sk_FragCoord.x, 0.0);\n", rectName); + fragBuilder->codeAppendf("\t\tySub = min(sk_FragCoord.y - %s.y, 0.0);\n", rectName); + fragBuilder->codeAppendf("\t\tySub += min(%s.w - sk_FragCoord.y, 0.0);\n", rectName); // Now compute coverage in x and y and multiply them to get the fraction of the pixel // covered. fragBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n"); } else { fragBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n"); - fragBuilder->codeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName); - fragBuilder->codeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos); - fragBuilder->codeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName); - fragBuilder->codeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos); + fragBuilder->codeAppendf("\t\talpha *= (sk_FragCoord.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", + rectName); + fragBuilder->codeAppendf("\t\talpha *= (%s.z - sk_FragCoord.x) > -0.5 ? 1.0 : 0.0;\n", + rectName); + fragBuilder->codeAppendf("\t\talpha *= (sk_FragCoord.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", + rectName); + fragBuilder->codeAppendf("\t\talpha *= (%s.w - sk_FragCoord.y) > -0.5 ? 1.0 : 0.0;\n", + rectName); } if (GrProcessorEdgeTypeIsInverseFill(aare.getEdgeType())) { @@ -199,10 +201,10 @@ void GrGLConvexPolyEffect::emitCode(EmitArgs& args) { GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; fragBuilder->codeAppend("\t\tfloat alpha = 1.0;\n"); fragBuilder->codeAppend("\t\tfloat edge;\n"); - const char* fragmentPos = fragBuilder->fragmentPosition(); for (int i = 0; i < cpe.getEdgeCount(); ++i) { - fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n", - edgeArrayName, i, fragmentPos, fragmentPos); + fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(sk_FragCoord.x, sk_FragCoord.y, " + "1));\n", + edgeArrayName, i); if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) { fragBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n"); } else { @@ -348,7 +350,6 @@ GrConvexPolyEffect::GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, cons for (int i = 0; i < n; ++i) { fEdges[3 * i + 2] += SK_ScalarHalf; } - this->setWillReadFragmentPosition(); } bool GrConvexPolyEffect::onIsEqual(const GrFragmentProcessor& other) const { diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp index eb7fe62..a93e74f 100644 --- a/src/gpu/effects/GrDitherEffect.cpp +++ b/src/gpu/effects/GrDitherEffect.cpp @@ -28,7 +28,6 @@ public: private: DitherEffect() { this->initClassID(); - this->setWillReadFragmentPosition(); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; @@ -79,8 +78,8 @@ void GLDitherEffect::emitCode(EmitArgs& args) { // For each channel c, add the random offset to the pixel to either bump // it up or let it remain constant during quantization. fragBuilder->codeAppendf("\t\tfloat r = " - "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n", - fragBuilder->fragmentPosition()); + "fract(sin(dot(sk_FragCoord.xy, vec2(12.9898,78.233))) * " + "43758.5453);\n"); fragBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n", args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str()); } diff --git a/src/gpu/effects/GrOvalEffect.cpp b/src/gpu/effects/GrOvalEffect.cpp index 13cbd25..21a4ba0 100644 --- a/src/gpu/effects/GrOvalEffect.cpp +++ b/src/gpu/effects/GrOvalEffect.cpp @@ -68,7 +68,6 @@ CircleEffect::CircleEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkSca , fRadius(r) , fEdgeType(edgeType) { this->initClassID(); - this->setWillReadFragmentPosition(); } bool CircleEffect::onIsEqual(const GrFragmentProcessor& other) const { @@ -124,7 +123,6 @@ void GLCircleEffect::emitCode(EmitArgs& args) { &circleName); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - const char* fragmentPos = fragBuilder->fragmentPosition(); SkASSERT(kHairlineAA_GrProcessorEdgeType != ce.getEdgeType()); // TODO: Right now the distance to circle caclulation is performed in a space normalized to the @@ -132,11 +130,13 @@ void GLCircleEffect::emitCode(EmitArgs& args) { // mediump. It'd be nice to only to this on mediump devices but we currently don't have the // caps here. if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) { - fragBuilder->codeAppendf("float d = (length((%s.xy - %s.xy) * %s.w) - 1.0) * %s.z;", - circleName, fragmentPos, circleName, circleName); + fragBuilder->codeAppendf("float d = (length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * " + "%s.z;", + circleName, circleName, circleName); } else { - fragBuilder->codeAppendf("float d = (1.0 - length((%s.xy - %s.xy) * %s.w)) * %s.z;", - circleName, fragmentPos, circleName, circleName); + fragBuilder->codeAppendf("float d = (1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * " + "%s.z;", + circleName, circleName, circleName); } if (GrProcessorEdgeTypeIsAA(ce.getEdgeType())) { fragBuilder->codeAppend("d = clamp(d, 0.0, 1.0);"); @@ -235,7 +235,6 @@ EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkS , fRadii(SkVector::Make(rx, ry)) , fEdgeType(edgeType) { this->initClassID(); - this->setWillReadFragmentPosition(); } bool EllipseEffect::onIsEqual(const GrFragmentProcessor& other) const { @@ -305,10 +304,9 @@ void GLEllipseEffect::emitCode(EmitArgs& args) { } GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - const char* fragmentPos = fragBuilder->fragmentPosition(); // d is the offset to the ellipse center - fragBuilder->codeAppendf("vec2 d = %s.xy - %s.xy;", fragmentPos, ellipseName); + fragBuilder->codeAppendf("vec2 d = sk_FragCoord.xy - %s.xy;", ellipseName); if (scaleName) { fragBuilder->codeAppendf("d *= %s.y;", scaleName); } diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp index 4db3957..adebc24 100644 --- a/src/gpu/effects/GrRRectEffect.cpp +++ b/src/gpu/effects/GrRRectEffect.cpp @@ -99,7 +99,6 @@ CircularRRectEffect::CircularRRectEffect(GrPrimitiveEdgeType edgeType, uint32_t , fEdgeType(edgeType) , fCircularCornerFlags(circularCornerFlags) { this->initClassID(); - this->setWillReadFragmentPosition(); } bool CircularRRectEffect::onIsEqual(const GrFragmentProcessor& other) const { @@ -178,7 +177,6 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) { } GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - const char* fragmentPos = fragBuilder->fragmentPosition(); // At each quarter-circle corner we compute a vector that is the offset of the fragment position // from the circle center. The vector is pinned in x and y to be in the quarter-plane relevant // to that corner. This means that points near the interior near the rrect top edge will have @@ -196,84 +194,86 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) { // alphas together. switch (crre.getCircularCornerFlags()) { case CircularRRectEffect::kAll_CornerFlags: - fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fragmentPos); - fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName); + fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("vec2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); fragBuilder->codeAppend("vec2 dxy = max(max(dxy0, dxy1), 0.0);"); fragBuilder->codeAppendf("float alpha = %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kTopLeft_CornerFlag: - fragBuilder->codeAppendf("vec2 dxy = max(%s.xy - %s.xy, 0.0);", - rectName, fragmentPos); - fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);", - rectName, fragmentPos); - fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);", - rectName, fragmentPos); + fragBuilder->codeAppendf("vec2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);", + rectName); + fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);", + rectName); + fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);", + rectName); fragBuilder->codeAppendf("float alpha = bottomAlpha * rightAlpha * %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kTopRight_CornerFlag: - fragBuilder->codeAppendf("vec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);", - fragmentPos, rectName, rectName, fragmentPos); - fragBuilder->codeAppendf("float leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);", - fragmentPos, rectName); - fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);", - rectName, fragmentPos); + fragBuilder->codeAppendf("vec2 dxy = max(vec2(sk_FragCoord.x - %s.z, " + "%s.y - sk_FragCoord.y), 0.0);", + rectName, rectName); + fragBuilder->codeAppendf("float leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);", + rectName); + fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);", + rectName); fragBuilder->codeAppendf("float alpha = bottomAlpha * leftAlpha * %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kBottomRight_CornerFlag: - fragBuilder->codeAppendf("vec2 dxy = max(%s.xy - %s.zw, 0.0);", - fragmentPos, rectName); - fragBuilder->codeAppendf("float leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);", - fragmentPos, rectName); - fragBuilder->codeAppendf("float topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);", - fragmentPos, rectName); + fragBuilder->codeAppendf("vec2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);", + rectName); + fragBuilder->codeAppendf("float leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);", + rectName); + fragBuilder->codeAppendf("float topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);", + rectName); fragBuilder->codeAppendf("float alpha = topAlpha * leftAlpha * %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kBottomLeft_CornerFlag: - fragBuilder->codeAppendf("vec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);", - rectName, fragmentPos, fragmentPos, rectName); - fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);", - rectName, fragmentPos); - fragBuilder->codeAppendf("float topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);", - fragmentPos, rectName); + fragBuilder->codeAppendf("vec2 dxy = max(vec2(%s.x - sk_FragCoord.x, sk_FragCoord.y - " + "%s.w), 0.0);", + rectName, rectName); + fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);", + rectName); + fragBuilder->codeAppendf("float topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);", + rectName); fragBuilder->codeAppendf("float alpha = topAlpha * rightAlpha * %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kLeft_CornerFlags: - fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fragmentPos); - fragBuilder->codeAppendf("float dy1 = %s.y - %s.w;", fragmentPos, rectName); + fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.w;", rectName); fragBuilder->codeAppend("vec2 dxy = max(vec2(dxy0.x, max(dxy0.y, dy1)), 0.0);"); - fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);", - rectName, fragmentPos); + fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);", + rectName); fragBuilder->codeAppendf("float alpha = rightAlpha * %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kTop_CornerFlags: - fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fragmentPos); - fragBuilder->codeAppendf("float dx1 = %s.x - %s.z;", fragmentPos, rectName); + fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.z;", rectName); fragBuilder->codeAppend("vec2 dxy = max(vec2(max(dxy0.x, dx1), dxy0.y), 0.0);"); - fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);", - rectName, fragmentPos); + fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);", + rectName); fragBuilder->codeAppendf("float alpha = bottomAlpha * %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kRight_CornerFlags: - fragBuilder->codeAppendf("float dy0 = %s.y - %s.y;", rectName, fragmentPos); - fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName); + fragBuilder->codeAppendf("float dy0 = %s.y - sk_FragCoord.y;", rectName); + fragBuilder->codeAppendf("vec2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); fragBuilder->codeAppend("vec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1.y)), 0.0);"); - fragBuilder->codeAppendf("float leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);", - fragmentPos, rectName); + fragBuilder->codeAppendf("float leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);", + rectName); fragBuilder->codeAppendf("float alpha = leftAlpha * %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kBottom_CornerFlags: - fragBuilder->codeAppendf("float dx0 = %s.x - %s.x;", rectName, fragmentPos); - fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName); + fragBuilder->codeAppendf("float dx0 = %s.x - sk_FragCoord.x;", rectName); + fragBuilder->codeAppendf("vec2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); fragBuilder->codeAppend("vec2 dxy = max(vec2(max(dx0, dxy1.x), dxy1.y), 0.0);"); - fragBuilder->codeAppendf("float topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);", - fragmentPos, rectName); + fragBuilder->codeAppendf("float topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);", + rectName); fragBuilder->codeAppendf("float alpha = topAlpha * %s;", clampedCircleDistance.c_str()); break; @@ -434,7 +434,6 @@ EllipticalRRectEffect::EllipticalRRectEffect(GrPrimitiveEdgeType edgeType, const : fRRect(rrect) , fEdgeType(edgeType) { this->initClassID(); - this->setWillReadFragmentPosition(); } bool EllipticalRRectEffect::onIsEqual(const GrFragmentProcessor& other) const { @@ -516,7 +515,6 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { &rectName); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - const char* fragmentPos = fragBuilder->fragmentPosition(); // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos // to the ellipse center. The vector is pinned in x and y to be in the quarter-plane relevant // to that corner. This means that points near the interior near the rrect top edge will have @@ -529,8 +527,8 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { // The code below is a simplified version of the above that performs maxs on the vector // components before computing distances and alpha values so that only one distance computation // need be computed to determine the min alpha. - fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fragmentPos); - fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName); + fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("vec2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); // If we're on a device with a "real" mediump then we'll do the distance computation in a space // that is normalized by the largest radius. The scale uniform will be scale, 1/scale. The diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp index d6872e1..095f100 100644 --- a/src/gpu/effects/GrTextureDomain.cpp +++ b/src/gpu/effects/GrTextureDomain.cpp @@ -330,7 +330,6 @@ GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentPro fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft; fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop; this->initClassID(); - this->setWillReadFragmentPosition(); } GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLSLInstance() const { @@ -345,8 +344,7 @@ GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLS kDefault_GrSLPrecision, "scaleAndTranslate", &scaleAndTranslateName); - args.fFragBuilder->codeAppendf("vec2 coords = %s.xy * %s.xy + %s.zw;", - args.fFragBuilder->fragmentPosition(), + args.fFragBuilder->codeAppendf("vec2 coords = sk_FragCoord.xy * %s.xy + %s.zw;", scaleAndTranslateName, scaleAndTranslateName); fGLDomain.sampleTexture(args.fFragBuilder, args.fUniformHandler, diff --git a/src/gpu/gl/GrGLGpuProgramCache.cpp b/src/gpu/gl/GrGLGpuProgramCache.cpp index c1ca160..2ff5dc7 100644 --- a/src/gpu/gl/GrGLGpuProgramCache.cpp +++ b/src/gpu/gl/GrGLGpuProgramCache.cpp @@ -81,11 +81,18 @@ GrGLProgram* GrGLGpu::ProgramCache::refProgram(const GrGLGpu* gpu, desc.finalize(); std::unique_ptr* entry = fMap.find(desc); if (!entry) { + // Didn't find an origin-independent version, check with the specific origin + GrSurfaceOrigin origin = pipeline.getRenderTarget()->origin(); + desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin)); + desc.finalize(); + entry = fMap.find(desc); + } + if (!entry) { // We have a cache miss #ifdef PROGRAM_CACHE_STATS ++fCacheMisses; #endif - GrGLProgram* program = GrGLProgramBuilder::CreateProgram(pipeline, primProc, desc, fGpu); + GrGLProgram* program = GrGLProgramBuilder::CreateProgram(pipeline, primProc, &desc, fGpu); if (nullptr == program) { return nullptr; } diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index c3e81fb..f3548e6 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -30,7 +30,7 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, - const GrProgramDesc& desc, + GrProgramDesc* desc, GrGLGpu* gpu) { GrAutoLocaleSetter als("C"); @@ -56,7 +56,7 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrPipeline& pipeline, GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, - const GrProgramDesc& desc) + GrProgramDesc* desc) : INHERITED(pipeline, primProc, desc) , fGpu(gpu) , fVaryingHandler(this) @@ -89,6 +89,13 @@ bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader, } *shaderIds->append() = shaderId; + if (!outInputs->fFlipY) { + GrProgramDesc* d = this->desc(); + // the program doesn't care about the surface origin, set the key to zero to indicate that + // it doesn't matter + d->setSurfaceOriginKey(0); + d->finalize(); + } return true; } @@ -244,7 +251,7 @@ void GrGLProgramBuilder::cleanupShaders(const SkTDArray& shaderIDs) { GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { return new GrGLProgram(fGpu, - this->desc(), + *this->desc(), fUniformHandles, programID, fUniformHandler.fUniforms, diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h index 84d6d91..cfbb734 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.h +++ b/src/gpu/gl/builders/GrGLProgramBuilder.h @@ -29,11 +29,14 @@ public: * The program implements what is specified in the stages given as input. * After successful generation, the builder result objects are available * to be used. + * This function may modify the GrProgramDesc by setting the surface origin + * key to 0 (unspecified) if it turns out the program does not care about + * the surface origin. * @return true if generation was successful. */ static GrGLProgram* CreateProgram(const GrPipeline&, const GrPrimitiveProcessor&, - const GrProgramDesc&, + GrProgramDesc*, GrGLGpu*); const GrCaps* caps() const override; @@ -42,7 +45,7 @@ public: private: GrGLProgramBuilder(GrGLGpu*, const GrPipeline&, const GrPrimitiveProcessor&, - const GrProgramDesc&); + GrProgramDesc*); bool compileAndAttachShaders(GrGLSLShaderBuilder& shader, GrGLuint programId, diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp index 7ef7348..f583420 100644 --- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp +++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp @@ -130,11 +130,6 @@ SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords) return coords2D; } -const char* GrGLSLFragmentShaderBuilder::fragmentPosition() { - SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kFragmentPosition_RequiredFeature;) - return "sk_FragCoord"; -} - const char* GrGLSLFragmentShaderBuilder::distanceVectorName() const { return "fsDistanceVector"; } diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h index f7d2323..ab806ea 100644 --- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h +++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h @@ -47,11 +47,6 @@ public: */ virtual SkString ensureCoords2D(const GrShaderVar&) = 0; - - /** Returns a variable name that represents the position of the fragment in the FS. The position - is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */ - virtual const char* fragmentPosition() = 0; - // TODO: remove this method. void declAppendf(const char* fmt, ...); @@ -167,7 +162,6 @@ public: // Shared GrGLSLFragmentBuilder interface. bool enableFeature(GLSLFeature) override; virtual SkString ensureCoords2D(const GrShaderVar&) override; - const char* fragmentPosition() override; const char* distanceVectorName() const override; // GrGLSLFPFragmentBuilder interface. diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp index c805825..2b8a3a7 100644 --- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp +++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp @@ -20,7 +20,7 @@ const int GrGLSLProgramBuilder::kVarsPerBlock = 8; GrGLSLProgramBuilder::GrGLSLProgramBuilder(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, - const GrProgramDesc& desc) + GrProgramDesc* desc) : fVS(this) , fGS(this) , fFS(this) @@ -348,7 +348,7 @@ void GrGLSLProgramBuilder::emitImageStorage(const GrProcessor::ImageStorageAcces void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) { // Swizzle the fragment shader outputs if necessary. GrSwizzle swizzle; - swizzle.setFromKey(this->desc().header().fOutputSwizzle); + swizzle.setFromKey(this->desc()->header().fOutputSwizzle); if (swizzle != GrSwizzle::RGBA()) { fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(), fFS.getPrimaryColorOutputName(), diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h index 2dba90f..3074110 100644 --- a/src/gpu/glsl/GrGLSLProgramBuilder.h +++ b/src/gpu/glsl/GrGLSLProgramBuilder.h @@ -40,8 +40,8 @@ public: const GrPrimitiveProcessor& primitiveProcessor() const { return fPrimProc; } const GrPipeline& pipeline() const { return fPipeline; } - const GrProgramDesc& desc() const { return fDesc; } - const GrProgramDesc::KeyHeader& header() const { return fDesc.header(); } + GrProgramDesc* desc() { return fDesc; } + const GrProgramDesc::KeyHeader& header() const { return fDesc->header(); } void appendUniformDecls(GrShaderFlags visibility, SkString*) const; @@ -99,7 +99,7 @@ public: const GrPipeline& fPipeline; const GrPrimitiveProcessor& fPrimProc; - const GrProgramDesc& fDesc; + GrProgramDesc* fDesc; BuiltinUniformHandles fUniformHandles; @@ -110,7 +110,7 @@ public: protected: explicit GrGLSLProgramBuilder(const GrPipeline&, const GrPrimitiveProcessor&, - const GrProgramDesc&); + GrProgramDesc*); void addFeature(GrShaderFlags shaders, uint32_t featureBit, const char* extensionName); diff --git a/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp b/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp index f8302b3..2aded89 100644 --- a/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp +++ b/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp @@ -22,7 +22,7 @@ void GrGLSLVertexBuilder::transformToNormalizedDeviceSpace(const GrShaderVar& po fProgramBuilder->addRTAdjustmentUniform(kHigh_GrSLPrecision, fProgramBuilder->rtAdjustment(), &fRtAdjustName); - if (this->getProgramBuilder()->desc().header().fSnapVerticesToPixelCenters) { + if (this->getProgramBuilder()->desc()->header().fSnapVerticesToPixelCenters) { if (kVec3f_GrSLType == posVar.getType()) { const char* p = posVar.c_str(); this->codeAppendf("{vec2 _posTmp = vec2(%s.x/%s.z, %s.y/%s.z);", p, p, p, p); @@ -47,7 +47,7 @@ void GrGLSLVertexBuilder::transformToNormalizedDeviceSpace(const GrShaderVar& po } // We could have the GrGeometryProcessor do this, but its just easier to have it performed // here. If we ever need to set variable pointsize, then we can reinvestigate. - if (this->getProgramBuilder()->desc().header().fHasPointSize) { + if (this->getProgramBuilder()->desc()->header().fHasPointSize) { this->codeAppend("gl_PointSize = 1.0;"); } } diff --git a/src/gpu/glsl/GrGLSLXferProcessor.cpp b/src/gpu/glsl/GrGLSLXferProcessor.cpp index e269819..4101080 100644 --- a/src/gpu/glsl/GrGLSLXferProcessor.cpp +++ b/src/gpu/glsl/GrGLSLXferProcessor.cpp @@ -49,11 +49,10 @@ void GrGLSLXferProcessor::emitCode(const EmitArgs& args) { kDefault_GrSLPrecision, "DstTextureCoordScale", &dstCoordScaleName); - const char* fragPos = fragBuilder->fragmentPosition(); fragBuilder->codeAppend("// Read color from copy of the destination.\n"); - fragBuilder->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;", - fragPos, dstTopLeftName, dstCoordScaleName); + fragBuilder->codeAppendf("vec2 _dstTexCoord = (sk_FragCoord.xy - %s) * %s;", + dstTopLeftName, dstCoordScaleName); if (!topDown) { fragBuilder->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;"); diff --git a/src/gpu/ops/GrDrawOp.h b/src/gpu/ops/GrDrawOp.h index 9e949b1..447a4dd 100644 --- a/src/gpu/ops/GrDrawOp.h +++ b/src/gpu/ops/GrDrawOp.h @@ -64,9 +64,6 @@ public: bool installPipeline(const GrPipeline::CreateArgs&); - // TODO no GrPrimitiveProcessors yet read fragment position - bool willReadFragmentPosition() const { return false; } - protected: static SkString DumpPipelineInfo(const GrPipeline& pipeline) { SkString string; diff --git a/src/gpu/ops/GrPLSPathRenderer.cpp b/src/gpu/ops/GrPLSPathRenderer.cpp index 545d12b..384733f 100644 --- a/src/gpu/ops/GrPLSPathRenderer.cpp +++ b/src/gpu/ops/GrPLSPathRenderer.cpp @@ -344,8 +344,7 @@ public: // gl_FragCoord. The oriented box positioning of the subsamples is of course not // optimal, but it greatly simplifies the math and this simplification is necessary for // performance reasons. - fsBuilder->codeAppendf("highp vec2 firstSample = %s.xy - vec2(0.25);", - fsBuilder->fragmentPosition()); + fsBuilder->codeAppendf("highp vec2 firstSample = sk_FragCoord.xy - vec2(0.25);"); fsBuilder->codeAppendf("highp vec2 delta1 = %s;", delta1.fsIn()); fsBuilder->codeAppendf("highp vec2 delta2 = %s;", delta2.fsIn()); fsBuilder->codeAppendf("highp vec2 delta3 = %s;", delta3.fsIn()); @@ -423,7 +422,6 @@ private: kHigh_GrSLPrecision); fInWindings = &this->addVertexAttrib("inWindings", kInt_GrVertexAttribType, kLow_GrSLPrecision); - this->setWillReadFragmentPosition(); } const Attribute* fInPosition; @@ -542,8 +540,7 @@ public: fsBuilder->codeAppend("highp vec2 uvIncY = uvdX * 0.1 + uvdY * 0.55;"); fsBuilder->codeAppendf("highp vec2 uv = %s.xy - uvdX * 0.35 - uvdY * 0.25;", uv.fsIn()); - fsBuilder->codeAppendf("highp vec2 firstSample = %s.xy - vec2(0.25);", - fsBuilder->fragmentPosition()); + fsBuilder->codeAppendf("highp vec2 firstSample = sk_FragCoord.xy - vec2(0.25);"); fsBuilder->codeAppendf("highp float d = dot(%s, (firstSample - %s).yx) * 2.0;", delta.fsIn(), ep1.fsIn()); fsBuilder->codeAppendf("pls.windings[0] += %s(d, uv) ? %s : 0;", inQuadName.c_str(), @@ -604,7 +601,6 @@ private: kHigh_GrSLPrecision); fInWindings = &this->addVertexAttrib("inWindings", kInt_GrVertexAttribType, kLow_GrSLPrecision); - this->setWillReadFragmentPosition(); } const Attribute* fInPosition; diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/src/gpu/vk/GrVkPipelineStateBuilder.cpp index 4125938..f7a6173 100644 --- a/src/gpu/vk/GrVkPipelineStateBuilder.cpp +++ b/src/gpu/vk/GrVkPipelineStateBuilder.cpp @@ -19,7 +19,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState( const GrStencilSettings& stencil, const GrPrimitiveProcessor& primProc, GrPrimitiveType primitiveType, - const GrVkPipelineState::Desc& desc, + GrVkPipelineState::Desc* desc, const GrVkRenderPass& renderPass) { // create a builder. This will be handed off to effects so they can use it to add // uniforms, varyings, textures, etc @@ -39,7 +39,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState( GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu, const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, - const GrProgramDesc& desc) + GrProgramDesc* desc) : INHERITED(pipeline, primProc, desc) , fGpu(gpu) , fVaryingHandler(this) @@ -62,7 +62,8 @@ bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage, const GrGLSLShaderBuilder& builder, VkShaderModule* shaderModule, VkPipelineShaderStageCreateInfo* stageInfo, - const SkSL::Program::Settings& settings) { + const SkSL::Program::Settings& settings, + GrVkPipelineState::Desc* desc) { SkString shaderString; for (int i = 0; i < builder.fCompilerStrings.count(); ++i) { if (builder.fCompilerStrings[i]) { @@ -80,13 +81,19 @@ bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage, if (inputs.fRTHeight) { this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); } + if (!inputs.fFlipY) { + // the program doesn't care about the surface origin, set the key to zero to indicate that + // it doesn't matter + desc->setSurfaceOriginKey(0); + desc->finalize(); + } return result; } GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil, GrPrimitiveType primitiveType, const GrVkRenderPass& renderPass, - const GrVkPipelineState::Desc& desc) { + GrVkPipelineState::Desc* desc) { VkDescriptorSetLayout dsLayout[2]; VkPipelineLayout pipelineLayout; VkShaderModule vertShaderModule; @@ -133,7 +140,8 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s fVS, &vertShaderModule, &shaderStageInfo[0], - settings)); + settings, + desc)); // TODO: geometry shader support. SkASSERT(!this->primitiveProcessor().willUseGeoShader()); @@ -142,7 +150,8 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s fFS, &fragShaderModule, &shaderStageInfo[1], - settings)); + settings, + desc)); GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline, stencil, @@ -165,7 +174,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s } return new GrVkPipelineState(fGpu, - desc, + *desc, pipeline, pipelineLayout, samplerDSHandle, diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.h b/src/gpu/vk/GrVkPipelineStateBuilder.h index cf4a983..ae59ec4 100644 --- a/src/gpu/vk/GrVkPipelineStateBuilder.h +++ b/src/gpu/vk/GrVkPipelineStateBuilder.h @@ -28,6 +28,8 @@ public: * * The GrVkPipelineState implements what is specified in the GrPipeline and GrPrimitiveProcessor * as input. After successful generation, the builder result objects are available to be used. + * This function may modify the program key by setting the surface origin key to 0 (unspecified) + * if it turns out the program does not care about the surface origin. * @return true if generation was successful. */ static GrVkPipelineState* CreatePipelineState(GrVkGpu*, @@ -35,7 +37,7 @@ public: const GrStencilSettings&, const GrPrimitiveProcessor&, GrPrimitiveType, - const GrVkPipelineState::Desc&, + GrVkPipelineState::Desc*, const GrVkRenderPass& renderPass); const GrCaps* caps() const override; @@ -49,18 +51,19 @@ private: GrVkPipelineStateBuilder(GrVkGpu*, const GrPipeline&, const GrPrimitiveProcessor&, - const GrProgramDesc&); + GrProgramDesc*); GrVkPipelineState* finalize(const GrStencilSettings&, GrPrimitiveType primitiveType, const GrVkRenderPass& renderPass, - const GrVkPipelineState::Desc&); + GrVkPipelineState::Desc*); bool createVkShaderModule(VkShaderStageFlagBits stage, const GrGLSLShaderBuilder& builder, VkShaderModule* shaderModule, VkPipelineShaderStageCreateInfo* stageInfo, - const SkSL::Program::Settings& settings); + const SkSL::Program::Settings& settings, + GrVkPipelineState::Desc* desc); GrGLSLUniformHandler* uniformHandler() override { return &fUniformHandler; } const GrGLSLUniformHandler* uniformHandler() const override { return &fUniformHandler; } diff --git a/src/gpu/vk/GrVkPipelineStateCache.cpp b/src/gpu/vk/GrVkPipelineStateCache.cpp index 7b935eb..f8d77a9 100644 --- a/src/gpu/vk/GrVkPipelineStateCache.cpp +++ b/src/gpu/vk/GrVkPipelineStateCache.cpp @@ -101,6 +101,13 @@ sk_sp GrVkResourceProvider::PipelineStateCache::refPipelineSt std::unique_ptr* entry = fMap.find(desc); if (!entry) { + // Didn't find an origin-independent version, check with the specific origin + GrSurfaceOrigin origin = pipeline.getRenderTarget()->origin(); + desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin)); + desc.finalize(); + entry = fMap.find(desc); + } + if (!entry) { #ifdef GR_PIPELINE_STATE_CACHE_STATS ++fCacheMisses; #endif @@ -110,7 +117,7 @@ sk_sp GrVkResourceProvider::PipelineStateCache::refPipelineSt stencil, primProc, primitiveType, - desc, + &desc, renderPass)); if (nullptr == pipelineState) { return nullptr; diff --git a/src/sksl/README b/src/sksl/README index d18367f..a4117ca 100644 --- a/src/sksl/README +++ b/src/sksl/README @@ -33,8 +33,10 @@ following differences between SkSL and GLSL: 'do_something_else();', depending on whether that cap is enabled or not. * no #version statement is required, and will be ignored if present * the output color is sk_FragColor (do not declare it) +* the fragment coordinate is sk_FragCoord, and is always relative to the upper + left. * lowp, mediump, and highp are always permitted (but will only be respected if - you run on a GLES device) + you run on a device which supports them) * you do not need to include ".0" to make a number a float (meaning that "vec2(x, y) * 4" is perfectly legal in SkSL, unlike GLSL where it would often have to be expressed "vec2(x, y) * 4.0". There is no performance penalty for diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index 55d9d2c..ebb4c52 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -624,11 +624,14 @@ std::unique_ptr IRGenerator::convertIdentifier(const ASTIdentifier& f->fFunctions)); } case Symbol::kVariable_Kind: { - Variable* var = (Variable*) result; - if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN && - fSettings->fFlipY && - (!fSettings->fCaps || !fSettings->fCaps->fragCoordConventionsExtensionString())) { - fInputs.fRTHeight = true; + const Variable* var = (const Variable*) result; + if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) { + fInputs.fFlipY = true; + if (fSettings->fFlipY && + (!fSettings->fCaps || + !fSettings->fCaps->fragCoordConventionsExtensionString())) { + fInputs.fRTHeight = true; + } } // default to kRead_RefKind; this will be corrected later if the variable is written to return std::unique_ptr(new VariableReference( diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h index 6a73be6..e4a975b 100644 --- a/src/sksl/ir/SkSLProgram.h +++ b/src/sksl/ir/SkSLProgram.h @@ -27,6 +27,8 @@ namespace SkSL { struct Program { struct Settings { const GrShaderCaps* fCaps = nullptr; + // if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate + // must be flipped. bool fFlipY = false; }; @@ -34,12 +36,17 @@ struct Program { // if true, this program requires the render target height uniform to be defined bool fRTHeight; + // if true, this program must be recompiled if the flipY setting changes. If false, the + // program will compile to the same code regardless of the flipY setting. + bool fFlipY; + void reset() { fRTHeight = false; + fFlipY = false; } bool isEmpty() { - return !fRTHeight; + return !fRTHeight && !fFlipY; } }; diff --git a/tests/ImageStorageTest.cpp b/tests/ImageStorageTest.cpp index 8ffb82d..a55c61b 100644 --- a/tests/ImageStorageTest.cpp +++ b/tests/ImageStorageTest.cpp @@ -30,7 +30,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageStorageLoad, reporter, ctxInfo) { TestFP(sk_sp texture, GrSLMemoryModel mm, GrSLRestrict restrict) : fImageStorageAccess(std::move(texture), kRead_GrIOType, mm, restrict) { this->initClassID(); - this->setWillReadFragmentPosition(); this->addImageStorageAccess(&fImageStorageAccess); } @@ -50,8 +49,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageStorageLoad, reporter, ctxInfo) { const TestFP& tfp = args.fFp.cast(); GrGLSLFPFragmentBuilder* fb = args.fFragBuilder; SkString imageLoadStr; - fb->codeAppendf("highp vec2 coord = %s.xy;", - args.fFragBuilder->fragmentPosition()); + fb->codeAppend("highp vec2 coord = sk_FragCoord.xy;"); fb->appendImageStorageLoad(&imageLoadStr, args.fImageStorages[0], "ivec2(coord)"); if (GrPixelConfigIsSint(tfp.fImageStorageAccess.texture()->config())) { diff --git a/tests/SkSLErrorTest.cpp b/tests/SkSLErrorTest.cpp index a33e6f1..c28dbbb 100644 --- a/tests/SkSLErrorTest.cpp +++ b/tests/SkSLErrorTest.cpp @@ -418,4 +418,13 @@ DEF_TEST(SkSLDivByZero, r) { "error: 1: division by zero\n1 error\n"); } +DEF_TEST(SkSLUnsupportedGLSLIdentifiers, r) { + test_failure(r, + "void main() { float x = gl_FragCoord.x; };", + "error: 1: unknown identifier 'gl_FragCoord'\n1 error\n"); + test_failure(r, + "void main() { float r = gl_FragColor.r; };", + "error: 1: unknown identifier 'gl_FragColor'\n1 error\n"); +} + #endif -- 2.7.4