1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144

gpu / command_buffer / service / dawn_instance.cc [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,
#ifdef WGPU_BREAKING_CHANGE_LOGGING_CALLBACK_TYPE
    wgpu::LoggingCallback<void> logging_callback) {
#else
    WGPULoggingCallback logging_callback,
    void* logging_callback_userdata) {
#endif
  // 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;
  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;
#ifdef WGPU_BREAKING_CHANGE_LOGGING_CALLBACK_TYPE
  dawn_instance_desc.SetLoggingCallback(logging_callback);
#else
  dawn_instance_desc.loggingCallback = logging_callback;
  dawn_instance_desc.loggingCallbackUserdata = logging_callback_userdata;
#endif

  // Create the instance with all the previous descriptors chained.
  wgpu::InstanceDescriptor instance_desc;
  instance_desc.nextInChain = &dawn_instance_desc;
  instance_desc.features.timedWaitAnyEnable = true;

  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