blob: f96a79ae8fcd08c1c79a8c3741e8d473560965f9 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gl/gl_switches.h"
#include <array>
#include "base/trace_event/trace_event.h"
#include "build/android_buildflags.h"
#include "build/build_config.h"
#include "ui/gl/buildflags.h"
#include "ui/gl/gl_display_manager.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/android_info.h"
#endif
#if BUILDFLAG(ENABLE_VULKAN) && \
(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID))
#include <vulkan/vulkan_core.h>
#include "third_party/angle/src/gpu_info_util/SystemInfo.h" // nogncheck
#endif // BUILDFLAG(ENABLE_VULKAN) && (BUILDFLAG(IS_LINUX) ||
// BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID))
namespace gl {
const char kGLImplementationEGLName[] = "egl";
const char kGLImplementationANGLEName[] = "angle";
const char kGLImplementationMockName[] = "mock";
const char kGLImplementationStubName[] = "stub";
const char kGLImplementationDisabledName[] = "disabled";
const char kANGLEImplementationDefaultName[] = "default";
const char kANGLEImplementationD3D9Name[] = "d3d9";
const char kANGLEImplementationD3D11Name[] = "d3d11";
const char kANGLEImplementationD3D11on12Name[] = "d3d11on12";
const char kANGLEImplementationD3D11WarpName[] = "d3d11-warp";
const char kANGLEImplementationD3D11WarpForWebGLName[] = "d3d11-warp-webgl";
const char kANGLEImplementationOpenGLName[] = "gl";
const char kANGLEImplementationOpenGLEGLName[] = "gl-egl";
const char kANGLEImplementationOpenGLESName[] = "gles";
const char kANGLEImplementationOpenGLESEGLName[] = "gles-egl";
const char kANGLEImplementationNullName[] = "null";
const char kANGLEImplementationVulkanName[] = "vulkan";
const char kANGLEImplementationSwiftShaderName[] = "swiftshader";
const char kANGLEImplementationSwiftShaderForWebGLName[] = "swiftshader-webgl";
const char kANGLEImplementationMetalName[] = "metal";
const char kANGLEImplementationNoneName[] = "";
// Special switches for "NULL"/stub driver implementations.
const char kANGLEImplementationD3D11NULLName[] = "d3d11-null";
const char kANGLEImplementationOpenGLNULLName[] = "gl-null";
const char kANGLEImplementationOpenGLESNULLName[] = "gles-null";
const char kANGLEImplementationVulkanNULLName[] = "vulkan-null";
const char kANGLEImplementationMetalNULLName[] = "metal-null";
// The command decoder names that can be passed to --use-cmd-decoder.
const char kCmdDecoderValidatingName[] = "validating";
const char kCmdDecoderPassthroughName[] = "passthrough";
// Swap chain formats for direct composition SDR video overlays.
const char kSwapChainFormatNV12[] = "nv12";
const char kSwapChainFormatYUY2[] = "yuy2";
const char kSwapChainFormatBGRA[] = "bgra";
const char kSwapChainFormatP010[] = "p010";
} // namespace gl
namespace switches {
// Disable workarounds for various GPU driver bugs.
const char kDisableGpuDriverBugWorkarounds[] =
"disable-gpu-driver-bug-workarounds";
// Stop the GPU from synchronizing presentation with vblank.
const char kDisableGpuVsync[] = "disable-gpu-vsync";
// Turns on GPU logging (debug build only).
const char kEnableGPUServiceLogging[] = "enable-gpu-service-logging";
// Turns on calling TRACE for every GL call.
const char kEnableGPUServiceTracing[] = "enable-gpu-service-tracing";
// Select which ANGLE backend to use. Options are:
// default: Attempts several ANGLE renderers until one successfully
// initializes, varying ES support by platform.
// d3d9: Legacy D3D9 renderer, ES2 only.
// d3d11: D3D11 renderer, ES2 and ES3.
// warp: D3D11 renderer using software rasterization, ES2 and ES3.
// gl: Desktop GL renderer, ES2 and ES3.
// gles: GLES renderer, ES2 and ES3.
const char kUseANGLE[] = "use-angle";
// Use the Pass-through command decoder, skipping all validation and state
// tracking. Switch lives in ui/gl because it affects the GL binding
// initialization on platforms that would otherwise not default to using
// EGL bindings.
const char kUseCmdDecoder[] = "use-cmd-decoder";
// ANGLE features are defined per-backend in third_party/angle/include/platform
// Enables specified comma separated ANGLE features if found.
const char kEnableANGLEFeatures[] = "enable-angle-features";
// Disables specified comma separated ANGLE features if found.
const char kDisableANGLEFeatures[] = "disable-angle-features";
// Select which implementation of GL the GPU process should use. Options are:
// desktop: whatever desktop OpenGL the user has installed (Linux and Mac
// default).
// egl: whatever EGL / GLES2 the user has installed (Windows default - actually
// ANGLE).
// swiftshader: The SwiftShader software renderer.
const char kUseGL[] = "use-gl";
// Inform Chrome that a GPU context will not be lost in power saving mode,
// screen saving mode, etc. Note that this flag does not ensure that a GPU
// context will never be lost in any situations, say, a GPU reset.
const char kGpuNoContextLost[] = "gpu-no-context-lost";
// Flag used for Linux tests: for desktop GL bindings, try to load this GL
// library first, but fall back to regular library if loading fails.
const char kTestGLLib[] = "test-gl-lib";
// Use hardware gpu, if available, for tests.
const char kUseGpuInTests[] = "use-gpu-in-tests";
// Enable use of the SGI_video_sync extension, which can have
// driver/sandbox/window manager compatibility issues.
const char kEnableSgiVideoSync[] = "enable-sgi-video-sync";
// Disables GL drawing operations which produce pixel output. With this
// the GL output will not be correct but tests will run faster.
const char kDisableGLDrawingForTests[] = "disable-gl-drawing-for-tests";
// Forces the use of software GL instead of hardware gpu for tests.
const char kOverrideUseSoftwareGLForTests[] =
"override-use-software-gl-for-tests";
// Disables specified comma separated GL Extensions if found.
const char kDisableGLExtensions[] = "disable-gl-extensions";
// Enables SwapBuffersWithBounds if it is supported.
const char kEnableSwapBuffersWithBounds[] = "enable-swap-buffers-with-bounds";
// Disable DirectComposition.
const char kDisableDirectComposition[] = "disable-direct-composition";
// Enable DirectComposition video overlays even if hardware doesn't support it.
const char kEnableDirectCompositionVideoOverlays[] =
"enable-direct-composition-video-overlays";
// Initialize the GPU process using the adapter with the specified LUID. This is
// only used on Windows, as LUID is a Windows specific structure.
const char kUseAdapterLuid[] = "use-adapter-luid";
// Allow usage of SwiftShader for WebGL
const char kEnableUnsafeSwiftShader[] = "enable-unsafe-swiftshader";
// Used for overriding the swap chain format for direct composition SDR video
// overlays.
const char kDirectCompositionVideoSwapChainFormat[] =
"direct-composition-video-swap-chain-format";
// Tint `SwapChainPresenter` with the following colors:
//
// - Decode swap chain: blue
// - VP blit: magenta
// - VP blit w/ staging texture: orange
// - MF proxy surface: green
//
// This is similar to `HKLM\Software\Microsoft\Windows\DWM` `OverlayTestMode=1`
// in DWM, but to help understand `SwapChainPresenter` state.
const char kTintDcLayer[] = "tint-dc-layer";
// This is the list of switches passed from this file that are passed from the
// GpuProcessHost to the GPU Process. Add your switch to this list if you need
// to read it in the GPU process, else don't add it.
const auto kGLSwitchesCopiedFromGpuProcessHostArray = std::to_array({
kDisableGpuDriverBugWorkarounds,
kDisableGpuVsync,
kEnableGPUServiceLogging,
kEnableGPUServiceTracing,
kEnableSgiVideoSync,
kGpuNoContextLost,
kDisableGLDrawingForTests,
kOverrideUseSoftwareGLForTests,
kUseANGLE,
kEnableSwapBuffersWithBounds,
kDisableDirectComposition,
kEnableDirectCompositionVideoOverlays,
kDirectCompositionVideoSwapChainFormat,
kTintDcLayer,
kEnableUnsafeSwiftShader,
});
// An external span to the array above, so that it can be exposed from the
// header file without specifying the size of the array manually.
const base::span<const char* const> kGLSwitchesCopiedFromGpuProcessHost =
kGLSwitchesCopiedFromGpuProcessHostArray;
#if BUILDFLAG(IS_ANDROID)
// On some Android emulators with software GL, ANGLE
// is exposing the native fence sync extension but it doesn't
// actually work. This switch is used to disable the Android native fence sync
// during test to avoid crashes.
//
// TODO(https://crbug.com/337886037): Remove this flag once the upstream ANGLE
// is fixed.
const char kDisableAndroidNativeFenceSyncForTesting[] =
"disable-android-native-fence-sync-for-testing";
#endif
} // namespace switches
namespace features {
// Enable DComp debug visualizations. This can be useful to determine how much
// work DWM is doing when we update our tree.
//
// Please be aware that some of these visualizations result in quickly flashing
// colors.
BASE_FEATURE(kDCompDebugVisualization, base::FEATURE_DISABLED_BY_DEFAULT);
// Use BufferCount of 3 for direct composition video swap chains.
BASE_FEATURE(kDCompTripleBufferVideoSwapChain,
base::FEATURE_DISABLED_BY_DEFAULT);
// Allow overlay swapchain to present on all GPUs even if they only support
// software overlays. GPU deny lists limit it to NVIDIA only at the moment.
BASE_FEATURE(kDirectCompositionSoftwareOverlays,
base::FEATURE_ENABLED_BY_DEFAULT);
// Detect and mark a single full screen video during overlay processing.
BASE_FEATURE(kEarlyFullScreenVideoOptimization,
base::FEATURE_ENABLED_BY_DEFAULT);
// Adjust the letterbox video size and position to the center of the screen so
// that DWM power optimization can be turned on.
BASE_FEATURE(kDirectCompositionLetterboxVideoOptimization,
base::FEATURE_ENABLED_BY_DEFAULT);
// Remove the topmost desktop plane for Media Foundation full screen
// letterboxing. This is a kill switch for the desktop plane removal
// optimization for Media Foundation Renderer, which should be enabled by
// default when crbug.com/406175378 is resolved.
BASE_FEATURE(kDesktopPlaneRemovalForMFFullScreenLetterbox,
base::FEATURE_ENABLED_BY_DEFAULT);
// Do not consider hardware YUV overlay count when promoting quads to DComp
// visuals. If there are more videos than hardware overlay planes, there may be
// a performance hit compared to drawing all the videos into a single swap
// chain. This feature is intended for testing and debugging.
BASE_FEATURE(kDirectCompositionUnlimitedOverlays,
base::FEATURE_DISABLED_BY_DEFAULT);
// Allow dual GPU rendering through EGL where supported, i.e., allow a WebGL
// or WebGPU context to be on the high performance GPU if preferred and Chrome
// internal rendering to be on the low power GPU.
BASE_FEATURE(kEGLDualGPURendering,
#if BUILDFLAG(IS_MAC)
base::FEATURE_ENABLED_BY_DEFAULT);
#else
base::FEATURE_DISABLED_BY_DEFAULT);
#endif
// Allow overlay swapchain to use Intel video processor for super resolution.
BASE_FEATURE(kIntelVpSuperResolution, base::FEATURE_DISABLED_BY_DEFAULT);
// Default to using ANGLE's Metal backend.
BASE_FEATURE(kDefaultANGLEMetal, base::FEATURE_ENABLED_BY_DEFAULT);
// Default to using ANGLE's Vulkan backend.
BASE_FEATURE(kDefaultANGLEVulkan,
#if BUILDFLAG(IS_DESKTOP_ANDROID)
base::FEATURE_ENABLED_BY_DEFAULT);
#else
base::FEATURE_DISABLED_BY_DEFAULT);
#endif
// Track current program's shaders at glUseProgram() call for crash report
// purpose. Only effective on Windows because the attached shaders may only
// be reliably retrieved with ANGLE backend.
BASE_FEATURE(kTrackCurrentShaders, base::FEATURE_DISABLED_BY_DEFAULT);
// Enable sharing Vulkan device queue with ANGLE's Vulkan backend.
BASE_FEATURE(kVulkanFromANGLE,
#if BUILDFLAG(IS_DESKTOP_ANDROID)
base::FEATURE_ENABLED_BY_DEFAULT);
#else
base::FEATURE_DISABLED_BY_DEFAULT);
#endif
bool IsDefaultANGLEVulkan() {
// Force on if DefaultANGLEVulkan feature is enabled from command line.
base::FeatureList* feature_list = base::FeatureList::GetInstance();
if (feature_list && feature_list->IsFeatureOverriddenFromCommandLine(
features::kDefaultANGLEVulkan.name,
base::FeatureList::OVERRIDE_ENABLE_FEATURE)) {
return true;
}
#if defined(MEMORY_SANITIZER)
return false;
#else // !defined(MEMORY_SANITIZER)
#if BUILDFLAG(IS_ANDROID)
// No support for devices before Q -- exit before checking feature flags
// so that devices are not counted in finch trials.
if (base::android::android_info::sdk_int() <
base::android::android_info::SDK_VERSION_Q) {
return false;
}
// For the sake of finch trials, limit to newer devices (Android T+); this
// condition can be relaxed over time.
if (base::android::android_info::sdk_int() <
base::android::android_info::SDK_VERSION_T) {
return false;
}
#endif // BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(ENABLE_VULKAN) && \
(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID))
angle::SystemInfo system_info;
{
TRACE_EVENT("gpu,startup", "angle::GetSystemInfoVulkan");
if (!angle::GetSystemInfoVulkan(&system_info)) {
return false;
}
}
if (static_cast<size_t>(system_info.activeGPUIndex) >=
system_info.gpus.size()) {
return false;
}
const auto& active_gpu = system_info.gpus[system_info.activeGPUIndex];
// Vulkan 1.1 is ANGLE's minimum requirement, but drivers older than 1.3 are
// rarely reliable enough.
if (active_gpu.driverApiVersion < VK_VERSION_1_3) {
return false;
}
// If |dirverId| is 0, the driver lacks VK_KHR_driver_properties.
// Consider this driver too old to be usable.
if (active_gpu.driverId == 0)
return false;
#if BUILDFLAG(IS_ANDROID)
// Samsung GPUs already use ANGLE as the GLES driver. Always choose
// ANGLE/Vulkan on these GPUs to avoid the inefficiencies of translating
// over ANGLE twice. This is not done if the feature is explicitly disabled
// (from command line, or by webview).
if (active_gpu.driverId == VK_DRIVER_ID_SAMSUNG_PROPRIETARY) {
if (!(feature_list && feature_list->IsFeatureOverriddenFromCommandLine(
features::kDefaultANGLEVulkan.name,
base::FeatureList::OVERRIDE_DISABLE_FEATURE))) {
return true;
}
}
// Exclude SwiftShader-based Android emulators for now.
if (active_gpu.driverId == VK_DRIVER_ID_GOOGLE_SWIFTSHADER) {
return false;
}
// Encountered bugs with older Imagination drivers. New drivers seem fixed,
// but disabled for the sake of experiment for now. crbug.com/371512561
if (active_gpu.driverId == VK_DRIVER_ID_IMAGINATION_PROPRIETARY) {
return false;
}
// Exclude old ARM drivers due to crashes related to creating
// AHB-based Video images in Vulkan. http://crbug.com/382676807.
if (active_gpu.driverId == VK_DRIVER_ID_ARM_PROPRIETARY &&
active_gpu.detailedDriverVersion.major <= 32) {
return false;
}
// Exclude old ARM chipsets due to rendering bugs, G52 is still found in
// Xiaomi phones. Note that if included in the future, there still seems to be
// a driver bug with async garbage collection, so that feature needs to be
// disabled in ANGLE. http://crbug.com/405085132
if (active_gpu.driverId == VK_DRIVER_ID_ARM_PROPRIETARY &&
active_gpu.deviceName.find("G52") != std::string::npos) {
return false;
}
// Exclude old Qualcomm drivers due to inefficient (and buggy) fallback
// to CPU path in glCopyTextureCHROMIUM with multi-plane images.
// http://crbug.com/383056998.
if (active_gpu.driverId == VK_DRIVER_ID_QUALCOMM_PROPRIETARY &&
active_gpu.detailedDriverVersion.minor <= 530) {
return false;
}
// Exclude Qualcomm 512.615 driver on Xiaomi phones that is the cause of
// yet-to-be explained GPU hangs.
// http://crbug.com/382725542
if (active_gpu.driverId == VK_DRIVER_ID_QUALCOMM_PROPRIETARY &&
active_gpu.detailedDriverVersion.minor == 615) {
return false;
}
// Exclude Qualcomm 512.676 driver on Adreno 720 that is the cause of
// undiagnosed rendering issues.
// http://crbug.com/440110161
if (active_gpu.driverId == VK_DRIVER_ID_QUALCOMM_PROPRIETARY &&
active_gpu.deviceName.find("Adreno") != std::string::npos &&
active_gpu.deviceName.find("720") != std::string::npos &&
active_gpu.detailedDriverVersion.minor == 676) {
return false;
}
#endif // BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_LINUX)
// AMDVLK driver is buggy, so disable Vulkan with AMDVLK for now.
// crbug.com/1340081
if (active_gpu.driverId == VK_DRIVER_ID_AMD_OPEN_SOURCE)
return false;
#endif // BUILDFLAG(IS_LINUX)
// The performance of MESA llvmpipe is really bad.
if (active_gpu.driverId == VK_DRIVER_ID_MESA_LLVMPIPE) {
return false;
}
#endif // BUILDFLAG(ENABLE_VULKAN) && (BUILDFLAG(IS_LINUX) ||
// BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID))
return base::FeatureList::IsEnabled(kDefaultANGLEVulkan);
#endif // !defined(MEMORY_SANITIZER)
}
// Use waitable swap chain on Windows to reduce display latency.
BASE_FEATURE(kDXGIWaitableSwapChain, base::FEATURE_DISABLED_BY_DEFAULT);
// If using waitable swap chain, specify the maximum number of queued frames.
const base::FeatureParam<int> kDXGIWaitableSwapChainMaxQueuedFrames{
&kDXGIWaitableSwapChain, "DXGIWaitableSwapChainMaxQueuedFrames", 2};
// Force a present interval of 0. This asks Windows to cancel the remaining time
// on the previously presented frame instead of synchronizing with vblank(s).
// Frames may be discarded if they are presented more frequently than one per
// vblank.
BASE_FEATURE(kDXGISwapChainPresentInterval0, base::FEATURE_DISABLED_BY_DEFAULT);
bool SupportsEGLDualGPURendering() {
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
return base::FeatureList::IsEnabled(kEGLDualGPURendering);
#else
return false;
#endif // IS_WIN || IS_MAC
}
} // namespace features