ccpr: Normalize homogeneous coords with frexp/ldexp
Hopefully increases cubic accuracy by manipulating exponents instead of calling normalize(). Bug: skia: Change-Id: I8d3596e858a2fbb6650c158753133c5a2e01e166 Reviewed-on: https://skia-review.googlesource.com/117009 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Ethan Nicholas <ethannicholas@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
parent
64ecdce4ad
commit
7c7ff031a5
@ -76,6 +76,9 @@ public:
|
||||
|
||||
bool vertexIDSupport() const { return fVertexIDSupport; }
|
||||
|
||||
// frexp, ldexp, etc.
|
||||
bool fpManipulationSupport() const { return fFPManipulationSupport; }
|
||||
|
||||
bool floatIs32Bits() const { return fFloatIs32Bits; }
|
||||
|
||||
bool halfIs32Bits() const { return fHalfIs32Bits; }
|
||||
@ -250,6 +253,7 @@ private:
|
||||
bool fExternalTextureSupport : 1;
|
||||
bool fTexelFetchSupport : 1;
|
||||
bool fVertexIDSupport : 1;
|
||||
bool fFPManipulationSupport : 1;
|
||||
bool fFloatIs32Bits : 1;
|
||||
bool fHalfIs32Bits : 1;
|
||||
|
||||
|
@ -46,6 +46,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
|
||||
fExternalTextureSupport = false;
|
||||
fTexelFetchSupport = false;
|
||||
fVertexIDSupport = false;
|
||||
fFPManipulationSupport = false;
|
||||
fFloatIs32Bits = true;
|
||||
fHalfIs32Bits = false;
|
||||
|
||||
@ -118,6 +119,7 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
|
||||
writer->appendBool("External texture support", fExternalTextureSupport);
|
||||
writer->appendBool("texelFetch support", fTexelFetchSupport);
|
||||
writer->appendBool("sk_VertexID support", fVertexIDSupport);
|
||||
writer->appendBool("Floating point manipulation support", fFPManipulationSupport);
|
||||
writer->appendBool("float == fp32", fFloatIs32Bits);
|
||||
writer->appendBool("half == fp32", fHalfIs32Bits);
|
||||
|
||||
|
@ -8,12 +8,35 @@
|
||||
#include "GrCCCubicShader.h"
|
||||
|
||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "glsl/GrGLSLProgramBuilder.h"
|
||||
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||
|
||||
using Shader = GrCCCoverageProcessor::Shader;
|
||||
|
||||
void GrCCCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* wind, const char** /*tighterHull*/) const {
|
||||
// Define a function that normalizes the homogeneous coordinates T=t/s in order to avoid
|
||||
// exponent overflow.
|
||||
SkString normalizeHomogCoordFn;
|
||||
GrShaderVar coord("coord", kFloat2_GrSLType);
|
||||
s->emitFunction(kFloat2_GrSLType, "normalize_homogeneous_coord", 1, &coord,
|
||||
s->getProgramBuilder()->shaderCaps()->fpManipulationSupport()
|
||||
// Exponent manipulation version: Scale the exponents so the larger
|
||||
// component has a magnitude in 1..2.
|
||||
// (Neither component should be infinity because ccpr crops big paths.)
|
||||
? "int exp;"
|
||||
"frexp(max(abs(coord.t), abs(coord.s)), exp);"
|
||||
"return coord * ldexp(1, 1 - exp);"
|
||||
|
||||
// Division version: Divide by the component with the larger magnitude.
|
||||
// (Both should not be 0 because ccpr catches degenerate cubics.)
|
||||
: "bool swap = abs(coord.t) > abs(coord.s);"
|
||||
"coord = swap ? coord.ts : coord;"
|
||||
"coord = float2(1, coord.t/coord.s);"
|
||||
"return swap ? coord.ts : coord;",
|
||||
|
||||
&normalizeHomogCoordFn);
|
||||
|
||||
// Find the cubic's power basis coefficients.
|
||||
s->codeAppendf("float2x4 C = float4x4(-1, 3, -3, 1, "
|
||||
" 3, -6, 3, 0, "
|
||||
@ -33,9 +56,10 @@ void GrCCCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
s->codeAppend ("q = x*D2 + (D2 >= 0 ? q : -q);");
|
||||
|
||||
s->codeAppend ("float2 l, m;");
|
||||
s->codeAppend ("l.ts = normalize(float2(q, 2*x * D1));");
|
||||
s->codeAppend ("m.ts = normalize(float2(2, q) * (discr >= 0 ? float2(D3, 1) "
|
||||
": float2(D2*D2 - D3*D1, D1)));");
|
||||
s->codeAppendf("l.ts = %s(float2(q, 2*x * D1));", normalizeHomogCoordFn.c_str());
|
||||
s->codeAppendf("m.ts = %s(float2(2, q) * (discr >= 0 ? float2(D3, 1) "
|
||||
": float2(D2*D2 - D3*D1, D1)));",
|
||||
normalizeHomogCoordFn.c_str());
|
||||
|
||||
s->codeAppend ("float4 K;");
|
||||
s->codeAppend ("float4 lm = l.sstt * m.stst;");
|
||||
@ -46,7 +70,7 @@ void GrCCCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
s->codeAppend ("L = float4(-1,x,-x,1) * l.sstt * (discr >= 0 ? l.ssst * l.sttt : lm);");
|
||||
s->codeAppend ("M = float4(-1,x,-x,1) * m.sstt * (discr >= 0 ? m.ssst * m.sttt : lm.xzyw);");
|
||||
|
||||
s->codeAppend ("short middlerow = abs(D2) > abs(D1) ? 2 : 1;");
|
||||
s->codeAppend ("int middlerow = abs(D2) > abs(D1) ? 2 : 1;");
|
||||
s->codeAppend ("float3x3 CI = inverse(float3x3(C[0][0], C[0][middlerow], C[0][3], "
|
||||
"C[1][0], C[1][middlerow], C[1][3], "
|
||||
" 0, 0, 1));");
|
||||
@ -66,7 +90,7 @@ void GrCCCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
|
||||
// Determine the amount of additional coverage to subtract out for the flat edge (P3 -> P0).
|
||||
s->declareGlobal(fEdgeDistanceEquation);
|
||||
s->codeAppendf("short edgeidx0 = %s > 0 ? 3 : 0;", wind);
|
||||
s->codeAppendf("int edgeidx0 = %s > 0 ? 3 : 0;", wind);
|
||||
s->codeAppendf("float2 edgept0 = %s[edgeidx0];", pts);
|
||||
s->codeAppendf("float2 edgept1 = %s[3 - edgeidx0];", pts);
|
||||
Shader::EmitEdgeDistanceEquation(s, "edgept0", "edgept1", fEdgeDistanceEquation.c_str());
|
||||
|
@ -805,6 +805,12 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli
|
||||
shaderCaps->fVertexIDSupport = ctxInfo.glslGeneration() >= k330_GrGLSLGeneration;
|
||||
}
|
||||
|
||||
if (kGL_GrGLStandard == standard) {
|
||||
shaderCaps->fFPManipulationSupport = ctxInfo.glslGeneration() >= k400_GrGLSLGeneration;
|
||||
} else {
|
||||
shaderCaps->fFPManipulationSupport = ctxInfo.glslGeneration() >= k310es_GrGLSLGeneration;
|
||||
}
|
||||
|
||||
shaderCaps->fFloatIs32Bits = is_float_fp32(ctxInfo, gli, GR_GL_HIGH_FLOAT);
|
||||
shaderCaps->fHalfIs32Bits = is_float_fp32(ctxInfo, gli, GR_GL_MEDIUM_FLOAT);
|
||||
}
|
||||
|
@ -261,6 +261,7 @@ void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties, uint
|
||||
shaderCaps->fTexelBufferSupport = true;
|
||||
shaderCaps->fTexelFetchSupport = true;
|
||||
shaderCaps->fVertexIDSupport = true;
|
||||
shaderCaps->fFPManipulationSupport = true;
|
||||
|
||||
// Assume the minimum precisions mandated by the SPIR-V spec.
|
||||
shaderCaps->fFloatIs32Bits = true;
|
||||
|
Loading…
Reference in New Issue
Block a user