Support multiple Vulkan instances in the Vulkan backend
This will allow the Vulkan backend connection to be initialized, and then selectively discover adapters on just one of the instances. This is needed so that discovery of the fallback WebGPU adapter can avoid initializing any adapters other than SwiftShader. Bug: chromium:1266550 Change-Id: Ia8b31c0239da89a41aa89f1c09a66e9e56e10d95 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/69980 Reviewed-by: Loko Kung <lokokung@google.com> Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
1a57ee9d4e
commit
652293f14c
|
@ -96,6 +96,9 @@ namespace dawn_native {
|
||||||
// gracefully shut down.
|
// gracefully shut down.
|
||||||
#define DAWN_INTERNAL_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::Internal, MESSAGE)
|
#define DAWN_INTERNAL_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::Internal, MESSAGE)
|
||||||
|
|
||||||
|
#define DAWN_FORMAT_INTERNAL_ERROR(...) \
|
||||||
|
DAWN_MAKE_ERROR(InternalErrorType::Internal, absl::StrFormat(__VA_ARGS__))
|
||||||
|
|
||||||
#define DAWN_UNIMPLEMENTED_ERROR(MESSAGE) \
|
#define DAWN_UNIMPLEMENTED_ERROR(MESSAGE) \
|
||||||
DAWN_MAKE_ERROR(InternalErrorType::Internal, std::string("Unimplemented: ") + MESSAGE)
|
DAWN_MAKE_ERROR(InternalErrorType::Internal, std::string("Unimplemented: ") + MESSAGE)
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace dawn_native {
|
||||||
#endif // defined(DAWN_ENABLE_BACKEND_OPENGL)
|
#endif // defined(DAWN_ENABLE_BACKEND_OPENGL)
|
||||||
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
|
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
|
||||||
namespace vulkan {
|
namespace vulkan {
|
||||||
BackendConnection* Connect(InstanceBase* instance, bool useSwiftshader);
|
BackendConnection* Connect(InstanceBase* instance);
|
||||||
}
|
}
|
||||||
#endif // defined(DAWN_ENABLE_BACKEND_VULKAN)
|
#endif // defined(DAWN_ENABLE_BACKEND_VULKAN)
|
||||||
|
|
||||||
|
@ -187,16 +187,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
|
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
|
||||||
case wgpu::BackendType::Vulkan:
|
case wgpu::BackendType::Vulkan:
|
||||||
// TODO(https://github.com/KhronosGroup/Vulkan-Loader/issues/287):
|
Register(vulkan::Connect(this), wgpu::BackendType::Vulkan);
|
||||||
// When we can load SwiftShader in parallel with the system driver, we should
|
|
||||||
// create the backend only once and expose SwiftShader as an additional adapter.
|
|
||||||
// For now, we create two VkInstances, one from SwiftShader, and one from the
|
|
||||||
// system. Note: If the Vulkan driver *is* SwiftShader, then this would load
|
|
||||||
// SwiftShader twice.
|
|
||||||
Register(vulkan::Connect(this, false), wgpu::BackendType::Vulkan);
|
|
||||||
# if defined(DAWN_ENABLE_SWIFTSHADER)
|
|
||||||
Register(vulkan::Connect(this, true), wgpu::BackendType::Vulkan);
|
|
||||||
# endif // defined(DAWN_ENABLE_SWIFTSHADER)
|
|
||||||
break;
|
break;
|
||||||
#endif // defined(DAWN_ENABLE_BACKEND_VULKAN)
|
#endif // defined(DAWN_ENABLE_BACKEND_VULKAN)
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,12 @@
|
||||||
|
|
||||||
namespace dawn_native { namespace vulkan {
|
namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
Adapter::Adapter(Backend* backend, VkPhysicalDevice physicalDevice)
|
Adapter::Adapter(InstanceBase* instance,
|
||||||
: AdapterBase(backend->GetInstance(), wgpu::BackendType::Vulkan),
|
VulkanInstance* vulkanInstance,
|
||||||
|
VkPhysicalDevice physicalDevice)
|
||||||
|
: AdapterBase(instance, wgpu::BackendType::Vulkan),
|
||||||
mPhysicalDevice(physicalDevice),
|
mPhysicalDevice(physicalDevice),
|
||||||
mBackend(backend) {
|
mVulkanInstance(vulkanInstance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const VulkanDeviceInfo& Adapter::GetDeviceInfo() const {
|
const VulkanDeviceInfo& Adapter::GetDeviceInfo() const {
|
||||||
|
@ -36,8 +38,8 @@ namespace dawn_native { namespace vulkan {
|
||||||
return mPhysicalDevice;
|
return mPhysicalDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
Backend* Adapter::GetBackend() const {
|
VulkanInstance* Adapter::GetVulkanInstance() const {
|
||||||
return mBackend;
|
return mVulkanInstance.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Adapter::IsDepthStencilFormatSupported(VkFormat format) {
|
bool Adapter::IsDepthStencilFormatSupported(VkFormat format) {
|
||||||
|
@ -45,7 +47,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
format == VK_FORMAT_D32_SFLOAT_S8_UINT);
|
format == VK_FORMAT_D32_SFLOAT_S8_UINT);
|
||||||
|
|
||||||
VkFormatProperties properties;
|
VkFormatProperties properties;
|
||||||
GetBackend()->GetFunctions().GetPhysicalDeviceFormatProperties(mPhysicalDevice, format,
|
mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(mPhysicalDevice, format,
|
||||||
&properties);
|
&properties);
|
||||||
return properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
return properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||||
}
|
}
|
||||||
|
@ -327,7 +329,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
// Via dawn_native::vulkan::WrapVulkanImage
|
// Via dawn_native::vulkan::WrapVulkanImage
|
||||||
return external_memory::Service::CheckSupport(mDeviceInfo) &&
|
return external_memory::Service::CheckSupport(mDeviceInfo) &&
|
||||||
external_semaphore::Service::CheckSupport(mDeviceInfo, mPhysicalDevice,
|
external_semaphore::Service::CheckSupport(mDeviceInfo, mPhysicalDevice,
|
||||||
mBackend->GetFunctions());
|
mVulkanInstance->GetFunctions());
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DawnDeviceDescriptor* descriptor) {
|
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DawnDeviceDescriptor* descriptor) {
|
||||||
|
|
|
@ -17,16 +17,19 @@
|
||||||
|
|
||||||
#include "dawn_native/Adapter.h"
|
#include "dawn_native/Adapter.h"
|
||||||
|
|
||||||
|
#include "common/RefCounted.h"
|
||||||
#include "common/vulkan_platform.h"
|
#include "common/vulkan_platform.h"
|
||||||
#include "dawn_native/vulkan/VulkanInfo.h"
|
#include "dawn_native/vulkan/VulkanInfo.h"
|
||||||
|
|
||||||
namespace dawn_native { namespace vulkan {
|
namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
class Backend;
|
class VulkanInstance;
|
||||||
|
|
||||||
class Adapter : public AdapterBase {
|
class Adapter : public AdapterBase {
|
||||||
public:
|
public:
|
||||||
Adapter(Backend* backend, VkPhysicalDevice physicalDevice);
|
Adapter(InstanceBase* instance,
|
||||||
|
VulkanInstance* vulkanInstance,
|
||||||
|
VkPhysicalDevice physicalDevice);
|
||||||
~Adapter() override = default;
|
~Adapter() override = default;
|
||||||
|
|
||||||
// AdapterBase Implementation
|
// AdapterBase Implementation
|
||||||
|
@ -34,7 +37,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
const VulkanDeviceInfo& GetDeviceInfo() const;
|
const VulkanDeviceInfo& GetDeviceInfo() const;
|
||||||
VkPhysicalDevice GetPhysicalDevice() const;
|
VkPhysicalDevice GetPhysicalDevice() const;
|
||||||
Backend* GetBackend() const;
|
VulkanInstance* GetVulkanInstance() const;
|
||||||
|
|
||||||
bool IsDepthStencilFormatSupported(VkFormat format);
|
bool IsDepthStencilFormatSupported(VkFormat format);
|
||||||
|
|
||||||
|
@ -47,7 +50,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
const DawnDeviceDescriptor* descriptor) override;
|
const DawnDeviceDescriptor* descriptor) override;
|
||||||
|
|
||||||
VkPhysicalDevice mPhysicalDevice;
|
VkPhysicalDevice mPhysicalDevice;
|
||||||
Backend* mBackend;
|
Ref<VulkanInstance> mVulkanInstance;
|
||||||
VulkanDeviceInfo mDeviceInfo = {};
|
VulkanDeviceInfo mDeviceInfo = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,13 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
static constexpr ICD kICDs[] = {
|
||||||
|
ICD::None,
|
||||||
|
#if defined(DAWN_ENABLE_SWIFTSHADER)
|
||||||
|
ICD::SwiftShader,
|
||||||
|
#endif // defined(DAWN_ENABLE_SWIFTSHADER)
|
||||||
|
};
|
||||||
|
|
||||||
VKAPI_ATTR VkBool32 VKAPI_CALL
|
VKAPI_ATTR VkBool32 VKAPI_CALL
|
||||||
OnDebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
OnDebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||||
VkDebugUtilsMessageTypeFlagsEXT /* messageTypes */,
|
VkDebugUtilsMessageTypeFlagsEXT /* messageTypes */,
|
||||||
|
@ -81,11 +88,9 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
Backend::Backend(InstanceBase* instance)
|
VulkanInstance::VulkanInstance() = default;
|
||||||
: BackendConnection(instance, wgpu::BackendType::Vulkan) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Backend::~Backend() {
|
VulkanInstance::~VulkanInstance() {
|
||||||
if (mDebugUtilsMessenger != VK_NULL_HANDLE) {
|
if (mDebugUtilsMessenger != VK_NULL_HANDLE) {
|
||||||
mFunctions.DestroyDebugUtilsMessengerEXT(mInstance, mDebugUtilsMessenger, nullptr);
|
mFunctions.DestroyDebugUtilsMessengerEXT(mInstance, mDebugUtilsMessenger, nullptr);
|
||||||
mDebugUtilsMessenger = VK_NULL_HANDLE;
|
mDebugUtilsMessenger = VK_NULL_HANDLE;
|
||||||
|
@ -98,21 +103,36 @@ namespace dawn_native { namespace vulkan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const VulkanFunctions& Backend::GetFunctions() const {
|
const VulkanFunctions& VulkanInstance::GetFunctions() const {
|
||||||
return mFunctions;
|
return mFunctions;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkInstance Backend::GetVkInstance() const {
|
VkInstance VulkanInstance::GetVkInstance() const {
|
||||||
return mInstance;
|
return mInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VulkanGlobalInfo& Backend::GetGlobalInfo() const {
|
const VulkanGlobalInfo& VulkanInstance::GetGlobalInfo() const {
|
||||||
return mGlobalInfo;
|
return mGlobalInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Backend::LoadVulkan(bool useSwiftshader) {
|
const std::vector<VkPhysicalDevice>& VulkanInstance::GetPhysicalDevices() const {
|
||||||
// First try to load the system Vulkan driver, if that fails, try to load with Swiftshader.
|
return mPhysicalDevices;
|
||||||
// Note: The system driver could potentially be Swiftshader if it was installed.
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
ResultOrError<Ref<VulkanInstance>> VulkanInstance::Create(const InstanceBase* instance,
|
||||||
|
ICD icd) {
|
||||||
|
Ref<VulkanInstance> vulkanInstance = AcquireRef(new VulkanInstance());
|
||||||
|
DAWN_TRY(vulkanInstance->Initialize(instance, icd));
|
||||||
|
return std::move(vulkanInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
MaybeError VulkanInstance::Initialize(const InstanceBase* instance, ICD icd) {
|
||||||
|
// These environment variables need only be set while loading procs and gathering device
|
||||||
|
// info.
|
||||||
|
ScopedEnvironmentVar vkICDFilenames;
|
||||||
|
ScopedEnvironmentVar vkLayerPath;
|
||||||
|
|
||||||
#if defined(DAWN_ENABLE_VULKAN_LOADER)
|
#if defined(DAWN_ENABLE_VULKAN_LOADER)
|
||||||
// If enabled, we use our own built Vulkan loader by specifying an absolute path to the
|
// If enabled, we use our own built Vulkan loader by specifying an absolute path to the
|
||||||
// shared library. Note that when we are currently getting the absolute path for the custom
|
// shared library. Note that when we are currently getting the absolute path for the custom
|
||||||
|
@ -126,49 +146,48 @@ namespace dawn_native { namespace vulkan {
|
||||||
#else
|
#else
|
||||||
const std::string resolvedVulkanLibPath = kVulkanLibName;
|
const std::string resolvedVulkanLibPath = kVulkanLibName;
|
||||||
#endif // defined(DAWN_ENABLE_VULKAN_LOADER)
|
#endif // defined(DAWN_ENABLE_VULKAN_LOADER)
|
||||||
if (mVulkanLib.Open(resolvedVulkanLibPath)) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
dawn::WarningLog() << std::string("Couldn't open ") + resolvedVulkanLibPath;
|
|
||||||
|
|
||||||
// If |useSwiftshader == true|, fallback and try to directly load the Swiftshader
|
switch (icd) {
|
||||||
// library.
|
case ICD::None: {
|
||||||
if (useSwiftshader) {
|
if (!mVulkanLib.Open(resolvedVulkanLibPath)) {
|
||||||
|
return DAWN_FORMAT_INTERNAL_ERROR("Couldn't load %s.", resolvedVulkanLibPath);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ICD::SwiftShader: {
|
||||||
#if defined(DAWN_ENABLE_SWIFTSHADER)
|
#if defined(DAWN_ENABLE_SWIFTSHADER)
|
||||||
if (mVulkanLib.Open(kSwiftshaderLibName)) {
|
// First try to load the system Vulkan driver, if that fails, try to load with
|
||||||
return {};
|
// Swiftshader. Note: The system driver could potentially be Swiftshader if it was
|
||||||
}
|
// installed.
|
||||||
dawn::WarningLog() << std::string("Couldn't open ") + kSwiftshaderLibName;
|
|
||||||
#else
|
|
||||||
UNREACHABLE();
|
|
||||||
#endif // defined(DAWN_ENABLE_SWIFTSHADER)
|
|
||||||
}
|
|
||||||
|
|
||||||
return DAWN_INTERNAL_ERROR("Couldn't load Vulkan");
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError Backend::Initialize(bool useSwiftshader) {
|
|
||||||
DAWN_TRY(LoadVulkan(useSwiftshader));
|
|
||||||
|
|
||||||
// These environment variables need only be set while loading procs and gathering device
|
|
||||||
// info.
|
|
||||||
ScopedEnvironmentVar vkICDFilenames;
|
|
||||||
ScopedEnvironmentVar vkLayerPath;
|
|
||||||
|
|
||||||
if (useSwiftshader) {
|
|
||||||
# if defined(DAWN_SWIFTSHADER_VK_ICD_JSON)
|
# if defined(DAWN_SWIFTSHADER_VK_ICD_JSON)
|
||||||
|
if (mVulkanLib.Open(resolvedVulkanLibPath)) {
|
||||||
std::string fullSwiftshaderICDPath =
|
std::string fullSwiftshaderICDPath =
|
||||||
GetExecutableDirectory() + DAWN_SWIFTSHADER_VK_ICD_JSON;
|
GetExecutableDirectory() + DAWN_SWIFTSHADER_VK_ICD_JSON;
|
||||||
if (!vkICDFilenames.Set("VK_ICD_FILENAMES", fullSwiftshaderICDPath.c_str())) {
|
if (!vkICDFilenames.Set("VK_ICD_FILENAMES", fullSwiftshaderICDPath.c_str())) {
|
||||||
return DAWN_INTERNAL_ERROR("Couldn't set VK_ICD_FILENAMES");
|
return DAWN_FORMAT_INTERNAL_ERROR("Couldn't set VK_ICD_FILENAMES to %s.",
|
||||||
|
fullSwiftshaderICDPath);
|
||||||
|
}
|
||||||
|
// Succesfully loaded driver and set VK_ICD_FILENAMES.
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
# endif // defined(DAWN_SWIFTSHADER_VK_ICD_JSON)
|
||||||
|
// Fallback to loading SwiftShader directly.
|
||||||
|
if (mVulkanLib.Open(kSwiftshaderLibName)) {
|
||||||
|
// Succesfully loaded SwiftShader.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return DAWN_FORMAT_INTERNAL_ERROR(
|
||||||
|
"Failed to load SwiftShader. DAWN_SWIFTSHADER_VK_ICD_JSON was not defined and "
|
||||||
|
"could not load %s.",
|
||||||
|
kSwiftshaderLibName);
|
||||||
|
#endif // defined(DAWN_ENABLE_SWIFTSHADER)
|
||||||
|
|
||||||
|
// ICD::SwiftShader should not be passed if SwiftShader is not enabled.
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
dawn::WarningLog() << "Swiftshader enabled but Dawn was not built with "
|
|
||||||
"DAWN_SWIFTSHADER_VK_ICD_JSON.";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetInstance()->IsBackendValidationEnabled()) {
|
if (instance->IsBackendValidationEnabled()) {
|
||||||
#if defined(DAWN_ENABLE_VULKAN_VALIDATION_LAYERS)
|
#if defined(DAWN_ENABLE_VULKAN_VALIDATION_LAYERS)
|
||||||
std::string vkDataDir = GetExecutableDirectory() + DAWN_VK_DATA_DIR;
|
std::string vkDataDir = GetExecutableDirectory() + DAWN_VK_DATA_DIR;
|
||||||
if (!vkLayerPath.Set("VK_LAYER_PATH", vkDataDir.c_str())) {
|
if (!vkLayerPath.Set("VK_LAYER_PATH", vkDataDir.c_str())) {
|
||||||
|
@ -182,10 +201,10 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
DAWN_TRY(mFunctions.LoadGlobalProcs(mVulkanLib));
|
DAWN_TRY(mFunctions.LoadGlobalProcs(mVulkanLib));
|
||||||
|
|
||||||
DAWN_TRY_ASSIGN(mGlobalInfo, GatherGlobalInfo(*this));
|
DAWN_TRY_ASSIGN(mGlobalInfo, GatherGlobalInfo(mFunctions));
|
||||||
|
|
||||||
VulkanGlobalKnobs usedGlobalKnobs = {};
|
VulkanGlobalKnobs usedGlobalKnobs = {};
|
||||||
DAWN_TRY_ASSIGN(usedGlobalKnobs, CreateInstance());
|
DAWN_TRY_ASSIGN(usedGlobalKnobs, CreateVkInstance(instance));
|
||||||
*static_cast<VulkanGlobalKnobs*>(&mGlobalInfo) = usedGlobalKnobs;
|
*static_cast<VulkanGlobalKnobs*>(&mGlobalInfo) = usedGlobalKnobs;
|
||||||
|
|
||||||
DAWN_TRY(mFunctions.LoadInstanceProcs(mInstance, mGlobalInfo));
|
DAWN_TRY(mFunctions.LoadInstanceProcs(mInstance, mGlobalInfo));
|
||||||
|
@ -194,28 +213,13 @@ namespace dawn_native { namespace vulkan {
|
||||||
DAWN_TRY(RegisterDebugUtils());
|
DAWN_TRY(RegisterDebugUtils());
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_TRY_ASSIGN(mPhysicalDevices, GetPhysicalDevices(*this));
|
DAWN_TRY_ASSIGN(mPhysicalDevices, GatherPhysicalDevices(mInstance, mFunctions));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() {
|
ResultOrError<VulkanGlobalKnobs> VulkanInstance::CreateVkInstance(
|
||||||
std::vector<std::unique_ptr<AdapterBase>> adapters;
|
const InstanceBase* instance) {
|
||||||
|
|
||||||
for (VkPhysicalDevice physicalDevice : mPhysicalDevices) {
|
|
||||||
std::unique_ptr<Adapter> adapter = std::make_unique<Adapter>(this, physicalDevice);
|
|
||||||
|
|
||||||
if (GetInstance()->ConsumedError(adapter->Initialize())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
adapters.push_back(std::move(adapter));
|
|
||||||
}
|
|
||||||
|
|
||||||
return adapters;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultOrError<VulkanGlobalKnobs> Backend::CreateInstance() {
|
|
||||||
VulkanGlobalKnobs usedKnobs = {};
|
VulkanGlobalKnobs usedKnobs = {};
|
||||||
std::vector<const char*> layerNames;
|
std::vector<const char*> layerNames;
|
||||||
InstanceExtSet extensionsToRequest = mGlobalInfo.extensions;
|
InstanceExtSet extensionsToRequest = mGlobalInfo.extensions;
|
||||||
|
@ -242,7 +246,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
UseLayerIfAvailable(VulkanLayer::RenderDocCapture);
|
UseLayerIfAvailable(VulkanLayer::RenderDocCapture);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (GetInstance()->IsBackendValidationEnabled()) {
|
if (instance->IsBackendValidationEnabled()) {
|
||||||
UseLayerIfAvailable(VulkanLayer::Validation);
|
UseLayerIfAvailable(VulkanLayer::Validation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +319,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
VkValidationFeaturesEXT validationFeatures;
|
VkValidationFeaturesEXT validationFeatures;
|
||||||
VkValidationFeatureEnableEXT kEnableSynchronizationValidation =
|
VkValidationFeatureEnableEXT kEnableSynchronizationValidation =
|
||||||
VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT;
|
VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT;
|
||||||
if (GetInstance()->IsBackendValidationEnabled() &&
|
if (instance->IsBackendValidationEnabled() &&
|
||||||
usedKnobs.HasExt(InstanceExt::ValidationFeatures)) {
|
usedKnobs.HasExt(InstanceExt::ValidationFeatures)) {
|
||||||
validationFeatures.enabledValidationFeatureCount = 1;
|
validationFeatures.enabledValidationFeatureCount = 1;
|
||||||
validationFeatures.pEnabledValidationFeatures = &kEnableSynchronizationValidation;
|
validationFeatures.pEnabledValidationFeatures = &kEnableSynchronizationValidation;
|
||||||
|
@ -331,7 +335,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
return usedKnobs;
|
return usedKnobs;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Backend::RegisterDebugUtils() {
|
MaybeError VulkanInstance::RegisterDebugUtils() {
|
||||||
VkDebugUtilsMessengerCreateInfoEXT createInfo;
|
VkDebugUtilsMessengerCreateInfoEXT createInfo;
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
||||||
createInfo.pNext = nullptr;
|
createInfo.pNext = nullptr;
|
||||||
|
@ -348,15 +352,41 @@ namespace dawn_native { namespace vulkan {
|
||||||
"vkCreateDebugUtilsMessengerEXT");
|
"vkCreateDebugUtilsMessengerEXT");
|
||||||
}
|
}
|
||||||
|
|
||||||
BackendConnection* Connect(InstanceBase* instance, bool useSwiftshader) {
|
Backend::Backend(InstanceBase* instance)
|
||||||
Backend* backend = new Backend(instance);
|
: BackendConnection(instance, wgpu::BackendType::Vulkan) {
|
||||||
|
|
||||||
if (instance->ConsumedError(backend->Initialize(useSwiftshader))) {
|
|
||||||
delete backend;
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return backend;
|
Backend::~Backend() = default;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() {
|
||||||
|
std::vector<std::unique_ptr<AdapterBase>> adapters;
|
||||||
|
|
||||||
|
InstanceBase* instance = GetInstance();
|
||||||
|
for (ICD icd : kICDs) {
|
||||||
|
if (mVulkanInstances[icd] == nullptr && instance->ConsumedError([&]() -> MaybeError {
|
||||||
|
DAWN_TRY_ASSIGN(mVulkanInstances[icd], VulkanInstance::Create(instance, icd));
|
||||||
|
return {};
|
||||||
|
}())) {
|
||||||
|
// Instance failed to initialize.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const std::vector<VkPhysicalDevice>& physicalDevices =
|
||||||
|
mVulkanInstances[icd]->GetPhysicalDevices();
|
||||||
|
for (uint32_t i = 0; i < physicalDevices.size(); ++i) {
|
||||||
|
std::unique_ptr<Adapter> adapter = std::make_unique<Adapter>(
|
||||||
|
instance, mVulkanInstances[icd].Get(), physicalDevices[i]);
|
||||||
|
if (instance->ConsumedError(adapter->Initialize())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
adapters.push_back(std::move(adapter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return adapters;
|
||||||
|
}
|
||||||
|
|
||||||
|
BackendConnection* Connect(InstanceBase* instance) {
|
||||||
|
return new Backend(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace dawn_native::vulkan
|
}} // namespace dawn_native::vulkan
|
||||||
|
|
|
@ -18,27 +18,41 @@
|
||||||
#include "dawn_native/BackendConnection.h"
|
#include "dawn_native/BackendConnection.h"
|
||||||
|
|
||||||
#include "common/DynamicLib.h"
|
#include "common/DynamicLib.h"
|
||||||
|
#include "common/RefCounted.h"
|
||||||
|
#include "common/ityp_array.h"
|
||||||
#include "dawn_native/vulkan/VulkanFunctions.h"
|
#include "dawn_native/vulkan/VulkanFunctions.h"
|
||||||
#include "dawn_native/vulkan/VulkanInfo.h"
|
#include "dawn_native/vulkan/VulkanInfo.h"
|
||||||
|
|
||||||
namespace dawn_native { namespace vulkan {
|
namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
class Backend : public BackendConnection {
|
enum class ICD {
|
||||||
|
None,
|
||||||
|
SwiftShader,
|
||||||
|
};
|
||||||
|
|
||||||
|
// VulkanInstance holds the reference to the Vulkan library, the VkInstance, VkPhysicalDevices
|
||||||
|
// on that instance, Vulkan functions loaded from the library, and global information
|
||||||
|
// gathered from the instance. VkPhysicalDevices bound to the VkInstance are bound to the GPU
|
||||||
|
// and GPU driver, keeping them active. It is RefCounted so that (eventually) when all adapters
|
||||||
|
// on an instance are no longer in use, the instance is deleted. This can be particuarly useful
|
||||||
|
// when we create multiple instances to selectively discover ICDs (like only
|
||||||
|
// SwiftShader/iGPU/dGPU/eGPU), and only one physical device on one instance remains in use. We
|
||||||
|
// can delete the VkInstances that are not in use to avoid holding the discrete GPU active.
|
||||||
|
class VulkanInstance : public RefCounted {
|
||||||
public:
|
public:
|
||||||
Backend(InstanceBase* instance);
|
static ResultOrError<Ref<VulkanInstance>> Create(const InstanceBase* instance, ICD icd);
|
||||||
~Backend() override;
|
~VulkanInstance();
|
||||||
|
|
||||||
const VulkanFunctions& GetFunctions() const;
|
const VulkanFunctions& GetFunctions() const;
|
||||||
VkInstance GetVkInstance() const;
|
VkInstance GetVkInstance() const;
|
||||||
const VulkanGlobalInfo& GetGlobalInfo() const;
|
const VulkanGlobalInfo& GetGlobalInfo() const;
|
||||||
|
const std::vector<VkPhysicalDevice>& GetPhysicalDevices() const;
|
||||||
MaybeError Initialize(bool useSwiftshader);
|
|
||||||
|
|
||||||
std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MaybeError LoadVulkan(bool useSwiftshader);
|
VulkanInstance();
|
||||||
ResultOrError<VulkanGlobalKnobs> CreateInstance();
|
|
||||||
|
MaybeError Initialize(const InstanceBase* instance, ICD icd);
|
||||||
|
ResultOrError<VulkanGlobalKnobs> CreateVkInstance(const InstanceBase* instance);
|
||||||
|
|
||||||
MaybeError RegisterDebugUtils();
|
MaybeError RegisterDebugUtils();
|
||||||
|
|
||||||
|
@ -52,6 +66,19 @@ namespace dawn_native { namespace vulkan {
|
||||||
std::vector<VkPhysicalDevice> mPhysicalDevices;
|
std::vector<VkPhysicalDevice> mPhysicalDevices;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Backend : public BackendConnection {
|
||||||
|
public:
|
||||||
|
Backend(InstanceBase* instance);
|
||||||
|
~Backend() override;
|
||||||
|
|
||||||
|
MaybeError Initialize();
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ityp::array<ICD, Ref<VulkanInstance>, 2> mVulkanInstances = {};
|
||||||
|
};
|
||||||
|
|
||||||
}} // namespace dawn_native::vulkan
|
}} // namespace dawn_native::vulkan
|
||||||
|
|
||||||
#endif // DAWNNATIVE_VULKAN_BACKENDVK_H_
|
#endif // DAWNNATIVE_VULKAN_BACKENDVK_H_
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
// Initialize the "instance" procs of our local function table.
|
// Initialize the "instance" procs of our local function table.
|
||||||
VulkanFunctions* functions = GetMutableFunctions();
|
VulkanFunctions* functions = GetMutableFunctions();
|
||||||
*functions = ToBackend(GetAdapter())->GetBackend()->GetFunctions();
|
*functions = ToBackend(GetAdapter())->GetVulkanInstance()->GetFunctions();
|
||||||
|
|
||||||
// Two things are crucial if device initialization fails: the function pointers to destroy
|
// Two things are crucial if device initialization fails: the function pointers to destroy
|
||||||
// objects, and the fence deleter that calls these functions. Do not do anything before
|
// objects, and the fence deleter that calls these functions. Do not do anything before
|
||||||
|
@ -196,14 +196,14 @@ namespace dawn_native { namespace vulkan {
|
||||||
}
|
}
|
||||||
|
|
||||||
VkInstance Device::GetVkInstance() const {
|
VkInstance Device::GetVkInstance() const {
|
||||||
return ToBackend(GetAdapter())->GetBackend()->GetVkInstance();
|
return ToBackend(GetAdapter())->GetVulkanInstance()->GetVkInstance();
|
||||||
}
|
}
|
||||||
const VulkanDeviceInfo& Device::GetDeviceInfo() const {
|
const VulkanDeviceInfo& Device::GetDeviceInfo() const {
|
||||||
return mDeviceInfo;
|
return mDeviceInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VulkanGlobalInfo& Device::GetGlobalInfo() const {
|
const VulkanGlobalInfo& Device::GetGlobalInfo() const {
|
||||||
return ToBackend(GetAdapter())->GetBackend()->GetGlobalInfo();
|
return ToBackend(GetAdapter())->GetVulkanInstance()->GetGlobalInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDevice Device::GetVkDevice() const {
|
VkDevice Device::GetVkDevice() const {
|
||||||
|
|
|
@ -86,10 +86,10 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
ResultOrError<VkSurfaceKHR> CreateVulkanSurface(Backend* backend, Surface* surface) {
|
ResultOrError<VkSurfaceKHR> CreateVulkanSurface(Adapter* adapter, Surface* surface) {
|
||||||
const VulkanGlobalInfo& info = backend->GetGlobalInfo();
|
const VulkanGlobalInfo& info = adapter->GetVulkanInstance()->GetGlobalInfo();
|
||||||
const VulkanFunctions& fn = backend->GetFunctions();
|
const VulkanFunctions& fn = adapter->GetVulkanInstance()->GetFunctions();
|
||||||
VkInstance instance = backend->GetVkInstance();
|
VkInstance instance = adapter->GetVulkanInstance()->GetVkInstance();
|
||||||
|
|
||||||
// May not be used in the platform-specific switches below.
|
// May not be used in the platform-specific switches below.
|
||||||
DAWN_UNUSED(info);
|
DAWN_UNUSED(info);
|
||||||
|
@ -155,7 +155,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
// See https://xcb.freedesktop.org/MixingCalls/ for more information about
|
// See https://xcb.freedesktop.org/MixingCalls/ for more information about
|
||||||
// interoperability between Xlib and XCB
|
// interoperability between Xlib and XCB
|
||||||
const XlibXcbFunctions* xlibXcb =
|
const XlibXcbFunctions* xlibXcb =
|
||||||
backend->GetInstance()->GetOrCreateXlibXcbFunctions();
|
adapter->GetInstance()->GetOrCreateXlibXcbFunctions();
|
||||||
ASSERT(xlibXcb != nullptr);
|
ASSERT(xlibXcb != nullptr);
|
||||||
|
|
||||||
if (info.HasExt(InstanceExt::XcbSurface) && xlibXcb->IsLoaded()) {
|
if (info.HasExt(InstanceExt::XcbSurface) && xlibXcb->IsLoaded()) {
|
||||||
|
@ -275,7 +275,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mVkSurface == VK_NULL_HANDLE) {
|
if (mVkSurface == VK_NULL_HANDLE) {
|
||||||
DAWN_TRY_ASSIGN(mVkSurface, CreateVulkanSurface(adapter->GetBackend(), GetSurface()));
|
DAWN_TRY_ASSIGN(mVkSurface, CreateVulkanSurface(adapter, GetSurface()));
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanSurfaceInfo surfaceInfo;
|
VulkanSurfaceInfo surfaceInfo;
|
||||||
|
|
|
@ -61,10 +61,8 @@ namespace dawn_native { namespace vulkan {
|
||||||
return extensions[ext];
|
return extensions[ext];
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Backend& backend) {
|
ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const VulkanFunctions& vkFunctions) {
|
||||||
VulkanGlobalInfo info = {};
|
VulkanGlobalInfo info = {};
|
||||||
const VulkanFunctions& vkFunctions = backend.GetFunctions();
|
|
||||||
|
|
||||||
// Gather info on available API version
|
// Gather info on available API version
|
||||||
{
|
{
|
||||||
info.apiVersion = VK_MAKE_VERSION(1, 0, 0);
|
info.apiVersion = VK_MAKE_VERSION(1, 0, 0);
|
||||||
|
@ -121,10 +119,9 @@ namespace dawn_native { namespace vulkan {
|
||||||
return std::move(info);
|
return std::move(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<std::vector<VkPhysicalDevice>> GetPhysicalDevices(const Backend& backend) {
|
ResultOrError<std::vector<VkPhysicalDevice>> GatherPhysicalDevices(
|
||||||
VkInstance instance = backend.GetVkInstance();
|
VkInstance instance,
|
||||||
const VulkanFunctions& vkFunctions = backend.GetFunctions();
|
const VulkanFunctions& vkFunctions) {
|
||||||
|
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
VkResult result =
|
VkResult result =
|
||||||
VkResult::WrapUnsafe(vkFunctions.EnumeratePhysicalDevices(instance, &count, nullptr));
|
VkResult::WrapUnsafe(vkFunctions.EnumeratePhysicalDevices(instance, &count, nullptr));
|
||||||
|
@ -143,8 +140,8 @@ namespace dawn_native { namespace vulkan {
|
||||||
ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Adapter& adapter) {
|
ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Adapter& adapter) {
|
||||||
VulkanDeviceInfo info = {};
|
VulkanDeviceInfo info = {};
|
||||||
VkPhysicalDevice physicalDevice = adapter.GetPhysicalDevice();
|
VkPhysicalDevice physicalDevice = adapter.GetPhysicalDevice();
|
||||||
const VulkanGlobalInfo& globalInfo = adapter.GetBackend()->GetGlobalInfo();
|
const VulkanGlobalInfo& globalInfo = adapter.GetVulkanInstance()->GetGlobalInfo();
|
||||||
const VulkanFunctions& vkFunctions = adapter.GetBackend()->GetFunctions();
|
const VulkanFunctions& vkFunctions = adapter.GetVulkanInstance()->GetFunctions();
|
||||||
|
|
||||||
// Query the device properties first to get the ICD's `apiVersion`
|
// Query the device properties first to get the ICD's `apiVersion`
|
||||||
vkFunctions.GetPhysicalDeviceProperties(physicalDevice, &info.properties);
|
vkFunctions.GetPhysicalDeviceProperties(physicalDevice, &info.properties);
|
||||||
|
@ -276,7 +273,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
VulkanSurfaceInfo info = {};
|
VulkanSurfaceInfo info = {};
|
||||||
|
|
||||||
VkPhysicalDevice physicalDevice = adapter.GetPhysicalDevice();
|
VkPhysicalDevice physicalDevice = adapter.GetPhysicalDevice();
|
||||||
const VulkanFunctions& vkFunctions = adapter.GetBackend()->GetFunctions();
|
const VulkanFunctions& vkFunctions = adapter.GetVulkanInstance()->GetFunctions();
|
||||||
|
|
||||||
// Get the surface capabilities
|
// Get the surface capabilities
|
||||||
DAWN_TRY(CheckVkSuccess(vkFunctions.GetPhysicalDeviceSurfaceCapabilitiesKHR(
|
DAWN_TRY(CheckVkSuccess(vkFunctions.GetPhysicalDeviceSurfaceCapabilitiesKHR(
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
class Adapter;
|
class Adapter;
|
||||||
class Backend;
|
class Backend;
|
||||||
|
struct VulkanFunctions;
|
||||||
|
|
||||||
// Global information - gathered before the instance is created
|
// Global information - gathered before the instance is created
|
||||||
struct VulkanGlobalKnobs {
|
struct VulkanGlobalKnobs {
|
||||||
|
@ -76,8 +77,10 @@ namespace dawn_native { namespace vulkan {
|
||||||
std::vector<bool> supportedQueueFamilies;
|
std::vector<bool> supportedQueueFamilies;
|
||||||
};
|
};
|
||||||
|
|
||||||
ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Backend& backend);
|
ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const VulkanFunctions& vkFunctions);
|
||||||
ResultOrError<std::vector<VkPhysicalDevice>> GetPhysicalDevices(const Backend& backend);
|
ResultOrError<std::vector<VkPhysicalDevice>> GatherPhysicalDevices(
|
||||||
|
VkInstance instance,
|
||||||
|
const VulkanFunctions& vkFunctions);
|
||||||
ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Adapter& adapter);
|
ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Adapter& adapter);
|
||||||
ResultOrError<VulkanSurfaceInfo> GatherSurfaceInfo(const Adapter& adapter,
|
ResultOrError<VulkanSurfaceInfo> GatherSurfaceInfo(const Adapter& adapter,
|
||||||
VkSurfaceKHR surface);
|
VkSurfaceKHR surface);
|
||||||
|
|
Loading…
Reference in New Issue