Revert "Fix precision caps and rrect/ellipse effect precisions"
This reverts commit e421800227
.
Reason for revert: Also may be responsible for layout test failures? Playing it safe.
Original change's description:
> Fix precision caps and rrect/ellipse effect precisions
>
> Replaces all the complex precision caps with a single flag that says
> whether "float" == fp32. Updates the ellipse and rrect effects to
> use float coords, and use the scale workaround when float != fp32.
>
> Bug: skia:7190
> Change-Id: Ieccff9f38acd05e5cec78fe90d01a5da901a9307
> Reviewed-on: https://skia-review.googlesource.com/70961
> Commit-Queue: Chris Dalton <csmartdalton@google.com>
> Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>
TBR=egdaniel@google.com,bsalomon@google.com,csmartdalton@google.com,ethannicholas@google.com
Change-Id: Idca2f0390e7a0eb85010255183f2f27332b8d26d
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:7190
Reviewed-on: https://skia-review.googlesource.com/72540
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
554c1f0508
commit
24f9c19172
@ -20,6 +20,40 @@ class SkJSONWriter;
|
||||
|
||||
class GrShaderCaps : public SkRefCnt {
|
||||
public:
|
||||
/** Info about shader variable precision within a given shader stage. That is, this info
|
||||
is relevant to a float (or vecNf) variable declared with a GrSLPrecision
|
||||
in a given GrShaderType. The info here is hoisted from the OpenGL spec. */
|
||||
struct PrecisionInfo {
|
||||
PrecisionInfo() {
|
||||
fLogRangeLow = 0;
|
||||
fLogRangeHigh = 0;
|
||||
fBits = 0;
|
||||
}
|
||||
|
||||
/** Is this precision level allowed in the shader stage? */
|
||||
bool supported() const { return 0 != fBits; }
|
||||
|
||||
bool operator==(const PrecisionInfo& that) const {
|
||||
return fLogRangeLow == that.fLogRangeLow && fLogRangeHigh == that.fLogRangeHigh &&
|
||||
fBits == that.fBits;
|
||||
}
|
||||
bool operator!=(const PrecisionInfo& that) const { return !(*this == that); }
|
||||
|
||||
/** floor(log2(|min_value|)) */
|
||||
int fLogRangeLow;
|
||||
/** floor(log2(|max_value|)) */
|
||||
int fLogRangeHigh;
|
||||
/** Number of bits of precision. As defined in OpenGL (with names modified to reflect this
|
||||
struct) :
|
||||
"""
|
||||
If the smallest representable value greater than 1 is 1 + e, then fBits will
|
||||
contain floor(log2(e)), and every value in the range [2^fLogRangeLow,
|
||||
2^fLogRangeHigh] can be represented to at least one part in 2^fBits.
|
||||
"""
|
||||
*/
|
||||
int fBits;
|
||||
};
|
||||
|
||||
/**
|
||||
* Indicates how GLSL must interact with advanced blend equations. The KHR extension requires
|
||||
* special layout qualifiers in the fragment shader.
|
||||
@ -47,6 +81,24 @@ public:
|
||||
bool texelBufferSupport() const { return fTexelBufferSupport; }
|
||||
int imageLoadStoreSupport() const { return fImageLoadStoreSupport; }
|
||||
|
||||
/**
|
||||
* Get the precision info for a variable of type kFloat_GrSLType, kFloat2_GrSLType, etc in a
|
||||
* given shader type. If the shader type is not supported or the precision level is not
|
||||
* supported in that shader type then the returned struct will report false when supported() is
|
||||
* called.
|
||||
*/
|
||||
const PrecisionInfo& getFloatShaderPrecisionInfo(GrShaderType shaderType,
|
||||
GrSLPrecision precision) const {
|
||||
return fFloatPrecisions[shaderType][precision];
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there any difference between the float shader variable precision types? If this is true
|
||||
* then unless the shader type is not supported, any call to getFloatShaderPrecisionInfo() would
|
||||
* report the same info for all precisions in all shader types.
|
||||
*/
|
||||
bool floatPrecisionVaries() const { return fShaderPrecisionVaries; }
|
||||
|
||||
/**
|
||||
* Some helper functions for encapsulating various extensions to read FB Buffer on openglES
|
||||
*
|
||||
@ -84,10 +136,6 @@ public:
|
||||
|
||||
bool vertexIDSupport() const { return fVertexIDSupport; }
|
||||
|
||||
bool floatIs32Bits() const { return fFloatIs32Bits; }
|
||||
|
||||
bool halfIs32Bits() const { return fHalfIs32Bits; }
|
||||
|
||||
AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
|
||||
|
||||
bool mustEnableAdvBlendEqs() const {
|
||||
@ -212,9 +260,17 @@ public:
|
||||
return fConfigOutputSwizzle[config];
|
||||
}
|
||||
|
||||
/** Precision qualifier that should be used with a sampler, given its config and visibility. */
|
||||
GrSLPrecision samplerPrecision(GrPixelConfig config, GrShaderFlags visibility) const {
|
||||
return static_cast<GrSLPrecision>(fSamplerPrecisions[visibility][config]);
|
||||
}
|
||||
|
||||
GrGLSLGeneration generation() const { return fGLSLGeneration; }
|
||||
|
||||
private:
|
||||
/** GrCaps subclasses must call this after filling in the shader precision table. */
|
||||
void initSamplerPrecisionTable();
|
||||
|
||||
void applyOptionsOverrides(const GrContextOptions& options);
|
||||
|
||||
GrGLSLGeneration fGLSLGeneration;
|
||||
@ -228,6 +284,7 @@ private:
|
||||
bool fIntegerSupport : 1;
|
||||
bool fTexelBufferSupport : 1;
|
||||
bool fImageLoadStoreSupport : 1;
|
||||
bool fShaderPrecisionVaries : 1;
|
||||
bool fDropsTileOnZeroDivide : 1;
|
||||
bool fFBFetchSupport : 1;
|
||||
bool fFBFetchNeedsCustomOutput : 1;
|
||||
@ -243,8 +300,6 @@ private:
|
||||
bool fExternalTextureSupport : 1;
|
||||
bool fTexelFetchSupport : 1;
|
||||
bool fVertexIDSupport : 1;
|
||||
bool fFloatIs32Bits : 1;
|
||||
bool fHalfIs32Bits : 1;
|
||||
bool fDisableImageMultitexturing : 1;
|
||||
|
||||
// Used for specific driver bug work arounds
|
||||
@ -256,6 +311,8 @@ private:
|
||||
bool fMustObfuscateUniformColor : 1;
|
||||
bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1;
|
||||
|
||||
PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];
|
||||
|
||||
const char* fVersionDeclString;
|
||||
|
||||
const char* fShaderDerivativeExtensionString;
|
||||
@ -282,6 +339,8 @@ private:
|
||||
GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt];
|
||||
GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt];
|
||||
|
||||
uint8_t fSamplerPrecisions[(1 << kGrShaderTypeCount)][kGrPixelConfigCnt];
|
||||
|
||||
friend class GrGLCaps; // For initialization.
|
||||
friend class GrMockCaps;
|
||||
friend class GrMtlCaps;
|
||||
|
@ -909,33 +909,6 @@ static inline bool GrPixelConfigIsUnorm(GrPixelConfig config) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Precision qualifier that should be used with a sampler.
|
||||
*/
|
||||
static inline GrSLPrecision GrSLSamplerPrecision(GrPixelConfig config) {
|
||||
switch (config) {
|
||||
case kUnknown_GrPixelConfig:
|
||||
case kAlpha_8_GrPixelConfig:
|
||||
case kGray_8_GrPixelConfig:
|
||||
case kRGB_565_GrPixelConfig:
|
||||
case kRGBA_4444_GrPixelConfig:
|
||||
case kRGBA_8888_GrPixelConfig:
|
||||
case kBGRA_8888_GrPixelConfig:
|
||||
case kSRGBA_8888_GrPixelConfig:
|
||||
case kSBGRA_8888_GrPixelConfig:
|
||||
case kRGBA_8888_sint_GrPixelConfig:
|
||||
return kLow_GrSLPrecision;
|
||||
case kRGBA_float_GrPixelConfig:
|
||||
case kRG_float_GrPixelConfig:
|
||||
return kHigh_GrSLPrecision;
|
||||
case kAlpha_half_GrPixelConfig:
|
||||
case kRGBA_half_GrPixelConfig:
|
||||
return kMedium_GrSLPrecision;
|
||||
}
|
||||
SK_ABORT("Unexpected type");
|
||||
return kHigh_GrSLPrecision;
|
||||
}
|
||||
|
||||
static inline GrPixelConfigIsClamped GrGetPixelConfigIsClamped(GrPixelConfig config) {
|
||||
return GrPixelConfigIsFloatingPoint(config) ? GrPixelConfigIsClamped::kNo
|
||||
: GrPixelConfigIsClamped::kYes;
|
||||
|
@ -52,7 +52,7 @@ static uint16_t sampler_key(GrSLType samplerType, GrPixelConfig config, GrShader
|
||||
GR_STATIC_ASSERT(1 == sizeof(caps.configTextureSwizzle(config).asKey()));
|
||||
return SkToU16(samplerTypeKey |
|
||||
caps.configTextureSwizzle(config).asKey() << kSamplerOrImageTypeKeyBits |
|
||||
(GrSLSamplerPrecision(config) << (8 + kSamplerOrImageTypeKeyBits)));
|
||||
(caps.samplerPrecision(config, visibility) << (8 + kSamplerOrImageTypeKeyBits)));
|
||||
}
|
||||
|
||||
static void add_sampler_and_image_keys(GrProcessorKeyBuilder* b, const GrResourceIOProcessor& proc,
|
||||
|
@ -13,6 +13,32 @@
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const char* shader_type_to_string(GrShaderType type) {
|
||||
switch (type) {
|
||||
case kVertex_GrShaderType:
|
||||
return "vertex";
|
||||
case kGeometry_GrShaderType:
|
||||
return "geometry";
|
||||
case kFragment_GrShaderType:
|
||||
return "fragment";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char* precision_to_string(GrSLPrecision p) {
|
||||
switch (p) {
|
||||
case kLow_GrSLPrecision:
|
||||
return "low";
|
||||
case kMedium_GrSLPrecision:
|
||||
return "medium";
|
||||
case kHigh_GrSLPrecision:
|
||||
return "high";
|
||||
default:
|
||||
SK_ABORT("Unexpected precision type.");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
|
||||
fGLSLGeneration = k330_GrGLSLGeneration;
|
||||
fShaderDerivativeSupport = false;
|
||||
@ -24,6 +50,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
|
||||
fIntegerSupport = false;
|
||||
fTexelBufferSupport = false;
|
||||
fImageLoadStoreSupport = false;
|
||||
fShaderPrecisionVaries = false;
|
||||
fDropsTileOnZeroDivide = false;
|
||||
fFBFetchSupport = false;
|
||||
fFBFetchNeedsCustomOutput = false;
|
||||
@ -46,8 +73,6 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
|
||||
fExternalTextureSupport = false;
|
||||
fTexelFetchSupport = false;
|
||||
fVertexIDSupport = false;
|
||||
fFloatIs32Bits = true;
|
||||
fHalfIs32Bits = false;
|
||||
|
||||
fVersionDeclString = nullptr;
|
||||
fShaderDerivativeExtensionString = nullptr;
|
||||
@ -88,6 +113,26 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
|
||||
writer->appendBool("Texel Buffer Support", fTexelBufferSupport);
|
||||
writer->appendBool("Image Load Store Support", fImageLoadStoreSupport);
|
||||
|
||||
writer->appendBool("Variable Precision", fShaderPrecisionVaries);
|
||||
|
||||
for (int s = 0; s < kGrShaderTypeCount; ++s) {
|
||||
GrShaderType shaderType = static_cast<GrShaderType>(s);
|
||||
writer->beginArray(SkStringPrintf("%s precisions",
|
||||
shader_type_to_string(shaderType)).c_str());
|
||||
for (int p = 0; p < kGrSLPrecisionCount; ++p) {
|
||||
if (fFloatPrecisions[s][p].supported()) {
|
||||
GrSLPrecision precision = static_cast<GrSLPrecision>(p);
|
||||
writer->beginObject(nullptr, false);
|
||||
writer->appendString("precision", precision_to_string(precision));
|
||||
writer->appendS32("log_low", fFloatPrecisions[s][p].fLogRangeLow);
|
||||
writer->appendS32("log_high", fFloatPrecisions[s][p].fLogRangeHigh);
|
||||
writer->appendS32("bits", fFloatPrecisions[s][p].fBits);
|
||||
writer->endObject();
|
||||
}
|
||||
}
|
||||
writer->endArray();
|
||||
}
|
||||
|
||||
static const char* kAdvBlendEqInteractionStr[] = {
|
||||
"Not Supported",
|
||||
"Automatic",
|
||||
@ -121,8 +166,6 @@ 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("float == fp32", fFloatIs32Bits);
|
||||
writer->appendBool("half == fp32", fHalfIs32Bits);
|
||||
|
||||
writer->appendS32("Max VS Samplers", fMaxVertexSamplers);
|
||||
writer->appendS32("Max GS Samplers", fMaxGeometrySamplers);
|
||||
@ -135,6 +178,59 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
|
||||
writer->endObject();
|
||||
}
|
||||
|
||||
void GrShaderCaps::initSamplerPrecisionTable() {
|
||||
// Determine the largest precision qualifiers that are effectively the same as lowp/mediump.
|
||||
// e.g. if lowp == mediump, then use mediump instead of lowp.
|
||||
GrSLPrecision effectiveMediumP[kGrShaderTypeCount];
|
||||
GrSLPrecision effectiveLowP[kGrShaderTypeCount];
|
||||
for (int s = 0; s < kGrShaderTypeCount; ++s) {
|
||||
const PrecisionInfo* info = fFloatPrecisions[s];
|
||||
effectiveMediumP[s] = info[kHigh_GrSLPrecision] == info[kMedium_GrSLPrecision] ?
|
||||
kHigh_GrSLPrecision : kMedium_GrSLPrecision;
|
||||
effectiveLowP[s] = info[kMedium_GrSLPrecision] == info[kLow_GrSLPrecision] ?
|
||||
effectiveMediumP[s] : kLow_GrSLPrecision;
|
||||
}
|
||||
|
||||
// Determine which precision qualifiers should be used with samplers.
|
||||
for (int visibility = 0; visibility < (1 << kGrShaderTypeCount); ++visibility) {
|
||||
GrSLPrecision mediump = kHigh_GrSLPrecision;
|
||||
GrSLPrecision lowp = kHigh_GrSLPrecision;
|
||||
for (int s = 0; s < kGrShaderTypeCount; ++s) {
|
||||
if (visibility & (1 << s)) {
|
||||
mediump = SkTMin(mediump, effectiveMediumP[s]);
|
||||
lowp = SkTMin(lowp, effectiveLowP[s]);
|
||||
}
|
||||
|
||||
GR_STATIC_ASSERT(0 == kLow_GrSLPrecision);
|
||||
GR_STATIC_ASSERT(1 == kMedium_GrSLPrecision);
|
||||
GR_STATIC_ASSERT(2 == kHigh_GrSLPrecision);
|
||||
|
||||
GR_STATIC_ASSERT((1 << kVertex_GrShaderType) == kVertex_GrShaderFlag);
|
||||
GR_STATIC_ASSERT((1 << kGeometry_GrShaderType) == kGeometry_GrShaderFlag);
|
||||
GR_STATIC_ASSERT((1 << kFragment_GrShaderType) == kFragment_GrShaderFlag);
|
||||
GR_STATIC_ASSERT(3 == kGrShaderTypeCount);
|
||||
}
|
||||
|
||||
uint8_t* table = fSamplerPrecisions[visibility];
|
||||
table[kUnknown_GrPixelConfig] = lowp;
|
||||
table[kAlpha_8_GrPixelConfig] = lowp;
|
||||
table[kGray_8_GrPixelConfig] = lowp;
|
||||
table[kRGB_565_GrPixelConfig] = lowp;
|
||||
table[kRGBA_4444_GrPixelConfig] = lowp;
|
||||
table[kRGBA_8888_GrPixelConfig] = lowp;
|
||||
table[kBGRA_8888_GrPixelConfig] = lowp;
|
||||
table[kSRGBA_8888_GrPixelConfig] = lowp;
|
||||
table[kSBGRA_8888_GrPixelConfig] = lowp;
|
||||
table[kRGBA_8888_sint_GrPixelConfig] = lowp;
|
||||
table[kRGBA_float_GrPixelConfig] = kHigh_GrSLPrecision;
|
||||
table[kRG_float_GrPixelConfig] = kHigh_GrSLPrecision;
|
||||
table[kAlpha_half_GrPixelConfig] = mediump;
|
||||
table[kRGBA_half_GrPixelConfig] = mediump;
|
||||
|
||||
GR_STATIC_ASSERT(14 == kGrPixelConfigCnt);
|
||||
}
|
||||
}
|
||||
|
||||
void GrShaderCaps::applyOptionsOverrides(const GrContextOptions& options) {
|
||||
#if GR_TEST_UTILS
|
||||
fDualSourceBlendingSupport = fDualSourceBlendingSupport && !options.fSuppressDualSourceBlending;
|
||||
|
@ -28,33 +28,34 @@ public:
|
||||
(void)center;
|
||||
auto radii = _outer.radii();
|
||||
(void)radii;
|
||||
prevRadii = float2(-1.0);
|
||||
useScale = !sk_Caps.floatIs32Bits;
|
||||
prevRadii = half2(-1.0);
|
||||
useScale = sk_Caps.floatPrecisionVaries;
|
||||
fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType,
|
||||
kDefault_GrSLPrecision, "ellipse");
|
||||
if (useScale) {
|
||||
fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat2_GrSLType,
|
||||
fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
kDefault_GrSLPrecision, "scale");
|
||||
}
|
||||
fragBuilder->codeAppendf(
|
||||
"float2 prevCenter;\nfloat2 prevRadii = float2(%f, %f);\nbool useScale = "
|
||||
"%s;\nfloat2 d = sk_FragCoord.xy - %s.xy;\n@if (useScale) {\n d *= "
|
||||
"%s.y;\n}\nfloat2 Z = d * %s.zw;\nfloat implicit = dot(Z, d) - 1.0;\nfloat "
|
||||
"grad_dot = 4.0 * dot(Z, Z);\ngrad_dot = max(grad_dot, 0.0001);\nfloat approx_dist "
|
||||
"= implicit * inversesqrt(grad_dot);\n@if (useScale) {\n approx_dist *= "
|
||||
"%s.x;\n}\nhalf alpha;\n@switch (%d) {\n case 0:\n alpha = "
|
||||
"half(approx_dist > 0.0 ? 0.0 : 1.0);\n break;\n case 1:\n ",
|
||||
"half2 prevCenter;\nhalf2 prevRadii = half2(%f, %f);\nbool useScale = %s;\nhalf2 d "
|
||||
"= half2(sk_FragCoord.xy - %s.xy);\n@if (useScale) {\n d *= %s.y;\n}\nhalf2 Z = "
|
||||
"d * half2(%s.zw);\nhalf implicit = dot(Z, d) - 1.0;\nhalf grad_dot = 4.0 * dot(Z, "
|
||||
"Z);\ngrad_dot = half(max(float(grad_dot), 0.0001));\nhalf approx_dist = "
|
||||
"float(implicit) * inversesqrt(float(grad_dot));\n@if (useScale) {\n "
|
||||
"approx_dist *= %s.x;\n}\nhalf alpha;\n@switch (%d) {\n case 0:\n alpha "
|
||||
"= half(float(approx_dist) > 0.0 ? 0.0 : 1.",
|
||||
prevRadii.fX, prevRadii.fY, (useScale ? "true" : "false"),
|
||||
args.fUniformHandler->getUniformCStr(fEllipseVar),
|
||||
fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "float2(0)",
|
||||
fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "half2(0)",
|
||||
args.fUniformHandler->getUniformCStr(fEllipseVar),
|
||||
fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "float2(0)",
|
||||
fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "half2(0)",
|
||||
(int)_outer.edgeType());
|
||||
fragBuilder->codeAppendf(
|
||||
" alpha = half(clamp(0.5 - approx_dist, 0.0, 1.0));\n break;\n case "
|
||||
"2:\n alpha = half(approx_dist > 0.0 ? 1.0 : 0.0);\n break;\n "
|
||||
"case 3:\n alpha = half(clamp(0.5 + approx_dist, 0.0, 1.0));\n "
|
||||
"break;\n default:\n discard;\n}\n%s = %s * alpha;\n",
|
||||
"0);\n break;\n case 1:\n alpha = half(clamp(0.5 - "
|
||||
"float(approx_dist), 0.0, 1.0));\n break;\n case 2:\n alpha = "
|
||||
"half(float(approx_dist) > 0.0 ? 1.0 : 0.0);\n break;\n case 3:\n "
|
||||
"alpha = half(clamp(0.5 + float(approx_dist), 0.0, 1.0));\n break;\n "
|
||||
"default:\n discard;\n}\n%s = %s * alpha;\n",
|
||||
args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)");
|
||||
}
|
||||
|
||||
|
@ -6,17 +6,17 @@
|
||||
*/
|
||||
|
||||
layout(key) in GrClipEdgeType edgeType;
|
||||
in float2 center;
|
||||
in float2 radii;
|
||||
in half2 center;
|
||||
in half2 radii;
|
||||
|
||||
float2 prevCenter;
|
||||
float2 prevRadii = float2(-1);
|
||||
half2 prevCenter;
|
||||
half2 prevRadii = half2(-1);
|
||||
// The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
|
||||
// The last two terms can underflow when float != fp32, so we also provide a workaround.
|
||||
// The last two terms can underflow with halfs, so we use floats.
|
||||
uniform float4 ellipse;
|
||||
|
||||
bool useScale = !sk_Caps.floatIs32Bits;
|
||||
layout(when=useScale) uniform float2 scale;
|
||||
bool useScale = sk_Caps.floatPrecisionVaries;
|
||||
layout(when=useScale) uniform half2 scale;
|
||||
|
||||
@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
|
||||
|
||||
@ -50,7 +50,7 @@ layout(when=useScale) uniform float2 scale;
|
||||
|
||||
void main() {
|
||||
// d is the offset to the ellipse center
|
||||
float2 d = sk_FragCoord.xy - ellipse.xy;
|
||||
half2 d = sk_FragCoord.xy - ellipse.xy;
|
||||
// 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 larger radius. The scale uniform will be scale, 1/scale. The
|
||||
// inverse squared radii uniform values are already in this normalized space. The center is
|
||||
@ -58,14 +58,14 @@ void main() {
|
||||
@if (useScale) {
|
||||
d *= scale.y;
|
||||
}
|
||||
float2 Z = d * ellipse.zw;
|
||||
half2 Z = d * ellipse.zw;
|
||||
// implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
|
||||
float implicit = dot(Z, d) - 1;
|
||||
half implicit = dot(Z, d) - 1;
|
||||
// grad_dot is the squared length of the gradient of the implicit.
|
||||
float grad_dot = 4 * dot(Z, Z);
|
||||
half grad_dot = 4 * dot(Z, Z);
|
||||
// Avoid calling inversesqrt on zero.
|
||||
grad_dot = max(grad_dot, 1e-4);
|
||||
float approx_dist = implicit * inversesqrt(grad_dot);
|
||||
half approx_dist = implicit * inversesqrt(grad_dot);
|
||||
@if (useScale) {
|
||||
approx_dist *= scale.x;
|
||||
}
|
||||
@ -102,4 +102,4 @@ void main() {
|
||||
et = (GrClipEdgeType) testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
|
||||
} while (GrClipEdgeType::kHairlineAA == et);
|
||||
return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry));
|
||||
}
|
||||
}
|
@ -165,9 +165,9 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
|
||||
fRadiusPlusHalfUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"radiusPlusHalf", &radiusPlusHalfName);
|
||||
|
||||
// If we're on a device where float != fp32 then the length calculation could overflow.
|
||||
// If we're on a device with a "real" mediump then the length calculation could overflow.
|
||||
SkString clampedCircleDistance;
|
||||
if (!args.fShaderCaps->floatIs32Bits()) {
|
||||
if (args.fShaderCaps->floatPrecisionVaries()) {
|
||||
clampedCircleDistance.printf("clamp(%s.x * (1.0 - length(dxy * %s.y)), 0.0, 1.0);",
|
||||
radiusPlusHalfName, radiusPlusHalfName);
|
||||
} else {
|
||||
@ -192,13 +192,13 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
|
||||
// alphas together.
|
||||
switch (crre.getCircularCornerFlags()) {
|
||||
case CircularRRectEffect::kAll_CornerFlags:
|
||||
fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);");
|
||||
fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);");
|
||||
fragBuilder->codeAppendf("half alpha = %s;", clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kTopLeft_CornerFlag:
|
||||
fragBuilder->codeAppendf("float2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);",
|
||||
fragBuilder->codeAppendf("half2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
@ -208,8 +208,8 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kTopRight_CornerFlag:
|
||||
fragBuilder->codeAppendf("float2 dxy = max(float2(sk_FragCoord.x - %s.z, "
|
||||
"%s.y - sk_FragCoord.y), 0.0);",
|
||||
fragBuilder->codeAppendf("half2 dxy = max(half2(sk_FragCoord.x - %s.z, "
|
||||
"%s.y - sk_FragCoord.y), 0.0);",
|
||||
rectName, rectName);
|
||||
fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
@ -219,7 +219,7 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kBottomRight_CornerFlag:
|
||||
fragBuilder->codeAppendf("float2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);",
|
||||
fragBuilder->codeAppendf("half2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
@ -229,8 +229,8 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kBottomLeft_CornerFlag:
|
||||
fragBuilder->codeAppendf("float2 dxy = max(float2(%s.x - sk_FragCoord.x, "
|
||||
"sk_FragCoord.y - %s.w), 0.0);",
|
||||
fragBuilder->codeAppendf("half2 dxy = max(half2(%s.x - sk_FragCoord.x, sk_FragCoord.y - "
|
||||
"%s.w), 0.0);",
|
||||
rectName, rectName);
|
||||
fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
@ -240,36 +240,36 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kLeft_CornerFlags:
|
||||
fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.w;", rectName);
|
||||
fragBuilder->codeAppend("float2 dxy = max(float2(dxy0.x, max(dxy0.y, dy1)), 0.0);");
|
||||
fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("half dy1 = sk_FragCoord.y - %s.w;", rectName);
|
||||
fragBuilder->codeAppend("half2 dxy = max(half2(dxy0.x, max(dxy0.y, dy1)), 0.0);");
|
||||
fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("half alpha = rightAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kTop_CornerFlags:
|
||||
fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.z;", rectName);
|
||||
fragBuilder->codeAppend("float2 dxy = max(float2(max(dxy0.x, dx1), dxy0.y), 0.0);");
|
||||
fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("half dx1 = sk_FragCoord.x - %s.z;", rectName);
|
||||
fragBuilder->codeAppend("half2 dxy = max(half2(max(dxy0.x, dx1), dxy0.y), 0.0);");
|
||||
fragBuilder->codeAppendf("half bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("half alpha = bottomAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kRight_CornerFlags:
|
||||
fragBuilder->codeAppendf("float dy0 = %s.y - sk_FragCoord.y;", rectName);
|
||||
fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppend("float2 dxy = max(float2(dxy1.x, max(dy0, dxy1.y)), 0.0);");
|
||||
fragBuilder->codeAppendf("half dy0 = %s.y - sk_FragCoord.y;", rectName);
|
||||
fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppend("half2 dxy = max(half2(dxy1.x, max(dy0, dxy1.y)), 0.0);");
|
||||
fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("half alpha = leftAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kBottom_CornerFlags:
|
||||
fragBuilder->codeAppendf("float dx0 = %s.x - sk_FragCoord.x;", rectName);
|
||||
fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppend("float2 dxy = max(float2(max(dx0, dxy1.x), dxy1.y), 0.0);");
|
||||
fragBuilder->codeAppendf("half dx0 = %s.x - sk_FragCoord.x;", rectName);
|
||||
fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppend("half2 dxy = max(half2(max(dx0, dxy1.x), dxy1.y), 0.0);");
|
||||
fragBuilder->codeAppendf("half topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("half alpha = topAlpha * %s;",
|
||||
@ -523,14 +523,14 @@ 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("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
|
||||
// If we're on a device where float != fp32 then we'll do the distance computation in a space
|
||||
// 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
|
||||
// radii uniform values are already in this normalized space.
|
||||
const char* scaleName = nullptr;
|
||||
if (!args.fShaderCaps->floatIs32Bits()) {
|
||||
if (args.fShaderCaps->floatPrecisionVaries()) {
|
||||
fScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "scale",
|
||||
&scaleName);
|
||||
}
|
||||
@ -543,12 +543,12 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
|
||||
kHalf2_GrSLType,
|
||||
"invRadiiXY",
|
||||
&invRadiiXYSqdName);
|
||||
fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);");
|
||||
fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);");
|
||||
if (scaleName) {
|
||||
fragBuilder->codeAppendf("dxy *= %s.y;", scaleName);
|
||||
}
|
||||
// Z is the x/y offsets divided by squared radii.
|
||||
fragBuilder->codeAppendf("float2 Z = dxy * %s.xy;", invRadiiXYSqdName);
|
||||
fragBuilder->codeAppendf("half2 Z = dxy * %s.xy;", invRadiiXYSqdName);
|
||||
break;
|
||||
}
|
||||
case SkRRect::kNinePatch_Type: {
|
||||
@ -561,11 +561,11 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
|
||||
fragBuilder->codeAppendf("dxy0 *= %s.y;", scaleName);
|
||||
fragBuilder->codeAppendf("dxy1 *= %s.y;", scaleName);
|
||||
}
|
||||
fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);");
|
||||
fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);");
|
||||
// Z is the x/y offsets divided by squared radii. We only care about the (at most) one
|
||||
// corner where both the x and y offsets are positive, hence the maxes. (The inverse
|
||||
// squared radii will always be positive.)
|
||||
fragBuilder->codeAppendf("float2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);",
|
||||
fragBuilder->codeAppendf("half2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);",
|
||||
invRadiiLTRBSqdName, invRadiiLTRBSqdName);
|
||||
|
||||
break;
|
||||
@ -574,12 +574,12 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
|
||||
SK_ABORT("RRect should always be simple or nine-patch.");
|
||||
}
|
||||
// implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1.
|
||||
fragBuilder->codeAppend("float implicit = dot(Z, dxy) - 1.0;");
|
||||
fragBuilder->codeAppend("half implicit = dot(Z, dxy) - 1.0;");
|
||||
// grad_dot is the squared length of the gradient of the implicit.
|
||||
fragBuilder->codeAppend("float grad_dot = 4.0 * dot(Z, Z);");
|
||||
fragBuilder->codeAppend("half grad_dot = 4.0 * dot(Z, Z);");
|
||||
// avoid calling inversesqrt on zero.
|
||||
fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
|
||||
fragBuilder->codeAppend("float approx_dist = implicit * inversesqrt(grad_dot);");
|
||||
fragBuilder->codeAppend("half approx_dist = implicit * inversesqrt(grad_dot);");
|
||||
if (scaleName) {
|
||||
fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName);
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
|
||||
**************************************************************************/
|
||||
|
||||
// This must be called after fCoreProfile is set on the GrGLCaps
|
||||
this->initGLSL(ctxInfo, gli);
|
||||
this->initGLSL(ctxInfo);
|
||||
GrShaderCaps* shaderCaps = fShaderCaps.get();
|
||||
|
||||
shaderCaps->fPathRenderingSupport = this->hasPathRenderingSupport(ctxInfo, gli);
|
||||
@ -634,6 +634,8 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
|
||||
fDrawRangeElementsSupport = version >= GR_GL_VER(3,0);
|
||||
}
|
||||
|
||||
this->initShaderPrecisionTable(ctxInfo, gli, shaderCaps);
|
||||
|
||||
if (kGL_GrGLStandard == standard) {
|
||||
if ((version >= GR_GL_VER(4, 0) || ctxInfo.hasExtension("GL_ARB_sample_shading")) &&
|
||||
ctxInfo.vendor() != kIntel_GrGLVendor) {
|
||||
@ -758,27 +760,7 @@ const char* get_glsl_version_decl_string(GrGLStandard standard, GrGLSLGeneration
|
||||
return "<no version>";
|
||||
}
|
||||
|
||||
bool is_float_fp32(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli, GrGLenum precision) {
|
||||
if (kGLES_GrGLStandard != ctxInfo.standard() &&
|
||||
ctxInfo.version() < GR_GL_VER(4,1) &&
|
||||
!ctxInfo.hasExtension("GL_ARB_ES2_compatibility")) {
|
||||
// We're on a desktop GL that doesn't have precision info. Assume they're all 32bit float.
|
||||
return true;
|
||||
}
|
||||
// glGetShaderPrecisionFormat doesn't accept GL_GEOMETRY_SHADER as a shader type. Hopefully the
|
||||
// geometry shaders don't have lower precision than vertex and fragment.
|
||||
for (GrGLenum shader : {GR_GL_FRAGMENT_SHADER, GR_GL_VERTEX_SHADER}) {
|
||||
GrGLint range[2];
|
||||
GrGLint bits;
|
||||
GR_GL_GetShaderPrecisionFormat(gli, shader, precision, range, &bits);
|
||||
if (range[0] < 127 || range[1] < 127 || bits < 23) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
||||
void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) {
|
||||
GrGLStandard standard = ctxInfo.standard();
|
||||
GrGLVersion version = ctxInfo.version();
|
||||
|
||||
@ -955,9 +937,6 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli
|
||||
shaderCaps->fVertexIDSupport = ctxInfo.glslGeneration() >= k330_GrGLSLGeneration;
|
||||
}
|
||||
|
||||
shaderCaps->fFloatIs32Bits = is_float_fp32(ctxInfo, gli, GR_GL_HIGH_FLOAT);
|
||||
shaderCaps->fHalfIs32Bits = is_float_fp32(ctxInfo, gli, GR_GL_MEDIUM_FLOAT);
|
||||
|
||||
if (kTegra3_GrGLRenderer == ctxInfo.renderer()) {
|
||||
// The Tegra3 compiler will sometimes never return if we have min(abs(x), 1.0),
|
||||
// so we must do the abs first in a separate expression.
|
||||
@ -1429,6 +1408,92 @@ void GrGLCaps::onDumpJSON(SkJSONWriter* writer) const {
|
||||
writer->endObject();
|
||||
}
|
||||
|
||||
static GrGLenum precision_to_gl_float_type(GrSLPrecision p) {
|
||||
switch (p) {
|
||||
case kLow_GrSLPrecision:
|
||||
return GR_GL_LOW_FLOAT;
|
||||
case kMedium_GrSLPrecision:
|
||||
return GR_GL_MEDIUM_FLOAT;
|
||||
case kHigh_GrSLPrecision:
|
||||
return GR_GL_HIGH_FLOAT;
|
||||
default:
|
||||
SK_ABORT("Unexpected precision type.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static GrGLenum shader_type_to_gl_shader(GrShaderType type) {
|
||||
switch (type) {
|
||||
case kVertex_GrShaderType:
|
||||
return GR_GL_VERTEX_SHADER;
|
||||
case kGeometry_GrShaderType:
|
||||
return GR_GL_GEOMETRY_SHADER;
|
||||
case kFragment_GrShaderType:
|
||||
return GR_GL_FRAGMENT_SHADER;
|
||||
}
|
||||
SK_ABORT("Unknown shader type.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GrGLCaps::initShaderPrecisionTable(const GrGLContextInfo& ctxInfo,
|
||||
const GrGLInterface* intf,
|
||||
GrShaderCaps* shaderCaps) {
|
||||
if (kGLES_GrGLStandard == ctxInfo.standard() || ctxInfo.version() >= GR_GL_VER(4, 1) ||
|
||||
ctxInfo.hasExtension("GL_ARB_ES2_compatibility")) {
|
||||
for (int s = 0; s < kGrShaderTypeCount; ++s) {
|
||||
if (kGeometry_GrShaderType != s) {
|
||||
GrShaderType shaderType = static_cast<GrShaderType>(s);
|
||||
GrGLenum glShader = shader_type_to_gl_shader(shaderType);
|
||||
GrShaderCaps::PrecisionInfo* first = nullptr;
|
||||
shaderCaps->fShaderPrecisionVaries = false;
|
||||
for (int p = 0; p < kGrSLPrecisionCount; ++p) {
|
||||
GrSLPrecision precision = static_cast<GrSLPrecision>(p);
|
||||
GrGLenum glPrecision = precision_to_gl_float_type(precision);
|
||||
GrGLint range[2];
|
||||
GrGLint bits;
|
||||
GR_GL_GetShaderPrecisionFormat(intf, glShader, glPrecision, range, &bits);
|
||||
if (bits) {
|
||||
shaderCaps->fFloatPrecisions[s][p].fLogRangeLow = range[0];
|
||||
shaderCaps->fFloatPrecisions[s][p].fLogRangeHigh = range[1];
|
||||
shaderCaps->fFloatPrecisions[s][p].fBits = bits;
|
||||
if (!first) {
|
||||
first = &shaderCaps->fFloatPrecisions[s][p];
|
||||
}
|
||||
else if (!shaderCaps->fShaderPrecisionVaries) {
|
||||
shaderCaps->fShaderPrecisionVaries =
|
||||
(*first != shaderCaps->fFloatPrecisions[s][p]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We're on a desktop GL that doesn't have precision info. Assume they're all 32bit float.
|
||||
shaderCaps->fShaderPrecisionVaries = false;
|
||||
for (int s = 0; s < kGrShaderTypeCount; ++s) {
|
||||
if (kGeometry_GrShaderType != s) {
|
||||
for (int p = 0; p < kGrSLPrecisionCount; ++p) {
|
||||
shaderCaps->fFloatPrecisions[s][p].fLogRangeLow = 127;
|
||||
shaderCaps->fFloatPrecisions[s][p].fLogRangeHigh = 127;
|
||||
shaderCaps->fFloatPrecisions[s][p].fBits = 23;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// GetShaderPrecisionFormat doesn't accept GL_GEOMETRY_SHADER as a shader type. Assume they're
|
||||
// the same as the vertex shader. Only fragment shaders were ever allowed to omit support for
|
||||
// highp. GS was added after GetShaderPrecisionFormat was added to the list of features that
|
||||
// are recommended against.
|
||||
if (shaderCaps->fGeometryShaderSupport) {
|
||||
for (int p = 0; p < kGrSLPrecisionCount; ++p) {
|
||||
shaderCaps->fFloatPrecisions[kGeometry_GrShaderType][p] =
|
||||
shaderCaps->fFloatPrecisions[kVertex_GrShaderType][p];
|
||||
}
|
||||
}
|
||||
shaderCaps->initSamplerPrecisionTable();
|
||||
}
|
||||
|
||||
bool GrGLCaps::bgraIsInternalFormat() const {
|
||||
return fConfigTable[kBGRA_8888_GrPixelConfig].fFormats.fBaseInternalFormat == GR_GL_BGRA;
|
||||
}
|
||||
|
@ -428,7 +428,7 @@ private:
|
||||
GrGLenum* externalType) const;
|
||||
|
||||
void init(const GrContextOptions&, const GrGLContextInfo&, const GrGLInterface*);
|
||||
void initGLSL(const GrGLContextInfo&, const GrGLInterface*);
|
||||
void initGLSL(const GrGLContextInfo&);
|
||||
bool hasPathRenderingSupport(const GrGLContextInfo&, const GrGLInterface*);
|
||||
|
||||
void onApplyOptionsOverrides(const GrContextOptions& options) override;
|
||||
@ -441,6 +441,8 @@ private:
|
||||
void initConfigTable(const GrContextOptions&, const GrGLContextInfo&, const GrGLInterface*,
|
||||
GrShaderCaps*);
|
||||
|
||||
void initShaderPrecisionTable(const GrGLContextInfo&, const GrGLInterface*, GrShaderCaps*);
|
||||
|
||||
GrGLStandard fStandard;
|
||||
|
||||
SkTArray<StencilFormat, true> fStencilFormats;
|
||||
|
@ -303,7 +303,7 @@ GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitSampler(GrSLType s
|
||||
const char* name,
|
||||
GrShaderFlags visibility) {
|
||||
this->updateSamplerCounts(visibility);
|
||||
GrSLPrecision precision = GrSLSamplerPrecision(config);
|
||||
GrSLPrecision precision = this->shaderCaps()->samplerPrecision(config, visibility);
|
||||
GrSwizzle swizzle = this->shaderCaps()->configTextureSwizzle(config);
|
||||
return this->uniformHandler()->addSampler(visibility, swizzle, samplerType, precision, name);
|
||||
}
|
||||
@ -311,7 +311,7 @@ GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitSampler(GrSLType s
|
||||
GrGLSLProgramBuilder::TexelBufferHandle GrGLSLProgramBuilder::emitTexelBuffer(
|
||||
GrPixelConfig config, const char* name, GrShaderFlags visibility) {
|
||||
this->updateSamplerCounts(visibility);
|
||||
GrSLPrecision precision = GrSLSamplerPrecision(config);
|
||||
GrSLPrecision precision = this->shaderCaps()->samplerPrecision(config, visibility);
|
||||
return this->uniformHandler()->addTexelBuffer(visibility, precision, name);
|
||||
}
|
||||
|
||||
|
@ -229,10 +229,21 @@ void GrMtlCaps::initShaderCaps() {
|
||||
shaderCaps->fTexelFetchSupport = false;
|
||||
shaderCaps->fVertexIDSupport = false;
|
||||
shaderCaps->fImageLoadStoreSupport = false;
|
||||
shaderCaps->fShaderPrecisionVaries = false; // ???
|
||||
|
||||
// Metal uses IEEE float and half floats so assuming those values here.
|
||||
shaderCaps->fFloatIs32Bits = true;
|
||||
shaderCaps->fHalfIs32Bits = false;
|
||||
// Metal uses IEEE float and half floats so using those values here.
|
||||
for (int s = 0; s < kGrShaderTypeCount; ++s) {
|
||||
auto& highp = shaderCaps->fFloatPrecisions[s][kHigh_GrSLPrecision];
|
||||
highp.fLogRangeLow = highp.fLogRangeHigh = 127;
|
||||
highp.fBits = 23;
|
||||
|
||||
auto& mediump = shaderCaps->fFloatPrecisions[s][kMedium_GrSLPrecision];
|
||||
mediump.fLogRangeLow = mediump.fLogRangeHigh = 15;
|
||||
mediump.fBits = 10;
|
||||
|
||||
shaderCaps->fFloatPrecisions[s][kLow_GrSLPrecision] = mediump;
|
||||
}
|
||||
shaderCaps->initSamplerPrecisionTable();
|
||||
|
||||
shaderCaps->fMaxVertexSamplers =
|
||||
shaderCaps->fMaxFragmentSamplers = 16;
|
||||
|
@ -259,8 +259,19 @@ void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties, uint
|
||||
shaderCaps->fVertexIDSupport = true;
|
||||
|
||||
// Assume the minimum precisions mandated by the SPIR-V spec.
|
||||
shaderCaps->fFloatIs32Bits = true;
|
||||
shaderCaps->fHalfIs32Bits = false;
|
||||
shaderCaps->fShaderPrecisionVaries = true;
|
||||
for (int s = 0; s < kGrShaderTypeCount; ++s) {
|
||||
auto& highp = shaderCaps->fFloatPrecisions[s][kHigh_GrSLPrecision];
|
||||
highp.fLogRangeLow = highp.fLogRangeHigh = 127;
|
||||
highp.fBits = 23;
|
||||
|
||||
auto& mediump = shaderCaps->fFloatPrecisions[s][kMedium_GrSLPrecision];
|
||||
mediump.fLogRangeLow = mediump.fLogRangeHigh = 14;
|
||||
mediump.fBits = 10;
|
||||
|
||||
shaderCaps->fFloatPrecisions[s][kLow_GrSLPrecision] = mediump;
|
||||
}
|
||||
shaderCaps->initSamplerPrecisionTable();
|
||||
|
||||
shaderCaps->fMaxVertexSamplers =
|
||||
shaderCaps->fMaxGeometrySamplers =
|
||||
|
@ -18,7 +18,7 @@ using std::abs;
|
||||
// macros to make sk_Caps.<cap name> work from C++ code
|
||||
#define sk_Caps (*args.fShaderCaps)
|
||||
|
||||
#define floatIs32Bits floatIs32Bits()
|
||||
#define floatPrecisionVaries floatPrecisionVaries()
|
||||
|
||||
// functions to make GLSL constructors work from C++ code
|
||||
inline SkPoint float2(float xy) { return SkPoint::Make(xy, xy); }
|
||||
|
@ -140,7 +140,7 @@ static void fill_caps(const SKSL_CAPS_CLASS& caps,
|
||||
CAP(mustEnableSpecificAdvBlendEqs);
|
||||
CAP(mustDeclareFragmentShaderOutput);
|
||||
CAP(canUseAnyFunctionInShader);
|
||||
CAP(floatIs32Bits);
|
||||
CAP(floatPrecisionVaries);
|
||||
CAP(integerSupport);
|
||||
#undef CAP
|
||||
}
|
||||
|
@ -135,8 +135,8 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool floatIs32Bits() const {
|
||||
return true;
|
||||
bool floatPrecisionVaries() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool integerSupport() const {
|
||||
|
@ -105,7 +105,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ApplyGamma, reporter, ctxInfo) {
|
||||
SkAutoTMalloc<uint32_t> read(kW * kH);
|
||||
|
||||
// We allow more error on GPUs with lower precision shader variables.
|
||||
float error = context->caps()->shaderCaps()->halfIs32Bits() ? 0.5f : 1.2f;
|
||||
float error = context->caps()->shaderCaps()->floatPrecisionVaries() ? 1.2f : 0.5f;
|
||||
|
||||
for (auto toSRGB : { false, true }) {
|
||||
sk_sp<SkSurface> dst(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii));
|
||||
|
@ -184,14 +184,14 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SRGBReadWritePixels, reporter, ctxInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
float error = context->caps()->shaderCaps()->halfIs32Bits() ? 0.5f : 1.2f;
|
||||
float error = context->caps()->shaderCaps()->floatPrecisionVaries() ? 1.2f : 0.5f;
|
||||
|
||||
// Write srgba data and read as srgba and then as rgba
|
||||
if (sContext->writePixels(iiSRGBA, origData, 0, 0, 0)) {
|
||||
// For the all-srgba case, we allow a small error only for devices that have
|
||||
// precision variation because the srgba data gets converted to linear and back in
|
||||
// the shader.
|
||||
float smallError = context->caps()->shaderCaps()->halfIs32Bits() ? 0.0f : 1.f;
|
||||
float smallError = context->caps()->shaderCaps()->floatPrecisionVaries() ? 1.f : 0.0f;
|
||||
read_and_check_pixels(reporter, sContext.get(), origData, iiSRGBA,
|
||||
check_srgb_to_linear_to_srgb_conversion, smallError,
|
||||
"write/read srgba to srgba texture");
|
||||
|
Loading…
Reference in New Issue
Block a user