blob: 1417f94839fb6dc80a7d1302db2c4aeb43a3416d [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/command_buffer/service/dawn_instance.h"
#include <dawn/webgpu_cpp.h>
#include "base/base_paths.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/strings/string_split.h"
#include "build/buildflag.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_preferences.h"
#if BUILDFLAG(IS_MAC)
#include "base/apple/bundle_locations.h"
#include "base/apple/foundation_util.h"
#endif
namespace gpu::webgpu {
// static
std::unique_ptr<DawnInstance> DawnInstance::Create(
dawn::platform::Platform* platform,
const GpuPreferences& gpu_preferences,
SafetyLevel safety,
dawn::native::DawnInstanceDescriptor* dawn_instance_descriptor) {
// Populate the WGSL blocklist based on the Finch feature.
std::vector<std::string> wgsl_unsafe_features_owned;
std::vector<const char*> wgsl_unsafe_features;
if (safety != SafetyLevel::kUnsafe) {
wgsl_unsafe_features_owned =
base::SplitString(features::kWGSLUnsafeFeatures.Get(), ",",
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
wgsl_unsafe_features.reserve(wgsl_unsafe_features_owned.size());
for (const auto& f : wgsl_unsafe_features_owned) {
wgsl_unsafe_features.push_back(f.c_str());
}
}
wgpu::DawnWGSLBlocklist wgsl_blocklist;
wgsl_blocklist.nextInChain = nullptr;
wgsl_blocklist.blocklistedFeatureCount = wgsl_unsafe_features.size();
wgsl_blocklist.blocklistedFeatures = wgsl_unsafe_features.data();
// Populate the instance toggles becaused on command line parameters and
// safety levels. Toggles which are not instance toggles will be ignored by
// the instance.
std::vector<const char*> require_instance_enabled_toggles;
std::vector<const char*> require_instance_disabled_toggles;
if (safety == SafetyLevel::kSafeExperimental) {
require_instance_enabled_toggles.push_back(
"expose_wgsl_experimental_features");
} else if (safety == SafetyLevel::kUnsafe) {
require_instance_enabled_toggles.push_back("allow_unsafe_apis");
}
for (const std::string& toggles :
gpu_preferences.enabled_dawn_features_list) {
require_instance_enabled_toggles.push_back(toggles.c_str());
}
for (const std::string& toggles :
gpu_preferences.disabled_dawn_features_list) {
require_instance_disabled_toggles.push_back(toggles.c_str());
}
wgpu::DawnTogglesDescriptor dawn_toggle_desc;
dawn_toggle_desc.nextInChain = &wgsl_blocklist;
dawn_toggle_desc.enabledToggleCount = require_instance_enabled_toggles.size();
dawn_toggle_desc.enabledToggles = require_instance_enabled_toggles.data();
dawn_toggle_desc.disabledToggleCount =
require_instance_disabled_toggles.size();
dawn_toggle_desc.disabledToggles = require_instance_disabled_toggles.data();
// Use DawnInstanceDescriptor to pass in the platform and additional search
// paths
std::string dawn_search_path;
base::FilePath module_path;
#if BUILDFLAG(IS_MAC)
if (base::apple::AmIBundled()) {
dawn_search_path = base::apple::FrameworkBundlePath()
.Append("Libraries")
.AsEndingWithSeparator()
.MaybeAsASCII();
}
if (dawn_search_path.empty())
#endif
{
#if BUILDFLAG(IS_IOS)
if (base::PathService::Get(base::DIR_ASSETS, &module_path)) {
#else
if (base::PathService::Get(base::DIR_MODULE, &module_path)) {
#endif
dawn_search_path = module_path.AsEndingWithSeparator().MaybeAsASCII();
}
}
const char* dawn_search_path_c_str = dawn_search_path.c_str();
dawn::native::DawnInstanceDescriptor dawn_instance_desc;
if (dawn_instance_descriptor) {
dawn_instance_desc = *dawn_instance_descriptor;
}
dawn_instance_desc.nextInChain = &dawn_toggle_desc;
dawn_instance_desc.additionalRuntimeSearchPathsCount =
dawn_search_path.empty() ? 0u : 1u;
dawn_instance_desc.additionalRuntimeSearchPaths = &dawn_search_path_c_str;
dawn_instance_desc.platform = platform;
// Create the instance with all the previous descriptors chained.
wgpu::InstanceDescriptor instance_desc;
instance_desc.nextInChain = &dawn_instance_desc;
static constexpr auto kInstanceFeatures = std::array{
wgpu::InstanceFeatureName::MultipleDevicesPerAdapter,
wgpu::InstanceFeatureName::TimedWaitAny,
};
instance_desc.requiredFeatureCount = kInstanceFeatures.size();
instance_desc.requiredFeatures = kInstanceFeatures.data();
auto instance = std::make_unique<DawnInstance>(
reinterpret_cast<const WGPUInstanceDescriptor*>(&instance_desc));
switch (gpu_preferences.enable_dawn_backend_validation) {
case DawnBackendValidationLevel::kDisabled:
break;
case DawnBackendValidationLevel::kPartial:
instance->SetBackendValidationLevel(
dawn::native::BackendValidationLevel::Partial);
break;
case DawnBackendValidationLevel::kFull:
instance->SetBackendValidationLevel(
dawn::native::BackendValidationLevel::Full);
break;
}
return instance;
}
} // namespace gpu::webgpu