#include "gpu/ipc/service/gpu_init.h"
#include <cstdlib>
#include <cstring>
#include <optional>
#include <string>
#include "arkweb/build/features/features.h"
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/debug/dump_without_crashing.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/strings/pattern.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
#include "build/chromeos_buildflags.h"
#include "components/crash/core/common/crash_key.h"
#include "components/viz/common/resources/shared_image_format.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/config/gpu_driver_bug_list.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "gpu/config/gpu_feature_type.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_info_collector.h"
#include "gpu/config/gpu_preferences.h"
#include "gpu/config/gpu_switches.h"
#include "gpu/config/gpu_switching.h"
#include "gpu/config/gpu_util.h"
#include "gpu/ipc/service/gpu_watchdog_thread.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/switches.h"
#include "ui/gl/buildflags.h"
#include "ui/gl/gl_display.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_switches.h"
#include "ui/gl/gl_utils.h"
#include "ui/gl/init/gl_factory.h"
#if BUILDFLAG(IS_MAC)
#include <GLES2/gl2.h>
#endif
#if BUILDFLAG(IS_OZONE)
#if BUILDFLAG(ENABLE_VULKAN)
#include "gpu/command_buffer/service/drm_modifiers_filter_vulkan.h"
#endif
#include "ui/ozone/public/drm_modifiers_filter.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/surface_factory_ozone.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "ui/gl/direct_composition_support.h"
#include "ui/gl/gl_angle_util_win.h"
#include "ui/gl/gl_surface_egl.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "ui/gfx/android/android_surface_control_compat.h"
#endif
#if BUILDFLAG(ENABLE_VULKAN)
#include "gpu/vulkan/init/vulkan_factory.h"
#include "gpu/vulkan/vulkan_implementation.h"
#include "gpu/vulkan/vulkan_instance.h"
#include "gpu/vulkan/vulkan_util.h"
#endif
#if !BUILDFLAG(IS_MAC)
#include "ui/gl/gl_fence_egl.h"
#endif
#if BUILDFLAG(USE_DAWN) || BUILDFLAG(SKIA_USE_DAWN)
#include "third_party/dawn/include/dawn/dawn_proc.h"
#include "third_party/dawn/include/dawn/native/DawnNative.h"
#endif
#if BUILDFLAG(SKIA_USE_DAWN)
#include "gpu/command_buffer/service/dawn_context_provider.h"
#include "third_party/dawn/include/dawn/webgpu_cpp.h"
#endif
#if BUILDFLAG(SKIA_USE_DAWN) && BUILDFLAG(IS_CHROMEOS)
#include "gpu/command_buffer/service/drm_modifiers_filter_dawn.h"
#endif
#include "arkweb/chromium_ext/gpu/ipc/service/gpu_init_ext.h"
namespace gpu {
namespace {
bool CollectGraphicsInfo(GPUInfo* gpu_info) {
DCHECK(gpu_info);
TRACE_EVENT("gpu,startup", "Collect Graphics Info");
bool success = CollectContextGraphicsInfo(gpu_info);
if (!success)
LOG(ERROR) << "CollectGraphicsInfo failed.";
return success;
}
void InitializeDawnProcs() {
#if BUILDFLAG(USE_DAWN) || BUILDFLAG(SKIA_USE_DAWN)
TRACE_EVENT("gpu,startup", "gpu_init::InitializeDawnProcs");
dawnProcSetProcs(&dawn::native::GetProcs());
#endif
}
void InitializePlatformOverlaySettings(GPUInfo* gpu_info,
const GpuFeatureInfo& gpu_feature_info) {
#if BUILDFLAG(IS_WIN)
gl::DirectCompositionOverlayWorkarounds workarounds = {
.disable_sw_video_overlays = gpu_feature_info.IsWorkaroundEnabled(
DISABLE_DIRECT_COMPOSITION_SW_VIDEO_OVERLAYS),
.disable_decode_swap_chain =
gpu_feature_info.IsWorkaroundEnabled(DISABLE_DECODE_SWAP_CHAIN),
.enable_bgra8_overlays_with_yuv_overlay_support =
gpu_feature_info.IsWorkaroundEnabled(
gpu::ENABLE_BGRA8_OVERLAYS_WITH_YUV_OVERLAY_SUPPORT),
.force_nv12_overlay_support =
gpu_feature_info.IsWorkaroundEnabled(gpu::FORCE_NV12_OVERLAY_SUPPORT),
.force_rgb10a2_overlay_support = gpu_feature_info.IsWorkaroundEnabled(
gpu::FORCE_RGB10A2_OVERLAY_SUPPORT),
.check_ycbcr_studio_g22_left_p709_for_nv12_support =
gpu_feature_info.IsWorkaroundEnabled(
gpu::CHECK_YCBCR_STUDIO_G22_LEFT_P709_FOR_NV12_SUPPORT),
.disable_dcomp_texture =
gpu_feature_info.IsWorkaroundEnabled(gpu::DISABLE_DCOMP_TEXTURE),
};
SetDirectCompositionOverlayWorkarounds(workarounds);
DCHECK(gpu_info);
CollectHardwareOverlayInfo(&gpu_info->overlay_info);
#elif BUILDFLAG(IS_ANDROID)
if (gpu_info->gpu.vendor_string.find("Qualcomm") != std::string::npos) {
gfx::SurfaceControl::EnableQualcommUBWC();
}
#endif
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CASTOS)
bool CanAccessDeviceFile(const GPUInfo& gpu_info) {
#if BUILDFLAG(IS_LINUX)
if (gpu_info.gpu.vendor_id != 0x10de ||
gpu_info.gpu.driver_vendor != "NVIDIA")
return true;
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::WILL_BLOCK);
if (access("/dev/nvidiactl", R_OK) != 0) {
DVLOG(1) << "NVIDIA device file /dev/nvidiactl access denied";
return false;
}
return true;
#else
return true;
#endif
}
#endif
class GpuWatchdogInit {
public:
GpuWatchdogInit() = default;
~GpuWatchdogInit() {
if (watchdog_ptr_)
watchdog_ptr_->OnInitComplete();
}
void SetGpuWatchdogPtr(GpuWatchdogThread* ptr) { watchdog_ptr_ = ptr; }
private:
raw_ptr<GpuWatchdogThread, DanglingUntriaged> watchdog_ptr_ = nullptr;
};
void PauseGpuWatchdog(GpuWatchdogThread* watchdog_thread) {
if (watchdog_thread) {
watchdog_thread->PauseWatchdog();
}
}
void ResumeGpuWatchdog(GpuWatchdogThread* watchdog_thread) {
if (watchdog_thread) {
watchdog_thread->ResumeWatchdog();
}
}
void DisableInProcessGpuVulkan(GpuFeatureInfo* gpu_feature_info,
GpuPreferences* gpu_preferences) {
if (gpu_feature_info->status_values[GPU_FEATURE_TYPE_VULKAN] ==
kGpuFeatureStatusEnabled ||
gpu_preferences->gr_context_type == GrContextType::kVulkan) {
LOG(ERROR) << "Vulkan not supported with in process gpu";
gpu_preferences->use_vulkan = VulkanImplementationName::kNone;
gpu_feature_info->status_values[GPU_FEATURE_TYPE_VULKAN] =
kGpuFeatureStatusDisabled;
gpu_preferences->gr_context_type = GrContextType::kGL;
}
}
#if BUILDFLAG(IS_ANDROID)
void DisableInProcessGpuGraphite(GpuFeatureInfo& gpu_feature_info,
GpuPreferences& gpu_preferences) {
if (gpu_feature_info.status_values[GPU_FEATURE_TYPE_SKIA_GRAPHITE] ==
kGpuFeatureStatusEnabled ||
gpu_preferences.gr_context_type == GrContextType::kGraphiteDawn) {
LOG(ERROR) << "Graphite not supported with in process gpu";
gpu_feature_info.status_values[GPU_FEATURE_TYPE_SKIA_GRAPHITE] =
kGpuFeatureStatusDisabled;
gpu_preferences.gr_context_type = GrContextType::kGL;
}
}
#endif
#if BUILDFLAG(ENABLE_VULKAN)
bool MatchGLInfo(const std::string& field, const std::string& patterns) {
auto pattern_strings = base::SplitString(patterns, "|", base::TRIM_WHITESPACE,
base::SPLIT_WANT_ALL);
for (const auto& pattern : pattern_strings) {
if (base::MatchPattern(field, pattern))
return true;
}
return false;
}
#endif
#if BUILDFLAG(IS_WIN)
uint64_t CHROME_LUID_to_uint64_t(const CHROME_LUID& luid) {
uint64_t id64 = static_cast<uint32_t>(luid.HighPart);
return (id64 << 32) | (luid.LowPart & 0xFFFFFFFF);
}
#endif
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
const GPUInfo::GPUDevice* GetDefaultGPU(
const GPUInfo& gpu_info,
const GpuFeatureInfo& gpu_feature_info) {
if (!gpu_feature_info.IsWorkaroundEnabled(FORCE_PHYSICAL_GPU_FOR_TESTING)) {
return &(gpu_info.gpu);
}
if (!gpu_info.gpu.IsSoftwareRenderer()) {
return &(gpu_info.gpu);
} else if (auto it =
std::ranges::find_if(gpu_info.secondary_gpus,
[](const GPUInfo::GPUDevice& device) {
return !device.IsSoftwareRenderer();
});
it != gpu_info.secondary_gpus.end()) {
return &(*it);
} else {
LOG(FATAL) << "No non-software renderer device available.";
}
}
void SetupGLDisplayManagerEGL(const GPUInfo& gpu_info,
const GpuFeatureInfo& gpu_feature_info) {
TRACE_EVENT("gpu,startup", "gpu_init::SetupGLDisplayManagerEGL");
const GPUInfo::GPUDevice* gpu_high_perf =
gpu_info.GetGpuByPreference(gl::GpuPreference::kHighPerformance);
const GPUInfo::GPUDevice* gpu_low_power =
gpu_info.GetGpuByPreference(gl::GpuPreference::kLowPower);
#if BUILDFLAG(IS_WIN)
const GPUInfo::GPUDevice* gpu_default =
GetDefaultGPU(gpu_info, gpu_feature_info);
uint64_t system_device_id_high_perf =
gpu_high_perf ? CHROME_LUID_to_uint64_t(gpu_high_perf->luid) : 0;
uint64_t system_device_id_low_power =
gpu_low_power ? CHROME_LUID_to_uint64_t(gpu_low_power->luid) : 0;
uint64_t system_device_id_default =
CHROME_LUID_to_uint64_t(gpu_default->luid);
#else
const GPUInfo::GPUDevice* gpu_default =
gpu_low_power ? gpu_low_power : GetDefaultGPU(gpu_info, gpu_feature_info);
uint64_t system_device_id_high_perf =
gpu_high_perf ? gpu_high_perf->system_device_id : 0;
uint64_t system_device_id_low_power =
gpu_low_power ? gpu_low_power->system_device_id : 0;
uint64_t system_device_id_default = gpu_default->system_device_id;
#endif
if (gpu_info.GpuCount() <= 1) {
gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
system_device_id_default);
return;
}
if (gpu_feature_info.IsWorkaroundEnabled(FORCE_LOW_POWER_GPU) &&
system_device_id_low_power) {
gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
system_device_id_low_power);
return;
}
if (gpu_feature_info.IsWorkaroundEnabled(FORCE_HIGH_PERFORMANCE_GPU) &&
system_device_id_high_perf) {
gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
system_device_id_high_perf);
return;
}
if (gpu_default == gpu_high_perf) {
gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
system_device_id_high_perf);
return;
}
gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
system_device_id_default);
if (system_device_id_high_perf) {
gl::SetGpuPreferenceEGL(gl::GpuPreference::kHighPerformance,
system_device_id_high_perf);
}
return;
}
#endif
}
GpuInit::GpuInit() = default;
GpuInit::~GpuInit() {
StopForceDiscreteGPU();
}
bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line,
const GpuPreferences& gpu_preferences) {
TRACE_EVENT("gpu,startup", "gpu::GpuInit::InitializeAndStartSandbox");
#if BUILDFLAG(IS_CHROMEOS)
LOG(WARNING) << "Starting gpu initialization.";
#endif
gpu_preferences_ = gpu_preferences;
gpu_preferences_.perform_graphite_precompilation =
features::IsSkiaGraphitePrecompilationEnabled(command_line);
bool needs_more_info = true;
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CASTOS)
needs_more_info = false;
CollectBasicGraphicsInfo(command_line, &gpu_info_);
SetKeysForCrashLogging(gpu_info_);
#if defined(SUBPIXEL_FONT_RENDERING_DISABLED)
gpu_info_.subpixel_font_rendering = false;
#else
gpu_info_.subpixel_font_rendering = true;
#endif
if (gpu_preferences_.enable_perf_data_collection) {
DevicePerfInfo device_perf_info;
CollectDevicePerfInfo(&device_perf_info, false);
device_perf_info_ = device_perf_info;
}
if (!CanAccessDeviceFile(gpu_info_))
return false;
gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
command_line, &needs_more_info);
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
SetupGLDisplayManagerEGL(gpu_info_, gpu_feature_info_);
#endif
#endif
gpu_info_.in_process_gpu = false;
DCHECK_EQ(gl::GetGLImplementation(), gl::kGLImplementationNone);
if (SwitchableGPUsSupported(gpu_info_, *command_line)) {
InitializeSwitchableGPUs(
gpu_feature_info_.enabled_gpu_driver_bug_workarounds);
}
gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
command_line, gpu_feature_info_,
gpu_preferences_.disable_software_rasterizer, needs_more_info);
bool enable_watchdog = !gpu_preferences_.disable_gpu_watchdog &&
!command_line->HasSwitch(switches::kHeadless);
#ifndef NDEBUG
enable_watchdog = false;
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_OHOS)
bool gpu_sandbox_start_early = gpu_preferences_.gpu_sandbox_start_early;
#else
bool gpu_sandbox_start_early = true;
#endif
if (gpu_sandbox_start_early) {
sandbox_helper_->PreSandboxStartup(gpu_preferences);
}
GpuWatchdogInit watchdog_init;
constexpr bool delayed_watchdog_enable = BUILDFLAG(IS_CHROMEOS);
if (enable_watchdog && !delayed_watchdog_enable) {
TRACE_EVENT("gpu,startup", "Create GpuWatchdog");
watchdog_thread_ =
GpuWatchdogThread::Create(gpu_preferences_.watchdog_starts_backgrounded,
gl_use_swiftshader_, "GpuWatchdog");
watchdog_init.SetGpuWatchdogPtr(watchdog_thread_.get());
}
bool attempted_startsandbox = false;
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_OHOS)
if (gpu_preferences_.gpu_sandbox_start_early) {
gpu_info_.sandboxed = sandbox_helper_->EnsureSandboxInitialized(
watchdog_thread_.get(), &gpu_info_, gpu_preferences_);
attempted_startsandbox = true;
}
#endif
#if BUILDFLAG(IS_OZONE)
ui::OzonePlatform::InitParams params;
params.single_process = false;
params.enable_native_gpu_memory_buffers =
gpu_preferences_.enable_native_gpu_memory_buffers;
params.handle_overlays_swap_failure =
base::FeatureList::IsEnabled(features::kHandleOverlaysSwapFailure);
#if BUILDFLAG(IS_CHROMEOS)
params.allow_sync_and_real_buffer_page_flip_testing = true;
#endif
ui::OzonePlatform::InitializeForGPU(params);
#endif
gl::GLDisplay* gl_display = nullptr;
PauseGpuWatchdog(watchdog_thread_.get());
if (!gl::init::InitializeStaticGLBindingsOneOff()) {
VLOG(1) << "gl::init::InitializeStaticGLBindingsOneOff failed";
return false;
}
#if BUILDFLAG(IS_WIN)
if (gpu_preferences_.gr_context_type == GrContextType::kGraphiteDawn &&
features::kSkiaGraphiteDawnBackendValidation.Get()) {
gl::GLDisplayEGL::EnableANGLEDebugLayer();
}
#endif
if (gl::GetGLImplementation() != gl::kGLImplementationDisabled) {
gl_display = gl::init::InitializeGLNoExtensionsOneOff(
false, gl::GpuPreference::kDefault);
if (!gl_display) {
gpu_preferences_.gr_context_type = GrContextType::kGL;
VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
return false;
}
}
const bool need_fallback_from_graphite = [this]() {
if (gpu_preferences_.gr_context_type != GrContextType::kGraphiteDawn &&
gpu_preferences_.gr_context_type != GrContextType::kGraphiteMetal) {
return false;
}
#if BUILDFLAG(IS_APPLE)
constexpr auto kRequiredANGLEImplementation = gl::ANGLEImplementation::kMetal;
#elif BUILDFLAG(IS_WIN)
constexpr auto kRequiredANGLEImplementation = gl::ANGLEImplementation::kD3D11;
#else
constexpr auto kRequiredANGLEImplementation = gl::ANGLEImplementation::kNone;
#endif
if (kRequiredANGLEImplementation == gl::ANGLEImplementation::kNone ||
gl::GetANGLEImplementation() == kRequiredANGLEImplementation) {
return false;
}
if (gl::GetANGLEImplementation() == gl::ANGLEImplementation::kSwiftShader) {
return false;
}
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableSkiaGraphite)) {
return false;
}
return true;
}();
if (need_fallback_from_graphite) {
gpu_preferences_.gr_context_type = GrContextType::kGL;
}
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
if (!attempted_startsandbox) {
sandbox_helper_->PreSandboxStartup(gpu_preferences);
}
#endif
ResumeGpuWatchdog(watchdog_thread_.get());
auto impl = gl::GetGLImplementationParts();
bool gl_disabled = impl == gl::kGLImplementationDisabled;
#if BUILDFLAG(ENABLE_VALIDATING_COMMAND_DECODER)
bool is_swangle = impl == gl::ANGLEImplementation::kSwiftShader;
gpu_preferences_.use_passthrough_cmd_decoder |= is_swangle;
gpu_info_.passthrough_cmd_decoder =
gpu_preferences_.use_passthrough_cmd_decoder;
#else
gpu_info_.passthrough_cmd_decoder = true;
gpu_preferences_.use_passthrough_cmd_decoder = true;
#endif
#if BUILDFLAG(IS_CHROMEOS)
if (gpu_preferences_.use_passthrough_cmd_decoder) {
LOG(WARNING) << "Using passthrough command decoder. NOTE: This log is "
<< "to help triage feedback reports and does not by itself mean there "
<< "is an issue.";
}
#endif
if (!gl_disabled) {
if (!gl_use_swiftshader_) {
if (!CollectGraphicsInfo(&gpu_info_)) {
VLOG(1) << "gpu::CollectGraphicsInfo failed";
return false;
}
SetKeysForCrashLogging(gpu_info_);
gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
command_line, nullptr);
gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
command_line, gpu_feature_info_,
gpu_preferences_.disable_software_rasterizer, false);
if (gl_use_swiftshader_) {
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly "
<< "on Linux";
return false;
#else
SaveHardwareGpuInfoAndGpuFeatureInfo();
gl::init::ShutdownGL(gl_display, true);
if (watchdog_thread_.get()) {
watchdog_thread_ = nullptr;
watchdog_init.SetGpuWatchdogPtr(nullptr);
watchdog_thread_ = GpuWatchdogThread::Create(
gpu_preferences_.watchdog_starts_backgrounded,
true, "GpuWatchdog");
watchdog_init.SetGpuWatchdogPtr(watchdog_thread_.get());
}
gl_display = gl::init::InitializeGLNoExtensionsOneOff(
true, gl::GpuPreference::kDefault);
if (!gl_display) {
VLOG(1)
<< "gl::init::InitializeGLNoExtensionsOneOff with SwiftShader "
<< "failed";
return false;
}
#endif
}
} else {
switch (gpu_preferences_.use_vulkan) {
case VulkanImplementationName::kNative: {
GPUInfo gpu_info;
if (!CollectGraphicsInfo(&gpu_info)) {
VLOG(1) << "gpu::CollectGraphicsInfo failed";
return false;
}
auto gpu_feature_info = ComputeGpuFeatureInfo(
gpu_info, gpu_preferences_, command_line, nullptr);
gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
gpu_feature_info.status_values[GPU_FEATURE_TYPE_VULKAN];
break;
}
case VulkanImplementationName::kForcedNative:
case VulkanImplementationName::kSwiftshader:
gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
kGpuFeatureStatusEnabled;
break;
case VulkanImplementationName::kNone:
gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
kGpuFeatureStatusDisabled;
break;
}
}
}
#if BUILDFLAG(IS_WIN)
{
PauseGpuWatchdog(watchdog_thread_.get());
base::FilePath module_path;
if (base::PathService::Get(base::DIR_MODULE, &module_path)) {
{
TRACE_EVENT("gpu,startup", "Load vk_swiftshader.dll");
base::LoadNativeLibrary(module_path.Append(L"vk_swiftshader.dll"),
nullptr);
}
#if defined(DAWN_USE_BUILT_DXC)
{
TRACE_EVENT("gpu,startup", "Load dxil.dll");
base::LoadNativeLibrary(module_path.Append(L"dxil.dll"), nullptr);
}
{
TRACE_EVENT("gpu,startup", "Load dxcompiler.dll");
base::LoadNativeLibrary(module_path.Append(L"dxcompiler.dll"), nullptr);
}
#endif
if (command_line->HasSwitch(switches::kUseRedistributableDirectML)) {
TRACE_EVENT("gpu,startup", "Load directml.dll");
base::LoadNativeLibrary(module_path.Append(L"directml.dll"), nullptr);
}
}
ResumeGpuWatchdog(watchdog_thread_.get());
}
#endif
#if BUILDFLAG(USE_WEBGPU_ON_VULKAN_VIA_GL_INTEROP)
if (gpu_feature_info_
.status_values[GPU_FEATURE_TYPE_WEBGPU_ON_VK_VIA_GL_INTEROP] ==
kGpuFeatureStatusEnabled) {
if (gpu_preferences_.use_vulkan == gpu::VulkanImplementationName::kNone) {
gpu_preferences_.use_vulkan = gpu::VulkanImplementationName::kNative;
}
gpu_preferences_.enable_webgpu_on_vk_via_gl_interop = true;
}
#endif
if (!(gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] ==
kGpuFeatureStatusEnabled ||
gpu_feature_info_
.status_values[GPU_FEATURE_TYPE_WEBGPU_ON_VK_VIA_GL_INTEROP] ==
kGpuFeatureStatusEnabled) ||
!InitializeVulkan()) {
gpu_preferences_.use_vulkan = VulkanImplementationName::kNone;
gpu_preferences_.enable_webgpu_on_vk_via_gl_interop = false;
gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
kGpuFeatureStatusDisabled;
gpu_feature_info_
.status_values[GPU_FEATURE_TYPE_WEBGPU_ON_VK_VIA_GL_INTEROP] =
kGpuFeatureStatusDisabled;
if (gpu_preferences_.gr_context_type == GrContextType::kVulkan) {
#if BUILDFLAG(IS_FUCHSIA)
LOG(FATAL) << "Vulkan initialization failed";
#else
gpu_preferences_.gr_context_type = GrContextType::kGL;
#endif
}
} else {
gpu_feature_info_.enabled_gpu_driver_bug_workarounds.push_back(
EXIT_ON_CONTEXT_LOST);
}
if (!gl_disabled) {
if (!CollectGpuExtraInfo(&gpu_extra_info_, gpu_preferences)) {
VLOG(1) << "gpu::CollectGpuExtraInfo failed";
return false;
}
}
if (!gl_disabled) {
if (!gpu_feature_info_.disabled_extensions.empty()) {
gl::init::SetDisabledExtensionsPlatform(
gpu_feature_info_.disabled_extensions);
}
if (!gl::init::InitializeExtensionSettingsOneOffPlatform(gl_display)) {
VLOG(1) << "gl::init::InitializeExtensionSettingsOneOffPlatform failed";
return false;
}
default_offscreen_surface_ =
gl::init::CreateOffscreenGLSurface(gl_display, gfx::Size());
if (!default_offscreen_surface_) {
VLOG(1) << "gl::init::CreateOffscreenGLSurface failed";
return false;
}
}
#if BUILDFLAG(IS_OZONE)
std::vector<gfx::BufferFormat> supported_buffer_formats_for_texturing;
{
TRACE_EVENT("gpu,startup", "ui::ozone::GetSupportedFormatsForTexturing");
supported_buffer_formats_for_texturing =
ui::OzonePlatform::GetInstance()
->GetSurfaceFactoryOzone()
->GetSupportedFormatsForTexturing();
}
std::vector<viz::SharedImageFormat>
supported_formats_for_gl_native_pixmap_import =
ui::OzonePlatform::GetInstance()
->GetSurfaceFactoryOzone()
->GetSupportedFormatsForGLNativePixmapImport();
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
if (!gl_disabled && !gl_use_swiftshader_) {
if (!CollectGraphicsInfo(&gpu_info_)) {
return false;
}
SetKeysForCrashLogging(gpu_info_);
gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
command_line, nullptr);
gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
command_line, gpu_feature_info_,
gpu_preferences_.disable_software_rasterizer, false);
if (gl_use_swiftshader_) {
VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly "
<< "on Linux";
return false;
}
}
#endif
if (gl_use_swiftshader_) {
AdjustInfoToSwiftShader();
}
if (kGpuFeatureStatusEnabled !=
gpu_feature_info_
.status_values[GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE]) {
gpu_preferences_.disable_accelerated_video_decode = true;
}
if (kGpuFeatureStatusEnabled !=
gpu_feature_info_
.status_values[GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE]) {
gpu_preferences_.disable_accelerated_video_encode = true;
}
bool recreate_watchdog = false;
if (!gl_use_swiftshader_ && command_line->HasSwitch(switches::kUseGL)) {
std::string use_gl = command_line->GetSwitchValueASCII(switches::kUseGL);
std::string use_angle =
command_line->GetSwitchValueASCII(switches::kUseANGLE);
if (use_gl == gl::kGLImplementationANGLEName &&
(use_angle == gl::kANGLEImplementationSwiftShaderName ||
use_angle == gl::kANGLEImplementationSwiftShaderForWebGLName)) {
gl_use_swiftshader_ = true;
if (watchdog_thread_) {
recreate_watchdog = true;
}
}
}
#if BUILDFLAG(IS_LINUX) || \
(BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_CHROMEOS_DEVICE))
if (!gl_disabled && !gl_use_swiftshader_ && std::getenv("RUNNING_UNDER_RR")) {
gl_use_swiftshader_ = true;
if (watchdog_thread_) {
recreate_watchdog = true;
}
}
#endif
gpu_info_.gl_implementation_parts = gl::GetGLImplementationParts();
bool software_rendering = false;
if (gl_use_swiftshader_ ||
gl::IsSoftwareGLImplementation(gl::GetGLImplementationParts())) {
software_rendering = true;
} else if (gl_disabled) {
DCHECK(!recreate_watchdog);
watchdog_thread_ = nullptr;
watchdog_init.SetGpuWatchdogPtr(nullptr);
} else if (enable_watchdog && delayed_watchdog_enable) {
recreate_watchdog = true;
}
if (recreate_watchdog) {
watchdog_thread_ = nullptr;
watchdog_init.SetGpuWatchdogPtr(nullptr);
watchdog_thread_ =
GpuWatchdogThread::Create(gpu_preferences_.watchdog_starts_backgrounded,
software_rendering, "GpuWatchdog");
watchdog_init.SetGpuWatchdogPtr(watchdog_thread_.get());
}
if (!gpu_info_.sandboxed && !attempted_startsandbox) {
gpu_info_.sandboxed = sandbox_helper_->EnsureSandboxInitialized(
watchdog_thread_.get(), &gpu_info_, gpu_preferences_);
}
InitializeDawnProcs();
if (gpu_preferences_.gr_context_type == GrContextType::kGraphiteDawn) {
if (!InitializeDawn()) {
auto& graphite_feature =
gpu_feature_info_.status_values[GPU_FEATURE_TYPE_SKIA_GRAPHITE];
#if BUILDFLAG(IS_ANDROID)
if (graphite_feature == kGpuFeatureStatusEnabled) {
graphite_feature = kGpuFeatureStatusDisabled;
}
#else
if (graphite_feature == kGpuFeatureStatusEnabled) {
return false;
}
#endif
gpu_preferences_.gr_context_type = GrContextType::kGL;
}
}
#if BUILDFLAG(IS_WIN)
{
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device;
if (dawn_context_provider_) {
d3d11_device = dawn_context_provider_->GetD3D11Device();
} else {
d3d11_device = gl::QueryD3D11DeviceObjectFromANGLE();
}
gl::InitializeDirectComposition(std::move(d3d11_device));
}
#endif
InitializePlatformOverlaySettings(&gpu_info_, gpu_feature_info_);
init_successful_ = true;
SetSkiaBackendType();
#if BUILDFLAG(IS_OZONE)
ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
gpu_feature_info_.supported_buffer_formats_for_allocation_and_texturing =
std::move(supported_buffer_formats_for_texturing);
gpu_feature_info_.supported_formats_for_gl_native_pixmap_import =
std::move(supported_formats_for_gl_native_pixmap_import);
[[maybe_unused]] auto* factory =
ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone();
bool filter_set = false;
#if BUILDFLAG(ENABLE_VULKAN)
if (gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] ==
kGpuFeatureStatusEnabled &&
factory->SupportsDrmModifiersFilter()) {
CHECK(!filter_set);
DCHECK(vulkan_implementation_ &&
vulkan_implementation_->GetVulkanInstance() &&
vulkan_implementation_->GetVulkanInstance()->vk_instance() !=
VK_NULL_HANDLE);
factory->SetDrmModifiersFilter(std::make_unique<DrmModifiersFilterVulkan>(
vulkan_implementation_.get()));
filter_set = true;
}
#endif
#if BUILDFLAG(SKIA_USE_DAWN) && BUILDFLAG(IS_CHROMEOS)
if (dawn_context_provider_ && factory->SupportsDrmModifiersFilter()) {
CHECK(!filter_set);
factory->SetDrmModifiersFilter(std::make_unique<DrmModifiersFilterDawn>(
dawn_context_provider_->GetDevice().GetAdapter()));
filter_set = true;
}
#endif
#endif
RecordUMA();
if (!watchdog_thread_) {
watchdog_init.SetGpuWatchdogPtr(nullptr);
}
#if !BUILDFLAG(IS_MAC)
if (gpu_feature_info_.IsWorkaroundEnabled(CHECK_EGL_FENCE_BEFORE_WAIT)) {
gl::GLFenceEGL::CheckEGLFenceBeforeWait();
}
if (gpu_feature_info_.IsWorkaroundEnabled(FLUSH_BEFORE_CREATE_FENCE)) {
gl::GLFenceEGL::FlushBeforeCreateFence();
}
#endif
return true;
}
void GpuInit::InitializeInProcess(base::CommandLine* command_line,
const GpuPreferences& gpu_preferences) {
#if BUILDFLAG(ARKWEB_GL_INIT)
TRACE_EVENT0("startup", "GpuInit::InitializeInProcess");
#endif
gpu_preferences_ = gpu_preferences;
init_successful_ = true;
#if BUILDFLAG(IS_ANDROID)
DCHECK(!EnableSwiftShaderIfNeeded(
command_line, gpu_feature_info_,
gpu_preferences_.disable_software_rasterizer, false));
gl::GLDisplay* gl_display = InitializeGLThreadSafe(
command_line, gpu_preferences_, &gpu_info_, &gpu_feature_info_);
if (!gl_display) {
LOG(FATAL) << "gpu::InitializeGLThreadSafe() failed.";
}
if (command_line->HasSwitch(switches::kWebViewDrawFunctorUsesVulkan)) {
bool result = InitializeVulkan();
CHECK(result);
} else {
DisableInProcessGpuVulkan(&gpu_feature_info_, &gpu_preferences_);
DisableInProcessGpuGraphite(gpu_feature_info_, gpu_preferences_);
}
default_offscreen_surface_ =
gl::init::CreateOffscreenGLSurface(gl_display, gfx::Size());
#else
#if BUILDFLAG(IS_OZONE)
ui::OzonePlatform::InitParams params;
params.single_process = true;
params.handle_overlays_swap_failure =
base::FeatureList::IsEnabled(features::kHandleOverlaysSwapFailure);
#if BUILDFLAG(IS_CHROMEOS)
params.allow_sync_and_real_buffer_page_flip_testing = true;
#endif
ui::OzonePlatform::InitializeForGPU(params);
#endif
bool needs_more_info = true;
#if !BUILDFLAG(IS_CASTOS) && !BUILDFLAG(IS_CAST_ANDROID)
needs_more_info = false;
CollectBasicGraphicsInfo(command_line, &gpu_info_);
#if defined(SUBPIXEL_FONT_RENDERING_DISABLED)
gpu_info_.subpixel_font_rendering = false;
#else
gpu_info_.subpixel_font_rendering = true;
#endif
gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
command_line, &needs_more_info);
if (SwitchableGPUsSupported(gpu_info_, *command_line)) {
InitializeSwitchableGPUs(
gpu_feature_info_.enabled_gpu_driver_bug_workarounds);
}
#endif
gl::GLDisplay* gl_display = nullptr;
gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
command_line, gpu_feature_info_,
gpu_preferences_.disable_software_rasterizer, needs_more_info);
gl_display = gl::init::InitializeGLNoExtensionsOneOff(
true,
gl::GpuPreference::kDefault);
if (!gl_display) {
VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
return;
}
bool gl_disabled = gl::GetGLImplementation() == gl::kGLImplementationDisabled;
#if BUILDFLAG(IS_LINUX) || \
(BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_CHROMEOS_DEVICE))
if (!gl_disabled && !gl_use_swiftshader_ && std::getenv("RUNNING_UNDER_RR")) {
gl_use_swiftshader_ = true;
}
#endif
gpu_info_.gl_implementation_parts = gl::GetGLImplementationParts();
if (!gl_disabled && !gl_use_swiftshader_) {
CollectContextGraphicsInfo(&gpu_info_);
gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
command_line, nullptr);
gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
command_line, gpu_feature_info_,
gpu_preferences_.disable_software_rasterizer, false);
if (gl_use_swiftshader_) {
SaveHardwareGpuInfoAndGpuFeatureInfo();
gl::init::ShutdownGL(gl_display, true);
gl_display = gl::init::InitializeGLNoExtensionsOneOff(
true,
gl::GpuPreference::kDefault);
if (!gl_display) {
VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed "
<< "with SwiftShader";
return;
}
}
}
if (!gl_disabled) {
if (!gpu_feature_info_.disabled_extensions.empty()) {
gl::init::SetDisabledExtensionsPlatform(
gpu_feature_info_.disabled_extensions);
}
if (!gl::init::InitializeExtensionSettingsOneOffPlatform(gl_display)) {
VLOG(1) << "gl::init::InitializeExtensionSettingsOneOffPlatform failed";
}
default_offscreen_surface_ =
gl::init::CreateOffscreenGLSurface(gl_display, gfx::Size());
if (!default_offscreen_surface_) {
VLOG(1) << "gl::init::CreateOffscreenGLSurface failed";
}
}
InitializePlatformOverlaySettings(&gpu_info_, gpu_feature_info_);
if (!gl_disabled) {
if (!CollectGpuExtraInfo(&gpu_extra_info_, gpu_preferences)) {
VLOG(1) << "gpu::CollectGpuExtraInfo failed";
}
}
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
if (!gl_disabled && !gl_use_swiftshader_) {
CollectContextGraphicsInfo(&gpu_info_);
gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
command_line, nullptr);
gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
command_line, gpu_feature_info_,
gpu_preferences_.disable_software_rasterizer, false);
if (gl_use_swiftshader_) {
SaveHardwareGpuInfoAndGpuFeatureInfo();
gl::init::ShutdownGL(gl_display, true);
gl_display = gl::init::InitializeGLNoExtensionsOneOff(
true,
gl::GpuPreference::kDefault);
if (!gl_display) {
VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed "
<< "with SwiftShader";
return;
}
}
}
#endif
if (gl_use_swiftshader_) {
AdjustInfoToSwiftShader();
}
#if BUILDFLAG(IS_OZONE)
const std::vector<gfx::BufferFormat> supported_buffer_formats_for_texturing =
ui::OzonePlatform::GetInstance()
->GetSurfaceFactoryOzone()
->GetSupportedFormatsForTexturing();
const std::vector<viz::SharedImageFormat>
supported_formats_for_gl_native_pixmap_import =
ui::OzonePlatform::GetInstance()
->GetSurfaceFactoryOzone()
->GetSupportedFormatsForGLNativePixmapImport();
gpu_feature_info_.supported_buffer_formats_for_allocation_and_texturing =
std::move(supported_buffer_formats_for_texturing);
gpu_feature_info_.supported_formats_for_gl_native_pixmap_import =
std::move(supported_formats_for_gl_native_pixmap_import);
#endif
#if BUILDFLAG(ARKWEB_VULKAN)
CHECK_IS_USING_VULKAN_AND_INITIAL()
#endif
DisableInProcessGpuVulkan(&gpu_feature_info_, &gpu_preferences_);
#if BUILDFLAG(ARKWEB_VULKAN)
}
#endif
#endif
InitializeDawnProcs();
#if !BUILDFLAG(IS_ANDROID)
if (gpu_preferences_.gr_context_type == GrContextType::kGraphiteDawn) {
if (!InitializeDawn()) {
if (gpu_feature_info_.status_values[GPU_FEATURE_TYPE_SKIA_GRAPHITE] !=
kGpuFeatureStatusEnabled) {
gpu_preferences_.gr_context_type = GrContextType::kGL;
} else {
LOG(FATAL) << "InitializeDawn() failed!";
}
}
}
#endif
SetSkiaBackendType();
RecordUMA();
}
void GpuInit::RecordUMA() {
if (gpu_preferences_.enable_perf_data_collection) {
return;
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CASTOS)
IntelGpuSeriesType intel_gpu_series_type = GetIntelGpuSeriesType(
gpu_info_.active_gpu().vendor_id, gpu_info_.active_gpu().device_id);
UMA_HISTOGRAM_ENUMERATION("GPU.IntelGpuSeriesType", intel_gpu_series_type);
#endif
UMA_HISTOGRAM_ENUMERATION("GPU.GLImplementation", gl::GetGLImplementation());
UMA_HISTOGRAM_BOOLEAN("GPU.Sandboxed", gpu_info_.sandboxed);
UMA_HISTOGRAM_ENUMERATION("GPU.SkiaBackendType", gpu_info_.skia_backend_type);
}
void GpuInit::SaveHardwareGpuInfoAndGpuFeatureInfo() {
gpu_info_for_hardware_gpu_ = gpu_info_;
gpu_feature_info_for_hardware_gpu_ = gpu_feature_info_;
}
void GpuInit::AdjustInfoToSwiftShader() {
gpu_feature_info_ = ComputeGpuFeatureInfoForSoftwareGL();
CollectContextGraphicsInfo(&gpu_info_);
}
scoped_refptr<gl::GLSurface> GpuInit::TakeDefaultOffscreenSurface() {
return std::move(default_offscreen_surface_);
}
void GpuInit::SetSkiaBackendType() {
CHECK(init_successful_);
CHECK_EQ(gpu_info_.skia_backend_type, SkiaBackendType::kNone);
auto skia_backend_type = SkiaBackendType::kUnknown;
switch (gpu_preferences_.gr_context_type) {
case gpu::GrContextType::kNone:
skia_backend_type = SkiaBackendType::kNone;
break;
case gpu::GrContextType::kGL:
skia_backend_type = SkiaBackendType::kGaneshGL;
break;
case gpu::GrContextType::kVulkan:
skia_backend_type = SkiaBackendType::kGaneshVulkan;
break;
case gpu::GrContextType::kGraphiteMetal:
skia_backend_type = SkiaBackendType::kUnknown;
break;
case gpu::GrContextType::kGraphiteDawn: {
#if BUILDFLAG(SKIA_USE_DAWN)
CHECK(dawn_context_provider_);
switch (dawn_context_provider_->backend_type()) {
case wgpu::BackendType::Vulkan:
skia_backend_type = SkiaBackendType::kGraphiteDawnVulkan;
break;
case wgpu::BackendType::D3D11:
skia_backend_type = SkiaBackendType::kGraphiteDawnD3D11;
break;
case wgpu::BackendType::D3D12:
skia_backend_type = SkiaBackendType::kGraphiteDawnD3D12;
break;
case wgpu::BackendType::Metal:
skia_backend_type = SkiaBackendType::kGraphiteDawnMetal;
break;
default:
break;
}
break;
#else
NOTREACHED();
#endif
}
}
gpu_info_.skia_backend_type = skia_backend_type;
static crash_reporter::CrashKeyString<24> crash_key("gr-context-type");
crash_key.Set(SkiaBackendTypeToString(skia_backend_type));
}
bool GpuInit::InitializeDawn() {
#if BUILDFLAG(SKIA_USE_DAWN)
TRACE_EVENT("gpu,startup", "gpu::GpuInit::InitializeDawn");
if (gpu_feature_info_.status_values[GPU_FEATURE_TYPE_SKIA_GRAPHITE] !=
kGpuFeatureStatusEnabled &&
!gpu::DawnContextProvider::DefaultForceFallbackAdapter()) {
return false;
}
#if BUILDFLAG(IS_ANDROID)
auto validate_adapter_fn = [this](wgpu::BackendType backend_type,
wgpu::Adapter adapter) {
if (backend_type == wgpu::BackendType::Vulkan) {
wgpu::AdapterInfo adapter_info;
wgpu::AdapterPropertiesVk adapter_properties_vk;
adapter_info.nextInChain = &adapter_properties_vk;
adapter.GetInfo(&adapter_info);
VulkanPhysicalDeviceProperties device_properties;
device_properties.device_name = adapter_info.device;
device_properties.vendor_id = adapter_info.vendorID;
device_properties.device_id = adapter_info.deviceID;
device_properties.driver_version = adapter_properties_vk.driverVersion;
if (!CheckVulkanCompatibilities(device_properties, gpu_info_)) {
return false;
}
gpu_info_.hardware_supports_vulkan = true;
gpu_info_.gpu.vendor_id = device_properties.vendor_id;
gpu_info_.gpu.device_id = device_properties.device_id;
}
return true;
};
#else
auto validate_adapter_fn = DawnContextProvider::DefaultValidateAdapterFn;
#endif
static BASE_FEATURE(kGraphiteDawnReportWorkerTaskProgressToWatchdog,
"GraphiteDawnReportWorkerTaskProgressToWatchdog",
base::FEATURE_ENABLED_BY_DEFAULT);
gl::ProgressReporter* progress_reporter = nullptr;
if (base::FeatureList::IsEnabled(
kGraphiteDawnReportWorkerTaskProgressToWatchdog)) {
progress_reporter = watchdog_thread_.get();
}
dawn_context_provider_ =
DawnContextProvider::Create(gpu_preferences_, gpu_feature_info_,
progress_reporter, validate_adapter_fn);
if (dawn_context_provider_) {
return true;
}
#endif
LOG(ERROR) << "Failed to create Dawn context provider for Graphite";
return false;
}
bool GpuInit::InitializeVulkan() {
#if BUILDFLAG(ENABLE_VULKAN)
#if BUILDFLAG(ARKWEB_VULKAN)
if (!features::IsUsingVulkan()) {
return false;
}
#endif
TRACE_EVENT("gpu,startup", "gpu::GpuInit::InitializeVulkan");
DCHECK(gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] ==
kGpuFeatureStatusEnabled ||
gpu_feature_info_
.status_values[GPU_FEATURE_TYPE_WEBGPU_ON_VK_VIA_GL_INTEROP] ==
kGpuFeatureStatusEnabled);
DCHECK_NE(gpu_preferences_.use_vulkan, VulkanImplementationName::kNone);
bool vulkan_use_swiftshader =
gpu_preferences_.use_vulkan == VulkanImplementationName::kSwiftshader;
bool forced_native =
gpu_preferences_.use_vulkan == VulkanImplementationName::kForcedNative;
bool use_swiftshader = gl_use_swiftshader_ || vulkan_use_swiftshader;
if (!use_swiftshader && !forced_native) {
const base::FeatureParam<std::string> disable_by_renderer(
&features::kVulkan, "disable_by_gl_renderer", "");
if (MatchGLInfo(gpu_info_.gl_renderer, disable_by_renderer.Get())) {
return false;
}
}
vulkan_implementation_ = CreateVulkanImplementation(
vulkan_use_swiftshader, gpu_preferences_.enable_vulkan_protected_memory);
if (!vulkan_implementation_ ||
!vulkan_implementation_->InitializeVulkanInstance(
!gpu_preferences_.disable_vulkan_surface)) {
LOG(ERROR) << "Failed to create and initialize Vulkan implementation.";
vulkan_implementation_ = nullptr;
CHECK(!gpu_preferences_.disable_vulkan_fallback_to_gl_for_testing);
}
if (!vulkan_implementation_) {
return false;
}
auto& vulkan_info =
vulkan_implementation_->GetVulkanInstance()->vulkan_info();
if (vulkan_info.physical_devices.empty()) {
return false;
}
VulkanPhysicalDeviceProperties device_properties(
vulkan_info.physical_devices.front().properties);
if (!use_swiftshader && !forced_native &&
!CheckVulkanCompatibilities(device_properties, gpu_info_)) {
vulkan_implementation_.reset();
return false;
}
gpu_info_.hardware_supports_vulkan = true;
gpu_info_.vulkan_info =
vulkan_implementation_->GetVulkanInstance()->vulkan_info();
#if BUILDFLAG(IS_ANDROID)
gpu_info_.gpu.vendor_id = device_properties.vendor_id;
gpu_info_.gpu.device_id = device_properties.device_id;
#endif
return true;
#else
return false;
#endif
}
}