in src/gpu/ganesh/gl/GrGLCaps.cpp [3936:4838]
void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
const GrContextOptions& contextOptions,
const GrGLInterface* glInterface,
GrShaderCaps* shaderCaps,
FormatWorkarounds* formatWorkarounds) {
GrGLDriverVersion driverVersion =
ctxInfo.angleBackend() == GrGLANGLEBackend::kUnknown ? ctxInfo.driverVersion()
: ctxInfo.angleDriverVersion();
// A driver bug on the nexus 6 causes incorrect dst copies when invalidate is called beforehand.
// Thus we are disabling this extension for now on Adreno4xx devices.
if (ctxInfo.renderer() == GrGLRenderer::kAdreno430 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno4xx_other ||
fDriverBugWorkarounds.disable_discard_framebuffer) {
fInvalidateFBType = kNone_InvalidateFBType;
}
if (ctxInfo.renderer() == GrGLRenderer::kIntelCherryView) {
// When running DMSAA_dst_read_with_existing_barrier with DMSAA disabled on linux Intel
// HD405, the test fails when using texture barriers. Oddly the gpu doing the draw which
// uses the barrier correctly. It is the next draw, which does not use or need a barrier,
// that is blending with a dst as if the barrier draw didn't happen. Since this GPU is not
// that important to us and this driver bug could probably manifest itself in the wild, we
// are just disabling texture barrier support for the gpu.
fTextureBarrierSupport = false;
}
// glClearTexImage seems to have a bug in NVIDIA drivers that was fixed sometime between
// 340.96 and 367.57.
if (GR_IS_GR_GL(ctxInfo.standard()) && ctxInfo.driver() == GrGLDriver::kNVIDIA &&
ctxInfo.driverVersion() < GR_GL_DRIVER_VER(367, 57, 0)) {
fClearTextureSupport = false;
}
// glBlitFramebuffer seems to produce incorrect results on QC, Mali400, and Tegra3 but
// glCopyTexSubImage2D works (even though there is no extension that specifically allows it).
if (ctxInfo.vendor() == GrGLVendor::kQualcomm ||
ctxInfo.renderer() == GrGLRenderer::kMali4xx ||
ctxInfo.renderer() == GrGLRenderer::kTegra_PreK1) {
fAllowBGRA8CopyTexSubImage = true;
}
// glCopyTexSubImage2D works for sRGB with GLES 3.0 and on some GPUs with GLES 2.0
if (ctxInfo.version() >= GR_GL_VER(3, 0) ||
ctxInfo.renderer() == GrGLRenderer::kMali4xx ||
ctxInfo.renderer() == GrGLRenderer::kTegra_PreK1) {
fAllowSRGBCopyTexSubImage = true;
}
// http://anglebug.com/6030
if (fMSFBOType == kES_EXT_MsToTexture_MSFBOType &&
ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D11) {
// As GL_EXT_multisampled_render_to_texture supporting issue,
// fall back to default dmsaa path
if ((ctxInfo.vendor() == GrGLVendor::kIntel ||
ctxInfo.angleVendor() == GrGLVendor::kIntel) &&
ctxInfo.renderer() >= GrGLRenderer::kIntelIceLake) {
fMSFBOType = kStandard_MSFBOType;
fMSAAResolvesAutomatically = false;
}
else {
fDisallowDynamicMSAA = true;
}
}
// http://skbug.com/12081
if (GR_IS_GR_WEBGL(ctxInfo.standard())) {
fDisallowDynamicMSAA = true;
}
// Below we are aggressive about turning off all mapping/transfer functionality together. This
// could be finer grained if code paths and tests were adjusted to check more specific caps.
// For example it might be possible to support buffer to buffer transfers even if buffer mapping
// or buffer to surface transfers don't work.
#if defined(__has_feature)
#if defined(SK_BUILD_FOR_MAC) && __has_feature(thread_sanitizer)
// See skbug.com/7058
fMapBufferType = kNone_MapBufferType;
fMapBufferFlags = kNone_MapFlags;
fTransferFromBufferToTextureSupport = false;
fTransferFromSurfaceToBufferSupport = false;
fTransferFromBufferToBufferSupport = false;
fTransferBufferType = TransferBufferType::kNone;
#endif
#endif
// We found that the Galaxy J5 with an Adreno 306 running 6.0.1 has a bug where
// GL_INVALID_OPERATION thrown by glDrawArrays when using a buffer that was mapped. The same bug
// did not reproduce on a Nexus7 2013 with a 320 running Android M with driver 127.0. It's
// unclear whether this really affects a wide range of devices.
if (ctxInfo.renderer() == GrGLRenderer::kAdreno3xx &&
ctxInfo.driverVersion() > GR_GL_DRIVER_VER(127, 0, 0)) {
fMapBufferType = kNone_MapBufferType;
fMapBufferFlags = kNone_MapFlags;
fTransferFromBufferToTextureSupport = false;
fTransferFromSurfaceToBufferSupport = false;
fTransferFromBufferToBufferSupport = false;
fTransferBufferType = TransferBufferType::kNone;
}
// The TransferPixelsToTexture test fails on ANGLE D3D9 and D3D11 if this is enabled.
// https://anglebug.com/5542
if (angle_backend_is_d3d(ctxInfo.angleBackend())) {
fTransferPixelsToRowBytesSupport = false;
}
// Using MIPs on this GPU seems to be a source of trouble.
if (ctxInfo.renderer() == GrGLRenderer::kPowerVR54x) {
fMipmapSupport = false;
}
#ifdef SK_BUILD_FOR_ANDROID
if (ctxInfo.renderer() == GrGLRenderer::kPowerVR54x) {
// Flutter found glTexSubImage2D for GL_RED is much slower than GL_ALPHA on the
// "MC18 PERSONAL SHOPPER"
formatWorkarounds->fDisallowR8ForPowerVRSGX54x = true;
}
#endif
// Reported on skia-discuss as occurring with these GL strings:
// GL_VERSION: 3.1.0 - Build 9.17.10.4459
// GL_VENDOR: Intel
// GL_RENDERER: Intel(R) HD Graphics 2000
// https://groups.google.com/g/skia-discuss/c/dYV1blEAda0/m/-zuZLXQKAwAJ?utm_medium=email&utm_source=footer
// See also http://skbug.com/9286
if (ctxInfo.renderer() == GrGLRenderer::kIntelSandyBridge &&
ctxInfo.driver() == GrGLDriver::kIntel) {
fMapBufferType = kNone_MapBufferType;
fMapBufferFlags = kNone_MapFlags;
// On skia-discuss it was reported that after turning off mapping there was this
// shader compilation error.
// ERROR: 0:18: 'assign' : cannot convert from '3-component vector of float' to 'varying 2-component vector of float'
// for this line:
// vTransformedCoords_5_S0 = mat3x2(umatrix_S1_c0_c1) * vec3(_tmp_2_inPosition, 1.0);
fShaderCaps->fNonsquareMatrixSupport = false;
}
if (ctxInfo.isOverCommandBuffer() && ctxInfo.version() >= GR_GL_VER(3,0)) {
formatWorkarounds->fDisallowTextureUnorm16 = true; // http://crbug.com/1224108
formatWorkarounds->fDisallowETC2Compression = true; // http://crbug.com/1224111
fTransferFromSurfaceToBufferSupport = false; // http://crbug.com/1224138
// http://crbug.com/1224117
fMapBufferFlags = kNone_MapFlags;
fMapBufferType = kNone_MapBufferType;
}
// https://b.corp.google.com/issues/143074513
// https://skbug.com/11152
if (ctxInfo.renderer() == GrGLRenderer::kAdreno615 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno620) {
fMSFBOType = kNone_MSFBOType;
fMSAAResolvesAutomatically = false;
}
#ifndef SK_BUILD_FOR_IOS
if (ctxInfo.renderer() == GrGLRenderer::kPowerVR54x ||
ctxInfo.renderer() == GrGLRenderer::kPowerVRRogue ||
(ctxInfo.renderer() == GrGLRenderer::kAdreno3xx && !ctxInfo.isOverCommandBuffer())) {
fPerformColorClearsAsDraws = true;
}
#endif
// A lot of GPUs have trouble with full screen clears (skbug.com/7195)
if (ctxInfo.renderer() == GrGLRenderer::kAMDRadeonHD7xxx ||
ctxInfo.renderer() == GrGLRenderer::kAMDRadeonR9M4xx) {
fPerformColorClearsAsDraws = true;
}
#ifdef SK_BUILD_FOR_MAC
// crbug.com/768134 - On MacBook Pros, the Intel Iris Pro doesn't always perform
// full screen clears
// crbug.com/773107 - On MacBook Pros, a wide range of Intel GPUs don't always
// perform full screen clears.
// Update on 4/4/2018 - This appears to be fixed on driver 10.30.12 on a macOS 10.13.2 on a
// Retina MBP Early 2015 with Iris 6100. It is possibly fixed on earlier drivers as well.
// crbug.com/1039912 - Crash rate in glClear spiked after OS update, affecting mostly
// Broadwell on 10.13+
if (ctxInfo.vendor() == GrGLVendor::kIntel &&
(ctxInfo.driverVersion() < GR_GL_DRIVER_VER(10, 30, 12) ||
ctxInfo.renderer() == GrGLRenderer::kIntelBroadwell)) {
fPerformColorClearsAsDraws = true;
}
// crbug.com/969609 - NVIDIA on Mac sometimes segfaults during glClear in chrome. It seems
// mostly concentrated in 10.13/14, GT 650Ms, driver 12+. But there are instances of older
// drivers and GTX 775s, so we'll start with a broader workaround.
if (ctxInfo.vendor() == GrGLVendor::kNVIDIA) {
fPerformColorClearsAsDraws = true;
}
#endif
// See crbug.com/755871. This could probably be narrowed to just partial clears as the driver
// bugs seems to involve clearing too much and not skipping the clear.
// See crbug.com/768134. This is also needed for full clears and was seen on an nVidia K620
// but only for D3D11 ANGLE.
if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D11) {
fPerformColorClearsAsDraws = true;
}
if (ctxInfo.renderer() == GrGLRenderer::kAdreno430 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno4xx_other) {
// This is known to be fixed sometime between driver 145.0 and 219.0
if (ctxInfo.driverVersion() <= GR_GL_DRIVER_VER(219, 0, 0)) {
fPerformStencilClearsAsDraws = true;
}
// This is known to be fixed sometime between driver 129.0 and 145.0 on Nexus 6P.
// On driver 129 on Android M it fails the unit tests called WritePixelsPendingIO without
// the workaround. It passes on Android N with driver 145 without the workaround.
// skbug.com/11834
if (ctxInfo.driverVersion() < GR_GL_DRIVER_VER(145, 0, 0)) {
fDisallowTexSubImageForUnormConfigTexturesEverBoundToFBO = true;
}
}
if (fDriverBugWorkarounds.gl_clear_broken) {
fPerformColorClearsAsDraws = true;
fPerformStencilClearsAsDraws = true;
}
if (ctxInfo.vendor() == GrGLVendor::kQualcomm) {
// It appears that all the Adreno GPUs have less than optimal performance when
// drawing w/ large index buffers.
fAvoidLargeIndexBufferDraws = true;
}
if (ctxInfo.renderer() == GrGLRenderer::kMali4xx ||
(ctxInfo.renderer() == GrGLRenderer::kWebGL &&
ctxInfo.webglRenderer() == GrGLRenderer::kMali4xx)) {
// Perspective SDF text runs significantly slower on Mali-4xx hardware
fDisablePerspectiveSDFText = true;
}
// This was reproduced on the following configurations:
// - A Galaxy J5 (Adreno 306) running Android 6 with driver 140.0
// - A Nexus 7 2013 (Adreno 320) running Android 5 with driver 104.0
// - A Nexus 7 2013 (Adreno 320) running Android 6 with driver 127.0
// - A Nexus 5 (Adreno 330) running Android 6 with driver 127.0
// and not produced on:
// - A Nexus 7 2013 (Adreno 320) running Android 4 with driver 53.0
// The particular lines that get dropped from test images varies across different devices.
if (ctxInfo.renderer() == GrGLRenderer::kAdreno3xx &&
ctxInfo.driverVersion() > GR_GL_DRIVER_VER(53, 0, 0)) {
fRequiresCullFaceEnableDisableWhenDrawingLinesAfterNonLines = true;
}
// TODO: Don't apply this on iOS?
if (ctxInfo.renderer() == GrGLRenderer::kPowerVRRogue &&
driverVersion < GR_GL_DRIVER_VER(23, 2, 0)) {
// Our Chromebook with GrGLRenderer::kPowerVRRogue crashes on large instanced draws. The
// current minimum number of instances observed to crash is somewhere between 2^14 and 2^15.
// Keep the number of instances below 1000, just to be safe.
fMaxInstancesPerDrawWithoutCrashing = 999;
} else if (fDriverBugWorkarounds.disallow_large_instanced_draw) {
fMaxInstancesPerDrawWithoutCrashing = 0x4000000;
}
#ifndef SK_BUILD_FOR_IOS
if (ctxInfo.renderer() == GrGLRenderer::kPowerVRRogue) {
// We saw this bug on a TecnoSpark 3 Pro with a PowerVR GE8300.
// GL_VERSION: "OpenGL ES 3.2 build 1.10@51309121"
// Possibly this could be more limited by driver version or HW generation.
// When using samplers, we are seeing a bug where the gpu is sometimes not sampling the
// correct mip level data. A workaround to this issue is that when binding a texture we also
// set some texture state, and it seems like any inividual state works (e.g. min/mag filter,
// base level, max level, etc.). Currently we just set the min filter level every time we
// bind a texture as the workaround.
fMustSetAnyTexParameterToEnableMipmapping = true;
// ColorTypeBackendAllocationTest failed for kAlpha_8 and kGray_8 when using
// GL_UNPACK_ROW_LENGTH. Perhaps this could be a more limited workaround by applying
// only to single channel 8 bit unorm formats but we only have a monolithic query for this
// support at present.
fWritePixelsRowBytesSupport = false;
// TransferPixelsToTextureTest fails for all color types on
// TecnoSpark 3 Pro with a PowerVR GE8300, GL_VERSION: "OpenGL ES 3.2 build 1.10@51309121"
// if GL_UNPACK_ROW_LENGTH is used.
fTransferPixelsToRowBytesSupport = false;
}
#endif
// Texture uploads sometimes seem to be ignored to textures bound to FBOS on Tegra3.
if (ctxInfo.renderer() == GrGLRenderer::kTegra_PreK1) {
fDisallowTexSubImageForUnormConfigTexturesEverBoundToFBO = true;
fUseDrawInsteadOfAllRenderTargetWrites = true;
}
#ifdef SK_BUILD_FOR_MAC
static constexpr bool isMAC = true;
#else
static constexpr bool isMAC = false;
#endif
#ifdef SK_BUILD_FOR_ANDROID
// Older versions of Android have problems with setting GL_TEXTURE_BASE_LEVEL or
// GL_TEXTURE_MAX_LEVEL on GL_TEXTURE_EXTERTNAL_OES textures. We just leave them as is and hope
// the client never changes them either.
fDontSetBaseOrMaxLevelForExternalTextures = true;
// PowerVR can crash setting the levels on Android up to Q for any texture?
// https://crbug.com/1123874
if (ctxInfo.vendor() == GrGLVendor::kImagination) {
fMipmapLevelControlSupport = false;
}
#endif
// We support manual mip-map generation (via iterative downsampling draw calls). This fixes
// bugs on some cards/drivers that produce incorrect mip-maps for sRGB textures when using
// glGenerateMipmap. Our implementation requires mip-level sampling control. Additionally,
// it can be much slower (especially on mobile GPUs), so we opt-in only when necessary:
if (fMipmapLevelControlSupport &&
!ctxInfo.isOverCommandBuffer() && // http://crbug.com/1224110
(contextOptions.fDoManualMipmapping ||
ctxInfo.vendor() == GrGLVendor::kIntel ||
(ctxInfo.driver() == GrGLDriver::kNVIDIA && isMAC) ||
ctxInfo.vendor() == GrGLVendor::kATI)) {
fDoManualMipmapping = true;
}
// See http://crbug.com/710443
#ifdef SK_BUILD_FOR_MAC
if (ctxInfo.renderer() == GrGLRenderer::kIntelBroadwell) {
fClearToBoundaryValuesIsBroken = true;
}
#endif
if (ctxInfo.vendor() == GrGLVendor::kQualcomm) {
fDrawArraysBaseVertexIsBroken = true;
}
// b/40043081, b/40045491: indirect draws in ANGLE + D3D are very slow
if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D9 ||
ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D11) {
fBaseVertexBaseInstanceSupport = false;
fNativeDrawIndirectSupport = false;
fMultiDrawType = MultiDrawType::kNone;
}
// https://b.corp.google.com/issues/188410972
if (ctxInfo.isRunningOverVirgl()) {
fDrawInstancedSupport = false;
}
// http://anglebug.com/4538
if (fBaseVertexBaseInstanceSupport && !fDrawInstancedSupport) {
fBaseVertexBaseInstanceSupport = false;
fNativeDrawIndirectSupport = false;
fMultiDrawType = MultiDrawType::kNone;
}
// Currently the extension is advertised but fb fetch is broken on 500 series Adrenos like the
// Galaxy S7.
// TODO: Once this is fixed we can update the check here to look at a driver version number too.
if (ctxInfo.renderer() == GrGLRenderer::kAdreno530 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno5xx_other) {
shaderCaps->fFBFetchSupport = false;
}
if (ctxInfo.renderer() == GrGLRenderer::kTegra_PreK1) {
// 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.
shaderCaps->fCanUseMinAndAbsTogether = false;
// Tegra3 fract() seems to trigger undefined behavior for negative values, so we
// must avoid this condition.
shaderCaps->fCanUseFractForNegativeValues = false;
}
// On Intel GPU there is an issue where it reads the second argument to atan "- %s.x" as an int
// thus must us -1.0 * %s.x to work correctly
if (ctxInfo.vendor() == GrGLVendor::kIntel) {
shaderCaps->fMustForceNegatedAtanParamToFloat = true;
}
#if defined(SK_BUILD_FOR_MAC)
if (ctxInfo.vendor() == GrGLVendor::kATI) {
// The Radeon GLSL compiler on Mac gets confused by ldexp(..., -x).
// Convert to ldexp(..., x * -1).
// http://skbug.com/12076
shaderCaps->fMustForceNegatedLdexpParamToMultiply = true;
}
#endif
// On some Intel GPUs there is an issue where the driver outputs bogus values in the shader
// when floor and abs are called on the same line. Thus we must execute an Op between them to
// make sure the compiler doesn't re-inline them even if we break the calls apart.
if (ctxInfo.vendor() == GrGLVendor::kIntel) {
shaderCaps->fMustDoOpBetweenFloorAndAbs = true;
}
// On Adreno devices with framebuffer fetch support, there is a bug where they always return
// the original dst color when reading the outColor even after being written to. By using a
// local outColor we can work around this bug.
if (shaderCaps->fFBFetchSupport && ctxInfo.vendor() == GrGLVendor::kQualcomm) {
shaderCaps->fRequiresLocalOutputColorForFBFetch = true;
}
// Newer Mali GPUs do incorrect static analysis in specific situations: If there is uniform
// color, and that uniform contains an opaque color, and the output of the shader is only based
// on that uniform plus soemthing un-trackable (like a texture read), the compiler will deduce
// that the shader always outputs opaque values. In that case, it appears to remove the shader
// based blending code it normally injects, turning SrcOver into Src. To fix this, we always
// insert an extra bit of math on the uniform that confuses the compiler just enough...
if (ctxInfo.renderer() == GrGLRenderer::kMaliT) {
shaderCaps->fMustObfuscateUniformColor = true;
}
#if defined(SK_BUILD_FOR_ANDROID)
// On the following GPUs, the Perlin noise code needs to aggressively snap to multiples
// of 1/255 to avoid artifacts in the double table lookup:
// Tegra3, PowerVRGE8320 (Wembley), MaliG76, and Adreno308
// Given the range of vendors we're just blanket enabling it on Android for OpenGL.
fShaderCaps->fPerlinNoiseRoundingFix = true;
#endif
// On Mali 400 there is a bug using dFd* in the x direction. So we avoid using it when possible.
if (ctxInfo.renderer() == GrGLRenderer::kMali4xx) {
fShaderCaps->fAvoidDfDxForGradientsWhenPossible = true;
}
#ifdef SK_BUILD_FOR_WIN
// Check for ANGLE on Windows, so we can workaround a bug in D3D itself (anglebug.com/2098).
//
// Basically, if a shader has a construct like:
//
// float x = someCondition ? someValue : 0;
// float2 result = (0 == x) ? float2(x, x)
// : float2(2 * x / x, 0);
//
// ... the compiler will produce an error 'NaN and infinity literals not allowed', even though
// we've explicitly guarded the division with a check against zero. This manifests in much
// more complex ways in some of our shaders, so we use this caps bit to add an epsilon value
// to the denominator of divisions, even when we've added checks that the denominator isn't 0.
if (angle_backend_is_d3d(ctxInfo.angleBackend()) || ctxInfo.isOverCommandBuffer()) {
shaderCaps->fMustGuardDivisionEvenAfterExplicitZeroCheck = true;
}
#endif
// The Adreno 5xx and 6xx produce incorrect results when comparing a pair of matrices.
if (ctxInfo.renderer() == GrGLRenderer::kAdreno530 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno5xx_other ||
ctxInfo.renderer() == GrGLRenderer::kAdreno615 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno620 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno630 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno640 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno6xx_other) {
shaderCaps->fRewriteMatrixComparisons = true;
}
// We've seen Adreno 3xx devices produce incorrect (flipped) values for gl_FragCoord, in some
// (rare) situations. It's sporadic, and mostly on older drivers. Additionally, old Adreno
// compilers (see crbug.com/skia/4078) crash when accessing .zw of gl_FragCoord, so just bypass
// using gl_FragCoord at all to get around it.
if (ctxInfo.renderer() == GrGLRenderer::kAdreno3xx) {
shaderCaps->fCanUseFragCoord = false;
}
// gl_FragCoord has an incorrect subpixel offset on legacy Tegra hardware.
if (ctxInfo.renderer() == GrGLRenderer::kTegra_PreK1) {
shaderCaps->fCanUseFragCoord = false;
}
if (fDriverBugWorkarounds.add_and_true_to_loop_condition) {
shaderCaps->fAddAndTrueToLoopCondition = true;
}
if (fDriverBugWorkarounds.unfold_short_circuit_as_ternary_operation) {
shaderCaps->fUnfoldShortCircuitAsTernary = true;
}
if (fDriverBugWorkarounds.emulate_abs_int_function) {
shaderCaps->fEmulateAbsIntFunction = true;
}
if (fDriverBugWorkarounds.rewrite_do_while_loops) {
shaderCaps->fRewriteDoWhileLoops = true;
}
if (fDriverBugWorkarounds.remove_pow_with_constant_exponent) {
shaderCaps->fRemovePowWithConstantExponent = true;
}
if (fDriverBugWorkarounds.disable_dual_source_blending_support) {
shaderCaps->fDualSourceBlendingSupport = false;
}
if (ctxInfo.renderer() == GrGLRenderer::kAdreno3xx ||
ctxInfo.renderer() == GrGLRenderer::kAdreno4xx_other) {
shaderCaps->fMustWriteToFragColor = true;
}
// Disabling advanced blend on various platforms with major known issues. We also block Chrome
// command buffer for now until its own denylists can be updated.
if (ctxInfo.renderer() == GrGLRenderer::kAdreno430 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno4xx_other ||
ctxInfo.renderer() == GrGLRenderer::kAdreno530 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno5xx_other ||
ctxInfo.driver() == GrGLDriver::kIntel ||
ctxInfo.angleVendor() == GrGLVendor::kIntel ||
ctxInfo.isOverCommandBuffer() ||
ctxInfo.vendor() == GrGLVendor::kARM /* http://skbug.com/11906 */) {
fBlendEquationSupport = kBasic_BlendEquationSupport;
shaderCaps->fAdvBlendEqInteraction = GrShaderCaps::kNotSupported_AdvBlendEqInteraction;
}
// Non-coherent advanced blend has an issue on NVIDIA pre 337.00.
if (((ctxInfo.driver() == GrGLDriver::kNVIDIA &&
ctxInfo.driverVersion() < GR_GL_DRIVER_VER(337, 00, 0)) ||
(ctxInfo.angleBackend() == GrGLANGLEBackend::kOpenGL &&
ctxInfo.angleDriver() == GrGLDriver::kNVIDIA &&
ctxInfo.angleDriverVersion() < GR_GL_DRIVER_VER(337, 00, 0))) &&
kAdvanced_BlendEquationSupport == fBlendEquationSupport) {
fBlendEquationSupport = kBasic_BlendEquationSupport;
shaderCaps->fAdvBlendEqInteraction = GrShaderCaps::kNotSupported_AdvBlendEqInteraction;
}
if (fDriverBugWorkarounds.disable_blend_equation_advanced) {
fBlendEquationSupport = kBasic_BlendEquationSupport;
shaderCaps->fAdvBlendEqInteraction = GrShaderCaps::kNotSupported_AdvBlendEqInteraction;
}
if (this->advancedBlendEquationSupport()) {
if ((ctxInfo.driver() == GrGLDriver::kNVIDIA &&
ctxInfo.driverVersion() < GR_GL_DRIVER_VER(355, 00, 0)) ||
(ctxInfo.angleBackend() == GrGLANGLEBackend::kOpenGL &&
ctxInfo.angleDriver() == GrGLDriver::kNVIDIA &&
ctxInfo.angleDriverVersion() < GR_GL_DRIVER_VER(355, 00, 0))) {
// Disable color-dodge and color-burn on pre-355.00 NVIDIA.
fAdvBlendEqDisableFlags |= (1 << static_cast<int>(skgpu::BlendEquation::kColorDodge)) |
(1 << static_cast<int>(skgpu::BlendEquation::kColorBurn));
}
if (ctxInfo.vendor() == GrGLVendor::kARM) {
// Disable color-burn on ARM until the fix is released.
fAdvBlendEqDisableFlags |= (1 << static_cast<int>(skgpu::BlendEquation::kColorBurn));
}
}
// On Adreno 5xx devices, there is a bug where we first draw using dual source blending. Thus
// the dst blend func references the dst. Then the next draw we disable blending. However, on
// the second draw the driver has a bug where it tries to access the second color output again.
// This is fixed by reseting the blend function to anything that does not reference src2 when we
// disable blending.
if (ctxInfo.renderer() == GrGLRenderer::kAdreno530 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno5xx_other ||
ctxInfo.renderer() == GrGLRenderer::kAdreno620 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno640) {
fMustResetBlendFuncBetweenDualSourceAndDisable = true;
}
// Many ES3 drivers only advertise the ES2 image_external extension, but support the _essl3
// extension, and require that it be enabled to work with ESSL3. Other devices require the ES2
// extension to be enabled, even when using ESSL3. Enabling both extensions fixes both cases.
// skbug.com/7713
if (ctxInfo.hasExtension("GL_OES_EGL_image_external") &&
ctxInfo.glslGeneration() >= SkSL::GLSLGeneration::k330 &&
!shaderCaps->fExternalTextureSupport) { // i.e. Missing the _essl3 extension
shaderCaps->fExternalTextureSupport = true;
shaderCaps->fExternalTextureExtensionString = "GL_OES_EGL_image_external";
shaderCaps->fSecondExternalTextureExtensionString = "GL_OES_EGL_image_external_essl3";
}
#ifdef SK_BUILD_FOR_IOS
// iOS drivers appear to implement TexSubImage by creating a staging buffer, and copying
// UNPACK_ROW_LENGTH * height bytes. That's unsafe in several scenarios, and the simplest fix
// is to just disable the feature.
// https://github.com/flutter/flutter/issues/16718
// https://bugreport.apple.com/web/?problemID=39948888
fWritePixelsRowBytesSupport = false;
// This affects all iOS devices for transfering from a PBO as well (presumably the issue is in
// the GL->Metal layer).
fTransferPixelsToRowBytesSupport = false;
#endif
if (ctxInfo.vendor() == GrGLVendor::kIntel || // IntelIris640 drops draws completely.
ctxInfo.webglVendor() == GrGLVendor::kIntel || // Disable if the webgl vendor is Intel
ctxInfo.renderer() == GrGLRenderer::kMaliT || // Some curves appear flat on GalaxyS6.
ctxInfo.renderer() == GrGLRenderer::kAdreno3xx ||
ctxInfo.renderer() == GrGLRenderer::kAdreno430 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno4xx_other || // We get garbage on Adreno405.
ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D9) { // D3D9 conic strokes fail.
fDisableTessellationPathRenderer = true;
}
// We found that on Wembley devices (PowerVR GE8320) that using tessellation path renderer would
// cause lots of rendering errors where it seemed like vertices were in the wrong place. This
// led to lots of GMs drawing nothing (e.g. dashing4) or lots of garbage. The Wembley devices
// were running Android 12 with a driver version of 1.13. We previously had TecnoSpark devices
// with the same GPU running on Android P (driver 1.10) which did not have this issue. We don't
// know when the bug appeared in the driver so for now we disable tessellation path renderer for
// all matching gpus regardless of driver version.
//
// 2022-10-28 Update: Testing via Flutter found this is not a problem on driver version 1.15.
// See https://github.com/flutter/flutter/issues/113596
// GL_VERSION : OpenGL ES 3.1 build 1.15@6133109
// GL_RENDERER: PowerVR Rogue AXE-1-16M
// GL_VENDOR : Imagination Technologies
if (ctxInfo.renderer() == GrGLRenderer::kPowerVRRogue &&
driverVersion < GR_GL_DRIVER_VER(1, 15, 0)) {
fDisableTessellationPathRenderer = true;
}
// The Wembley device draws the mesh_update GM incorrectly when using transfer buffers. Buffer
// to buffer transfers affect draws earlier in the GL command sequence.
// Android API: 31
// GL_VERSION : OpenGL ES 3.2 build 1.13@5720833
// GL_RENDERER: PowerVR Rogue GE8300
// GL_VENDOR : Imagination Technologies
if (ctxInfo.renderer() == GrGLRenderer::kPowerVRRogue) {
fTransferFromBufferToBufferSupport = false;
}
// The Wembley device fails shader compilations with no error message when there is a const
// parameter. Given that we've already passed through SkSL compilation and enforced that the
// parameter is never written, it is harmless to strip the const off when writing GLSL.
// Android API: 31
// GL_VERSION : OpenGL ES 3.2 build 1.13@5720833
// GL_RENDERER: PowerVR Rogue GE8300
// GL_VENDOR : Imagination Technologies
if (ctxInfo.renderer() == GrGLRenderer::kPowerVRRogue) {
fShaderCaps->fRemoveConstFromFunctionParameters = true;
}
#ifdef SK_BUILD_FOR_WIN
// glDrawElementsIndirect fails GrMeshTest on every Win10 Intel bot.
if (ctxInfo.driver() == GrGLDriver::kIntel ||
(ctxInfo.angleVendor() == GrGLVendor::kIntel &&
ctxInfo.angleBackend() == GrGLANGLEBackend::kOpenGL)) {
fNativeDrawIndexedIndirectIsBroken = true;
fUseClientSideIndirectBuffers = true;
}
#endif
// PowerVRGX6250 drops every pixel if we modify the sample mask while color writes are disabled.
if (ctxInfo.renderer() == GrGLRenderer::kPowerVRRogue) {
fNeverDisableColorWrites = true;
shaderCaps->fMustWriteToFragColor = true;
}
// It appears that Qualcomm drivers don't actually support
// GL_NV_shader_noperspective_interpolation in ES 3.00 or 3.10 shaders, only 3.20.
// https://crbug.com/986581
if (ctxInfo.vendor() == GrGLVendor::kQualcomm &&
SkSL::GLSLGeneration::k320es != ctxInfo.glslGeneration()) {
shaderCaps->fNoPerspectiveInterpolationSupport = false;
}
// We disable srgb write control for Adreno4xx devices.
// see: https://bug.skia.org/5329
if (ctxInfo.renderer() == GrGLRenderer::kAdreno430 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno4xx_other) {
fSRGBWriteControl = false;
}
// MacPro devices with AMD cards fail to create MSAA sRGB render buffers.
#if defined(SK_BUILD_FOR_MAC)
if (ctxInfo.vendor() == GrGLVendor::kATI) {
formatWorkarounds->fDisableSRGBRenderWithMSAAForMacAMD = true;
}
#endif
// Command buffer fails glTexSubImage2D with type == GL_HALF_FLOAT_OES if a GL_RGBA16F texture
// is created with glTexStorage2D. See crbug.com/1008003.
formatWorkarounds->fDisableRGBA16FTexStorageForCrBug1008003 =
ctxInfo.isOverCommandBuffer() && ctxInfo.version() < GR_GL_VER(3, 0);
#if defined(SK_BUILD_FOR_WIN)
// On Intel Windows ES contexts it seems that using texture storage with BGRA causes
// problems with cross-context SkImages.
formatWorkarounds->fDisableBGRATextureStorageForIntelWindowsES =
ctxInfo.driver() == GrGLDriver::kIntel && GR_IS_GR_GL_ES(ctxInfo.standard());
#endif
// On the Intel Iris 6100, interacting with LUM16F seems to confuse the driver. After
// writing to/reading from a LUM16F texture reads from/writes to other formats behave
// erratically.
// All Adrenos claim to support LUM16F but don't appear to actually do so.
// The failing devices/gpus were: Nexus5/Adreno330, Nexus5x/Adreno418, Pixel/Adreno530,
// Pixel2XL/Adreno540 and Pixel3/Adreno630
formatWorkarounds->fDisableLuminance16F =
(ctxInfo.renderer() == GrGLRenderer::kIntelBroadwell ||
ctxInfo.vendor() == GrGLVendor::kQualcomm) &&
ctxInfo.angleBackend() == GrGLANGLEBackend::kUnknown;
#ifdef SK_BUILD_FOR_MAC
// On a MacBookPro 11.5 running MacOS 10.13 with a Radeon M370X the TransferPixelsFrom test
// fails when transferring out from a GL_RG8 texture using GL_RG/GL_UNSIGNED_BYTE.
// The same error also occurs in MacOS 10.15 with a Radeon Pro 5300M.
formatWorkarounds->fDisallowDirectRG8ReadPixels =
ctxInfo.renderer() == GrGLRenderer::kAMDRadeonR9M3xx ||
ctxInfo.renderer() == GrGLRenderer::kAMDRadeonPro5xxx ||
ctxInfo.renderer() == GrGLRenderer::kAMDRadeonProVegaxx;
#endif
#ifdef SK_BUILD_FOR_ANDROID
// crbug.com/945506. Telemetry reported a memory usage regression for Android Go Chrome/WebView
// when using glTexStorage2D. This appears to affect OOP-R (so not just over command buffer).
// Update 10/2023, it looks like this may just effect chrome Android GO devices which are
// running on Mali-T720. It does not seem to impact Qualcomm devices. We have no tests to verify
// if newer ARM devices are impacted, so for now we keep this disabled on all ARM by default.
//
// We allow the client to pass in a GrContextOption flag to say they prefer having tex storage
// support regadless of memory usage impacts. This is important for supporting Protected
// textures as they require tex storage support.
if (ctxInfo.vendor() == GrGLVendor::kARM &&
!contextOptions.fAlwaysUseTexStorageWhenAvailable &&
!fSupportsProtectedContent) {
formatWorkarounds->fDisableTexStorage = true;
}
#endif
// https://github.com/flutter/flutter/issues/38700
if (ctxInfo.driver() == GrGLDriver::kAndroidEmulator) {
shaderCaps->fNoDefaultPrecisionForExternalSamplers = true;
}
// http://skbug.com/9491: Nexus5 produces rendering artifacts when we use QCOM_tiled_rendering.
if (ctxInfo.renderer() == GrGLRenderer::kAdreno3xx) {
fTiledRenderingSupport = false;
}
// https://github.com/flutter/flutter/issues/47164
// https://github.com/flutter/flutter/issues/47804
if (fTiledRenderingSupport && (!glInterface->fFunctions.fStartTiling ||
!glInterface->fFunctions.fEndTiling)) {
// Some devices expose the QCOM tiled memory extension string but don't actually provide the
// start and end tiling functions (see above flutter bugs). To work around this, the funcs
// are marked optional in the interface generator, but we turn off the tiled rendering cap
// if they aren't provided. This disabling is in driver workarounds so that SKQP will still
// fail on devices that advertise the extension w/o the functions.
fTiledRenderingSupport = false;
}
if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D9) {
formatWorkarounds->fDisallowBGRA8ReadPixels = true;
}
// We disable MSAA for older Intel GPUs. Before Gen9, performance was very bad. Even with Gen9,
// we've seen driver crashes in the wild.
// (crbug.com/527565, crbug.com/983926)
if (ctxInfo.vendor() == GrGLVendor::kIntel || ctxInfo.angleVendor() == GrGLVendor::kIntel) {
// Gen11 seems mostly ok, except we avoid drawing lines with MSAA. (anglebug.com/7796)
if (ctxInfo.renderer() >= GrGLRenderer::kIntelIceLake &&
contextOptions.fAllowMSAAOnNewIntel) {
if (fMSFBOType != kNone_MSFBOType) {
fAvoidLineDraws = true;
}
} else {
fMSFBOType = kNone_MSFBOType;
}
}
// ANGLE's D3D9 backend + AMD GPUs are flaky with program binary caching (skbug.com/10395)
if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D9 &&
ctxInfo.angleVendor() == GrGLVendor::kATI) {
fProgramBinarySupport = false;
}
// skbug.com/11204. Avoid recursion issue in SurfaceContext::writePixels.
if (fDisallowTexSubImageForUnormConfigTexturesEverBoundToFBO) {
fReuseScratchTextures = false;
}
// skbug.com/11935. Don't reorder on these GPUs in GL on old drivers.
if ((ctxInfo.renderer() == GrGLRenderer::kAdreno620 ||
ctxInfo.renderer() == GrGLRenderer::kAdreno640) &&
ctxInfo.driverVersion() < GR_GL_DRIVER_VER(571, 0, 0)) {
fAvoidReorderingRenderTasks = true;
}
// http://crbug.com/1197152
// http://b/187364475
// We could limit this < 1.13 on ChromeOS but we don't really have a good way to detect
// ChromeOS from here.
if (ctxInfo.renderer() == GrGLRenderer::kPowerVRRogue &&
ctxInfo.driver() == GrGLDriver::kImagination &&
driverVersion < GR_GL_DRIVER_VER(1, 16, 0)) {
fShaderCaps->fShaderDerivativeSupport = false;
}
if (ctxInfo.driver() == GrGLDriver::kFreedreno) {
formatWorkarounds->fDisallowUnorm16Transfers = true;
}
// If we keep rebind the same texture to an FBO's color attachment but changing between MSAA and
// non-MSAA we get corruption in the texture contents. Binding texture 0 and then rebinding the
// original texture avoids this.
// This was found on Nexus 5, Android 6.0.1, build M4B30Z
// GL_VENDOR : "Qualcomm"
// GL_RENDERER: "Adreno (TM) 330"
// GL_VERSION : "OpenGL ES 3.0 V@127.0 AU@ (GIT@I96aee987eb)"
//
// We also so alpha blending issues on these GMs skbug_9819, p3_ovals, p3 on Mali-Gxx devices
// The GM issues were observed on a Galaxy S9 running Android 10:
// GL_VERSION : "OpenGL ES 3.2 v1.r19p0-01rel0.###other-sha0123456789ABCDEF0###"
// GL_RENDERER: "Mali-G72"
// GL_VENDOR : "ARM"
// and a P30 running Android 9:
// GL_VERSION : "OpenGL ES 3.2 v1.r16p0-01rel0.4aee637066427cbcd25297324dba15f5"
// GL_RENDERER: "Mali-G76"
// GL_VENDOR : "ARM"
// but *not* a Galaxy S20 running Android 10:
// GL_VERSION : "OpenGL ES 3.2 v1.r20p0-01rel0.###other-sha0123456789ABCDEF0###"
// GL_RENDERER: "Mali-G77"
// GL_VENDOR : "ARM"
// It's unclear if the difference is driver version or Bifrost vs Valhall. The workaround is
// fairly trivial so just applying to all Bifrost and Valhall.
if ((ctxInfo.renderer() == GrGLRenderer::kAdreno3xx &&
ctxInfo.driver() == GrGLDriver::kQualcomm) ||
(ctxInfo.renderer() == GrGLRenderer::kMaliG)) {
fBindTexture0WhenChangingTextureFBOMultisampleCount = true;
}
// skbug.com/12640
// We found that on the Galaxy S7 the TransferPixelsTo test would fail after adding
// glCheckFramebufferStatus() checks when making new FBOs. Note that the returned status was
// GL_FRAMEBUFFER_COMPLETE. Switching the color binding to ID 0 and back to the original
// afterwards works around the issue.
// GL_VENDOR : "ARM"
// GL_RENDERER: "Mali-T880"
// GL_VERSION : "OpenGL ES 3.2 v1.r22p0-01rel0.f294e54ceb2cb2d81039204fa4b0402e"
//
// This *didn't* reproduce on a Kevin ChromeOS device:
// GL_VENDOR : "ARM"
// GL_RENDERER: "Mali-T860"
// GL_VERSION : "OpenGL ES 3.2 v1.r26p0-01rel0.217d2597f6bd19b169343737782e56e3"
if (ctxInfo.renderer() == GrGLRenderer::kMaliT &&
ctxInfo.driver() == GrGLDriver::kARM &&
ctxInfo.driverVersion() < GR_GL_DRIVER_VER(1, 26, 0)) {
fRebindColorAttachmentAfterCheckFramebufferStatus = true;
}
#ifdef SK_BUILD_FOR_MAC
// skbug.com/398631003
if (ctxInfo.vendor() == GrGLVendor::kApple &&
// Even the GL ANGLE backend doesn't have this issue, so the workaround is only necessary
// if we're not rendering with ANGLE.
ctxInfo.angleBackend() == GrGLANGLEBackend::kUnknown) {
fBindDefaultFramebufferOnPresent = true;
}
#endif
// skbug.com/13286
// We found that the P30 produces a GL error when setting GL_TEXTURE_MAX_ANISOTROPY as a sampler
// parameter but not as a texture parameter. We are disabling anisotropy on drivers that may
// be affected.
//
// FAIL on P30
// GL_VENDOR : ARM
// GL_RENDERER: Mali-G76
// GL_VERSION : OpenGL ES 3.2 v1.r16p0-01rel0.4aee637066427cbcd25297324dba15f5
//
// PASS on Pixel6
// GL_VENDOR : ARM
// GL_RENDERER: Mali-G78
// GL_VERSION : OpenGL ES 3.2 v1.r32p1-00pxl0.b7e5868a59a273f4a9f58d1657ef99de
//
// PASS on Galaxy S30:
// GL_VENDOR : ARM
// GL_RENDERER: Mali-G77
// GL_VERSION : OpenGL ES 3.2 v1.r20p0-01rel0.###other-sha0123456789ABCDEF0###
//
// PASS on Galaxy S9:
// GL_VENDOR : ARM
// GL_RENDERER: Mali-G72
// GL_VENDOR : OpenGL ES 3.2 v1.r19p0-01rel0.###other-sha0123456789ABCDEF0###
if (ctxInfo.renderer() == GrGLRenderer::kMaliG &&
ctxInfo.driver() == GrGLDriver::kARM &&
ctxInfo.driverVersion() < GR_GL_DRIVER_VER(1, 19, 0)) {
fAnisoSupport = false;
}
// b/229626353
// On certain classes of Adreno running WebGL, glTexSubImage2D() occasionally fails to upload
// texels on time for sampling. The solution is to call glFlush() before glTexSubImage2D().
// Seen on:
// * Nexus 5x (Adreno 418)
// * Nexus 6 (Adreno 420)
// * Pixel 3 (Adreno 630)
if (ctxInfo.renderer() == GrGLRenderer::kWebGL &&
(ctxInfo.webglRenderer() == GrGLRenderer::kAdreno4xx_other ||
ctxInfo.webglRenderer() == GrGLRenderer::kAdreno630)) {
fFlushBeforeWritePixels = true;
}
// crbug.com/1395777
// There appears to be a driver bug in GLSL program linking on Mali 400 and 450 devices with
// driver version 2.1.199xx that causes the copy-as-draw programs in GrGLGpu to fail. The crash
// rate increased when scaling copy support was added, so disallow scaling copy-as-draws on
// these devices.
if (ctxInfo.renderer() == GrGLRenderer::kMali4xx &&
ctxInfo.driverVersion() >= GR_GL_DRIVER_VER(2, 1, 19900)) {
fDisableScalingCopyAsDraws = true;
}
// skbug.com/14194
// Setting the max level is technically unnecessary, but on Intel drivers it makes it
// clear that a rendering feedback loop is not occurring, and avoids hitting a slow path.
// When running on ANGLE, however, this triggers the validator because we can only use
// levels between BASE_LEVEL and MAX_LEVEL for a framebuffer, and we're trying to use
// MAX_LEVEL+1. So instead we set up sync points between each mipmap level render.
if (ctxInfo.vendor() == GrGLVendor::kIntel &&
ctxInfo.angleBackend() == GrGLANGLEBackend::kUnknown) {
fRegenerateMipmapType = RegenerateMipmapType::kBasePlusMaxLevel;
} else if (ctxInfo.angleVendor() == GrGLVendor::kIntel) {
fRegenerateMipmapType = RegenerateMipmapType::kBasePlusSync;
}
#ifdef SK_BUILD_FOR_MAC
// On Apple Silicon, RG88 requires 2-byte alignment for transfer buffer readback
if (ctxInfo.vendor() == GrGLVendor::kApple) {
fPadRG88TransferAlignment = true;
}
#endif
}