Vulkan: Implement the backend connection and adapter.

This also changes VulkanInfo to gather info on backends / adapters
instead of the device, because all the info gathering can happen before
the device is created.

BUG=dawn:29

Change-Id: I9dc4412f494428f1ae589544d3adf76fe8b9a3a3
Reviewed-on: https://dawn-review.googlesource.com/c/3941
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Corentin Wallez 2019-02-04 09:31:09 +00:00 committed by Commit Bot service account
parent c26f6dae33
commit d1be0e7077
14 changed files with 486 additions and 286 deletions

View File

@ -649,6 +649,10 @@ source_set("libdawn_native_sources") {
if (dawn_enable_vulkan) {
deps += [ "third_party:vulkan_headers" ]
sources += [
"src/dawn_native/vulkan/AdapterVk.cpp",
"src/dawn_native/vulkan/AdapterVk.h",
"src/dawn_native/vulkan/BackendVk.cpp",
"src/dawn_native/vulkan/BackendVk.h",
"src/dawn_native/vulkan/BindGroupLayoutVk.cpp",
"src/dawn_native/vulkan/BindGroupLayoutVk.h",
"src/dawn_native/vulkan/BindGroupVk.cpp",

View File

@ -0,0 +1,56 @@
// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "dawn_native/vulkan/AdapterVk.h"
#include "dawn_native/vulkan/BackendVk.h"
#include "dawn_native/vulkan/DeviceVk.h"
namespace dawn_native { namespace vulkan {
Adapter::Adapter(Backend* backend, VkPhysicalDevice physicalDevice)
: AdapterBase(backend->GetInstance(), BackendType::Vulkan),
mPhysicalDevice(physicalDevice),
mBackend(backend) {
}
const VulkanDeviceInfo& Adapter::GetDeviceInfo() const {
return mDeviceInfo;
}
VkPhysicalDevice Adapter::GetPhysicalDevice() const {
return mPhysicalDevice;
}
Backend* Adapter::GetBackend() const {
return mBackend;
}
MaybeError Adapter::Initialize() {
DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this));
mPCIInfo.deviceId = mDeviceInfo.properties.deviceID;
mPCIInfo.vendorId = mDeviceInfo.properties.vendorID;
mPCIInfo.name = mDeviceInfo.properties.deviceName;
return {};
}
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl() {
std::unique_ptr<Device> device = std::make_unique<Device>(this);
DAWN_TRY(device->Initialize());
return device.release();
}
}} // namespace dawn_native::vulkan

View File

@ -0,0 +1,48 @@
// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef DAWNNATIVE_VULKAN_ADAPTERVK_H_
#define DAWNNATIVE_VULKAN_ADAPTERVK_H_
#include "dawn_native/Adapter.h"
#include "common/vulkan_platform.h"
#include "dawn_native/vulkan/VulkanInfo.h"
namespace dawn_native { namespace vulkan {
class Backend;
class Adapter : public AdapterBase {
public:
Adapter(Backend* backend, VkPhysicalDevice physicalDevice);
virtual ~Adapter() = default;
const VulkanDeviceInfo& GetDeviceInfo() const;
VkPhysicalDevice GetPhysicalDevice() const;
Backend* GetBackend() const;
MaybeError Initialize();
private:
ResultOrError<DeviceBase*> CreateDeviceImpl() override;
VkPhysicalDevice mPhysicalDevice;
Backend* mBackend;
VulkanDeviceInfo mDeviceInfo = {};
};
}} // namespace dawn_native::vulkan
#endif // DAWNNATIVE_VULKAN_ADAPTERVK_H_

View File

@ -0,0 +1,224 @@
// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "dawn_native/vulkan/BackendVk.h"
#include "dawn_native/Instance.h"
#include "dawn_native/VulkanBackend.h"
#include "dawn_native/vulkan/AdapterVk.h"
#include "dawn_native/vulkan/VulkanError.h"
#include <iostream>
#if DAWN_PLATFORM_LINUX
const char kVulkanLibName[] = "libvulkan.so.1";
#elif DAWN_PLATFORM_WINDOWS
const char kVulkanLibName[] = "vulkan-1.dll";
#else
# error "Unimplemented Vulkan backend platform"
#endif
namespace dawn_native { namespace vulkan {
Backend::Backend(InstanceBase* instance) : BackendConnection(instance, BackendType::Vulkan) {
}
Backend::~Backend() {
if (mDebugReportCallback != VK_NULL_HANDLE) {
mFunctions.DestroyDebugReportCallbackEXT(mInstance, mDebugReportCallback, nullptr);
mDebugReportCallback = VK_NULL_HANDLE;
}
// VkPhysicalDevices are destroyed when the VkInstance is destroyed
if (mInstance != VK_NULL_HANDLE) {
mFunctions.DestroyInstance(mInstance, nullptr);
mInstance = VK_NULL_HANDLE;
}
}
const VulkanFunctions& Backend::GetFunctions() const {
return mFunctions;
}
VkInstance Backend::GetVkInstance() const {
return mInstance;
}
MaybeError Backend::Initialize() {
if (!mVulkanLib.Open(kVulkanLibName)) {
return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't open ") + kVulkanLibName);
}
DAWN_TRY(mFunctions.LoadGlobalProcs(mVulkanLib));
DAWN_TRY_ASSIGN(mGlobalInfo, GatherGlobalInfo(*this));
VulkanGlobalKnobs usedGlobalKnobs = {};
DAWN_TRY_ASSIGN(usedGlobalKnobs, CreateInstance());
*static_cast<VulkanGlobalKnobs*>(&mGlobalInfo) = usedGlobalKnobs;
DAWN_TRY(mFunctions.LoadInstanceProcs(mInstance, mGlobalInfo));
if (usedGlobalKnobs.debugReport) {
DAWN_TRY(RegisterDebugReport());
}
DAWN_TRY_ASSIGN(mPhysicalDevices, GetPhysicalDevices(*this));
return {};
}
std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() {
std::vector<std::unique_ptr<AdapterBase>> adapters;
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 = {};
std::vector<const char*> layersToRequest;
std::vector<const char*> extensionsToRequest;
// vktrace works by instering a layer, but we hide it behind a macro due to the vktrace
// layer crashes when used without vktrace server started. See this vktrace issue:
// https://github.com/LunarG/VulkanTools/issues/254
// Also it is good to put it in first position so that it doesn't see Vulkan calls inserted
// by other layers.
#if defined(DAWN_USE_VKTRACE)
if (mGlobalInfo.vktrace) {
layersToRequest.push_back(kLayerNameLunargVKTrace);
usedKnobs.vktrace = true;
}
#endif
// RenderDoc installs a layer at the system level for its capture but we don't want to use
// it unless we are debugging in RenderDoc so we hide it behind a macro.
#if defined(DAWN_USE_RENDERDOC)
if (mGlobalInfo.renderDocCapture) {
layersToRequest.push_back(kLayerNameRenderDocCapture);
usedKnobs.renderDocCapture = true;
}
#endif
#if defined(DAWN_ENABLE_ASSERTS)
if (mGlobalInfo.standardValidation) {
layersToRequest.push_back(kLayerNameLunargStandardValidation);
usedKnobs.standardValidation = true;
}
if (mGlobalInfo.debugReport) {
extensionsToRequest.push_back(kExtensionNameExtDebugReport);
usedKnobs.debugReport = true;
}
#endif
// Always request all extensions used to create VkSurfaceKHR objects so that they are
// always available for embedders looking to create VkSurfaceKHR on our VkInstance.
if (mGlobalInfo.macosSurface) {
extensionsToRequest.push_back(kExtensionNameMvkMacosSurface);
usedKnobs.macosSurface = true;
}
if (mGlobalInfo.surface) {
extensionsToRequest.push_back(kExtensionNameKhrSurface);
usedKnobs.surface = true;
}
if (mGlobalInfo.waylandSurface) {
extensionsToRequest.push_back(kExtensionNameKhrWaylandSurface);
usedKnobs.waylandSurface = true;
}
if (mGlobalInfo.win32Surface) {
extensionsToRequest.push_back(kExtensionNameKhrWin32Surface);
usedKnobs.win32Surface = true;
}
if (mGlobalInfo.xcbSurface) {
extensionsToRequest.push_back(kExtensionNameKhrXcbSurface);
usedKnobs.xcbSurface = true;
}
if (mGlobalInfo.xlibSurface) {
extensionsToRequest.push_back(kExtensionNameKhrXlibSurface);
usedKnobs.xlibSurface = true;
}
VkApplicationInfo appInfo;
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pNext = nullptr;
appInfo.pApplicationName = nullptr;
appInfo.applicationVersion = 0;
appInfo.pEngineName = nullptr;
appInfo.engineVersion = 0;
appInfo.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.pApplicationInfo = &appInfo;
createInfo.enabledLayerCount = static_cast<uint32_t>(layersToRequest.size());
createInfo.ppEnabledLayerNames = layersToRequest.data();
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensionsToRequest.size());
createInfo.ppEnabledExtensionNames = extensionsToRequest.data();
DAWN_TRY(CheckVkSuccess(mFunctions.CreateInstance(&createInfo, nullptr, &mInstance),
"vkCreateInstance"));
return usedKnobs;
}
MaybeError Backend::RegisterDebugReport() {
VkDebugReportCallbackCreateInfoEXT createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
createInfo.pNext = nullptr;
createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
createInfo.pfnCallback = Backend::OnDebugReportCallback;
createInfo.pUserData = this;
return CheckVkSuccess(mFunctions.CreateDebugReportCallbackEXT(
mInstance, &createInfo, nullptr, &mDebugReportCallback),
"vkCreateDebugReportcallback");
}
VKAPI_ATTR VkBool32 VKAPI_CALL
Backend::OnDebugReportCallback(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT /*objectType*/,
uint64_t /*object*/,
size_t /*location*/,
int32_t /*messageCode*/,
const char* /*pLayerPrefix*/,
const char* pMessage,
void* /*pUserdata*/) {
std::cout << pMessage << std::endl;
ASSERT((flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) == 0);
return VK_FALSE;
}
BackendConnection* Connect(InstanceBase* instance) {
Backend* backend = new Backend(instance);
if (instance->ConsumedError(backend->Initialize())) {
delete backend;
return nullptr;
}
return backend;
}
}} // namespace dawn_native::vulkan

View File

@ -0,0 +1,64 @@
// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef DAWNNATIVE_VULKAN_BACKENDVK_H_
#define DAWNNATIVE_VULKAN_BACKENDVK_H_
#include "dawn_native/BackendConnection.h"
#include "common/DynamicLib.h"
#include "dawn_native/vulkan/VulkanFunctions.h"
#include "dawn_native/vulkan/VulkanInfo.h"
namespace dawn_native { namespace vulkan {
class Backend : public BackendConnection {
public:
Backend(InstanceBase* instance);
~Backend() override;
const VulkanFunctions& GetFunctions() const;
VkInstance GetVkInstance() const;
MaybeError Initialize();
std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override;
private:
ResultOrError<VulkanGlobalKnobs> CreateInstance();
MaybeError RegisterDebugReport();
static VKAPI_ATTR VkBool32 VKAPI_CALL
OnDebugReportCallback(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType,
uint64_t object,
size_t location,
int32_t messageCode,
const char* pLayerPrefix,
const char* pMessage,
void* pUserdata);
DynamicLib mVulkanLib;
VulkanGlobalInfo mGlobalInfo = {};
VkInstance mInstance = VK_NULL_HANDLE;
VulkanFunctions mFunctions;
VkDebugReportCallbackEXT mDebugReportCallback = VK_NULL_HANDLE;
std::vector<VkPhysicalDevice> mPhysicalDevices;
};
}} // namespace dawn_native::vulkan
#endif // DAWNNATIVE_VULKAN_BACKENDVK_H_

View File

@ -19,6 +19,8 @@
#include "dawn_native/Commands.h"
#include "dawn_native/DynamicUploader.h"
#include "dawn_native/ErrorData.h"
#include "dawn_native/vulkan/AdapterVk.h"
#include "dawn_native/vulkan/BackendVk.h"
#include "dawn_native/vulkan/BindGroupLayoutVk.h"
#include "dawn_native/vulkan/BindGroupVk.h"
#include "dawn_native/vulkan/BufferUploader.h"
@ -38,72 +40,22 @@
#include "dawn_native/vulkan/TextureVk.h"
#include "dawn_native/vulkan/VulkanError.h"
#include <spirv-cross/spirv_cross.hpp>
#include <iostream>
#if DAWN_PLATFORM_LINUX
const char kVulkanLibName[] = "libvulkan.so.1";
#elif DAWN_PLATFORM_WINDOWS
const char kVulkanLibName[] = "vulkan-1.dll";
#else
# error "Unimplemented Vulkan backend platform"
#endif
namespace dawn_native { namespace vulkan {
BackendConnection* Connect(InstanceBase* instance) {
return nullptr;
}
// Device
Device::Device() : DeviceBase(nullptr) {
MaybeError maybeError = Initialize();
// In device initialization, the error callback can't have been set yet.
// So it's too early to use ConsumedError - consume the error manually.
if (DAWN_UNLIKELY(maybeError.IsError())) {
ErrorData* error = maybeError.AcquireError();
printf("Device initialization error: %s\n", error->GetMessage().c_str());
delete error;
ASSERT(false);
return;
}
Device::Device(Adapter* adapter) : DeviceBase(adapter) {
}
MaybeError Device::Initialize() {
if (!mVulkanLib.Open(kVulkanLibName)) {
return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't open ") + kVulkanLibName);
}
// Copy the adapter's device info to the device so that we can change the "knobs"
mDeviceInfo = ToBackend(GetAdapter())->GetDeviceInfo();
VulkanFunctions* functions = GetMutableFunctions();
DAWN_TRY(functions->LoadGlobalProcs(mVulkanLib));
*functions = ToBackend(GetAdapter())->GetBackend()->GetFunctions();
DAWN_TRY_ASSIGN(mGlobalInfo, GatherGlobalInfo(*this));
VulkanGlobalKnobs usedGlobalKnobs = {};
DAWN_TRY_ASSIGN(usedGlobalKnobs, CreateInstance());
*static_cast<VulkanGlobalKnobs*>(&mGlobalInfo) = usedGlobalKnobs;
DAWN_TRY(functions->LoadInstanceProcs(mInstance, mGlobalInfo));
if (usedGlobalKnobs.debugReport) {
DAWN_TRY(RegisterDebugReport());
}
std::vector<VkPhysicalDevice> physicalDevices;
DAWN_TRY_ASSIGN(physicalDevices, GetPhysicalDevices(*this));
if (physicalDevices.empty()) {
return DAWN_CONTEXT_LOST_ERROR("No physical devices");
}
// TODO(cwallez@chromium.org): Choose the physical device based on ???
mPhysicalDevice = physicalDevices[0];
DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this, mPhysicalDevice));
VkPhysicalDevice physicalDevice = ToBackend(GetAdapter())->GetPhysicalDevice();
VulkanDeviceKnobs usedDeviceKnobs = {};
DAWN_TRY_ASSIGN(usedDeviceKnobs, CreateDevice());
DAWN_TRY_ASSIGN(usedDeviceKnobs, CreateDevice(physicalDevice));
*static_cast<VulkanDeviceKnobs*>(&mDeviceInfo) = usedDeviceKnobs;
DAWN_TRY(functions->LoadDeviceProcs(mVkDevice, mDeviceInfo));
@ -116,10 +68,6 @@ namespace dawn_native { namespace vulkan {
mMemoryAllocator = std::make_unique<MemoryAllocator>(this);
mRenderPassCache = std::make_unique<RenderPassCache>(this);
mPCIInfo.deviceId = mDeviceInfo.properties.deviceID;
mPCIInfo.vendorId = mDeviceInfo.properties.vendorID;
mPCIInfo.name = mDeviceInfo.properties.deviceName;
return {};
}
@ -182,17 +130,6 @@ namespace dawn_native { namespace vulkan {
fn.DestroyDevice(mVkDevice, nullptr);
mVkDevice = VK_NULL_HANDLE;
}
if (mDebugReportCallback != VK_NULL_HANDLE) {
fn.DestroyDebugReportCallbackEXT(mInstance, mDebugReportCallback, nullptr);
mDebugReportCallback = VK_NULL_HANDLE;
}
// VkPhysicalDevices are destroyed when the VkInstance is destroyed
if (mInstance != VK_NULL_HANDLE) {
fn.DestroyInstance(mInstance, nullptr);
mInstance = VK_NULL_HANDLE;
}
}
ResultOrError<BindGroupBase*> Device::CreateBindGroupImpl(
@ -283,22 +220,13 @@ namespace dawn_native { namespace vulkan {
}
}
const dawn_native::PCIInfo& Device::GetPCIInfo() const {
return mPCIInfo;
VkInstance Device::GetVkInstance() const {
return ToBackend(GetAdapter())->GetBackend()->GetVkInstance();
}
const VulkanDeviceInfo& Device::GetDeviceInfo() const {
return mDeviceInfo;
}
VkInstance Device::GetInstance() const {
return mInstance;
}
VkPhysicalDevice Device::GetPhysicalDevice() const {
return mPhysicalDevice;
}
VkDevice Device::GetVkDevice() const {
return mVkDevice;
}
@ -392,94 +320,7 @@ namespace dawn_native { namespace vulkan {
mWaitSemaphores.push_back(semaphore);
}
ResultOrError<VulkanGlobalKnobs> Device::CreateInstance() {
VulkanGlobalKnobs usedKnobs = {};
std::vector<const char*> layersToRequest;
std::vector<const char*> extensionsToRequest;
// vktrace works by instering a layer, but we hide it behind a macro due to the vktrace
// layer crashes when used without vktrace server started, see this vktrace issue:
// https://github.com/LunarG/VulkanTools/issues/254
// Also it is good to put it in first position so that it doesn't see Vulkan calls inserted
// by other layers.
#if defined(DAWN_USE_VKTRACE)
if (mGlobalInfo.vktrace) {
layersToRequest.push_back(kLayerNameLunargVKTrace);
usedKnobs.vktrace = true;
}
#endif
// RenderDoc installs a layer at the system level for its capture but we don't want to use
// it unless we are debugging in RenderDoc so we hide it behind a macro.
#if defined(DAWN_USE_RENDERDOC)
if (mGlobalInfo.renderDocCapture) {
layersToRequest.push_back(kLayerNameRenderDocCapture);
usedKnobs.renderDocCapture = true;
}
#endif
#if defined(DAWN_ENABLE_ASSERTS)
if (mGlobalInfo.standardValidation) {
layersToRequest.push_back(kLayerNameLunargStandardValidation);
usedKnobs.standardValidation = true;
}
if (mGlobalInfo.debugReport) {
extensionsToRequest.push_back(kExtensionNameExtDebugReport);
usedKnobs.debugReport = true;
}
#endif
// Always request all extensions used to create VkSurfaceKHR objects so that they are
// always available for embedders looking to create VkSurfaceKHR on our VkInstance.
if (mGlobalInfo.macosSurface) {
extensionsToRequest.push_back(kExtensionNameMvkMacosSurface);
usedKnobs.macosSurface = true;
}
if (mGlobalInfo.surface) {
extensionsToRequest.push_back(kExtensionNameKhrSurface);
usedKnobs.surface = true;
}
if (mGlobalInfo.waylandSurface) {
extensionsToRequest.push_back(kExtensionNameKhrWaylandSurface);
usedKnobs.waylandSurface = true;
}
if (mGlobalInfo.win32Surface) {
extensionsToRequest.push_back(kExtensionNameKhrWin32Surface);
usedKnobs.win32Surface = true;
}
if (mGlobalInfo.xcbSurface) {
extensionsToRequest.push_back(kExtensionNameKhrXcbSurface);
usedKnobs.xcbSurface = true;
}
if (mGlobalInfo.xlibSurface) {
extensionsToRequest.push_back(kExtensionNameKhrXlibSurface);
usedKnobs.xlibSurface = true;
}
VkApplicationInfo appInfo;
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pNext = nullptr;
appInfo.pApplicationName = nullptr;
appInfo.applicationVersion = 0;
appInfo.pEngineName = nullptr;
appInfo.engineVersion = 0;
appInfo.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.pApplicationInfo = &appInfo;
createInfo.enabledLayerCount = static_cast<uint32_t>(layersToRequest.size());
createInfo.ppEnabledLayerNames = layersToRequest.data();
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensionsToRequest.size());
createInfo.ppEnabledExtensionNames = extensionsToRequest.data();
DAWN_TRY(CheckVkSuccess(fn.CreateInstance(&createInfo, nullptr, &mInstance),
"vkCreateInstance"));
return usedKnobs;
}
ResultOrError<VulkanDeviceKnobs> Device::CreateDevice() {
ResultOrError<VulkanDeviceKnobs> Device::CreateDevice(VkPhysicalDevice physicalDevice) {
VulkanDeviceKnobs usedKnobs = {};
float zero = 0.0f;
@ -541,7 +382,7 @@ namespace dawn_native { namespace vulkan {
createInfo.ppEnabledExtensionNames = extensionsToRequest.data();
createInfo.pEnabledFeatures = &usedKnobs.features;
DAWN_TRY(CheckVkSuccess(fn.CreateDevice(mPhysicalDevice, &createInfo, nullptr, &mVkDevice),
DAWN_TRY(CheckVkSuccess(fn.CreateDevice(physicalDevice, &createInfo, nullptr, &mVkDevice),
"vkCreateDevice"));
return usedKnobs;
@ -551,34 +392,6 @@ namespace dawn_native { namespace vulkan {
fn.GetDeviceQueue(mVkDevice, mQueueFamily, 0, &mQueue);
}
MaybeError Device::RegisterDebugReport() {
VkDebugReportCallbackCreateInfoEXT createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
createInfo.pNext = nullptr;
createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
createInfo.pfnCallback = Device::OnDebugReportCallback;
createInfo.pUserData = this;
return CheckVkSuccess(
fn.CreateDebugReportCallbackEXT(mInstance, &createInfo, nullptr, &mDebugReportCallback),
"vkCreateDebugReportcallback");
}
VKAPI_ATTR VkBool32 VKAPI_CALL
Device::OnDebugReportCallback(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT /*objectType*/,
uint64_t /*object*/,
size_t /*location*/,
int32_t /*messageCode*/,
const char* /*pLayerPrefix*/,
const char* pMessage,
void* /*pUserdata*/) {
std::cout << pMessage << std::endl;
ASSERT((flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) == 0);
return VK_FALSE;
}
VulkanFunctions* Device::GetMutableFunctions() {
return const_cast<VulkanFunctions*>(&fn);
}

View File

@ -17,7 +17,6 @@
#include "dawn_native/dawn_platform.h"
#include "common/DynamicLib.h"
#include "common/Serial.h"
#include "common/SerialQueue.h"
#include "dawn_native/Device.h"
@ -30,6 +29,7 @@
namespace dawn_native { namespace vulkan {
class Adapter;
class BufferUploader;
class FencedDeleter;
class MapRequestTracker;
@ -38,15 +38,16 @@ namespace dawn_native { namespace vulkan {
class Device : public DeviceBase {
public:
Device();
Device(Adapter* adapter);
~Device();
MaybeError Initialize();
// Contains all the Vulkan entry points, vkDoFoo is called via device->fn.DoFoo.
const VulkanFunctions fn;
VkInstance GetVkInstance() const;
const VulkanDeviceInfo& GetDeviceInfo() const;
VkInstance GetInstance() const;
VkPhysicalDevice GetPhysicalDevice() const;
VkDevice GetVkDevice() const;
uint32_t GetGraphicsQueueFamily() const;
VkQueue GetQueue() const;
@ -73,8 +74,6 @@ namespace dawn_native { namespace vulkan {
Serial GetLastSubmittedCommandSerial() const final override;
void TickImpl() override;
const dawn_native::PCIInfo& GetPCIInfo() const override;
ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override;
MaybeError CopyFromStagingToBuffer(StagingBufferBase* source,
uint32_t sourceOffset,
@ -103,37 +102,17 @@ namespace dawn_native { namespace vulkan {
TextureBase* texture,
const TextureViewDescriptor* descriptor) override;
MaybeError Initialize();
ResultOrError<VulkanGlobalKnobs> CreateInstance();
ResultOrError<VulkanDeviceKnobs> CreateDevice();
ResultOrError<VulkanDeviceKnobs> CreateDevice(VkPhysicalDevice physicalDevice);
void GatherQueueFromDevice();
MaybeError RegisterDebugReport();
static VKAPI_ATTR VkBool32 VKAPI_CALL
OnDebugReportCallback(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType,
uint64_t object,
size_t location,
int32_t messageCode,
const char* pLayerPrefix,
const char* pMessage,
void* pUserdata);
// To make it easier to use fn it is a public const member. However
// the Device is allowed to mutate them through these private methods.
VulkanFunctions* GetMutableFunctions();
VulkanGlobalInfo mGlobalInfo = {};
VulkanDeviceInfo mDeviceInfo = {};
DynamicLib mVulkanLib;
VkInstance mInstance = VK_NULL_HANDLE;
VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE;
VkDevice mVkDevice = VK_NULL_HANDLE;
uint32_t mQueueFamily = 0;
VkQueue mQueue = VK_NULL_HANDLE;
VkDebugReportCallbackEXT mDebugReportCallback = VK_NULL_HANDLE;
std::unique_ptr<BufferUploader> mBufferUploader;
std::unique_ptr<FencedDeleter> mDeleter;
@ -166,8 +145,6 @@ namespace dawn_native { namespace vulkan {
std::vector<CommandPoolAndBuffer> mUnusedCommands;
CommandPoolAndBuffer mPendingCommands;
std::vector<VkSemaphore> mWaitSemaphores;
dawn_native::PCIInfo mPCIInfo;
};
}} // namespace dawn_native::vulkan

View File

@ -96,7 +96,7 @@ namespace dawn_native { namespace vulkan {
void FencedDeleter::Tick(Serial completedSerial) {
VkDevice vkDevice = mDevice->GetVkDevice();
VkInstance instance = mDevice->GetInstance();
VkInstance instance = mDevice->GetVkInstance();
// Buffers and images must be deleted before memories because it is invalid to free memory
// that still have resources bound to it.

View File

@ -58,7 +58,8 @@ namespace dawn_native { namespace vulkan {
}
void NativeSwapChainImpl::Init(dawnWSIContextVulkan* /*context*/) {
if (mDevice->ConsumedError(GatherSurfaceInfo(*mDevice, mSurface, &mInfo))) {
if (mDevice->ConsumedError(
GatherSurfaceInfo(*ToBackend(mDevice->GetAdapter()), mSurface, &mInfo))) {
ASSERT(false);
}

View File

@ -27,15 +27,13 @@
namespace dawn_native { namespace vulkan {
dawnDevice CreateDevice() {
return reinterpret_cast<dawnDevice>(new Device());
}
VkInstance GetInstance(dawnDevice device) {
Device* backendDevice = reinterpret_cast<Device*>(device);
return backendDevice->GetInstance();
return backendDevice->GetVkInstance();
}
// Explicitly export this function because it uses the "native" type for surfaces while the
// header as seen in this file uses the wrapped type.
DAWN_NATIVE_EXPORT dawnSwapChainImplementation
CreateNativeSwapChainImpl(dawnDevice device, VkSurfaceKHRNative surfaceNative) {
Device* backendDevice = reinterpret_cast<Device*>(device);

View File

@ -14,7 +14,8 @@
#include "dawn_native/vulkan/VulkanInfo.h"
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/AdapterVk.h"
#include "dawn_native/vulkan/BackendVk.h"
#include <cstring>
@ -43,13 +44,14 @@ namespace dawn_native { namespace vulkan {
const char kExtensionNameKhrXcbSurface[] = "VK_KHR_xcb_surface";
const char kExtensionNameKhrXlibSurface[] = "VK_KHR_xlib_surface";
ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Device& device) {
ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Backend& backend) {
VulkanGlobalInfo info = {};
const VulkanFunctions& vkFunctions = backend.GetFunctions();
// Gather the info about the instance layers
{
uint32_t count = 0;
VkResult result = device.fn.EnumerateInstanceLayerProperties(&count, nullptr);
VkResult result = vkFunctions.EnumerateInstanceLayerProperties(&count, nullptr);
// From the Vulkan spec result should be success if there are 0 layers,
// incomplete otherwise. This means that both values represent a success.
// This is the same for all Enumarte functions
@ -58,7 +60,7 @@ namespace dawn_native { namespace vulkan {
}
info.layers.resize(count);
result = device.fn.EnumerateInstanceLayerProperties(&count, info.layers.data());
result = vkFunctions.EnumerateInstanceLayerProperties(&count, info.layers.data());
if (result != VK_SUCCESS) {
return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceLayerProperties");
}
@ -80,14 +82,14 @@ namespace dawn_native { namespace vulkan {
{
uint32_t count = 0;
VkResult result =
device.fn.EnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
vkFunctions.EnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceExtensionProperties");
}
info.extensions.resize(count);
result = device.fn.EnumerateInstanceExtensionProperties(nullptr, &count,
info.extensions.data());
result = vkFunctions.EnumerateInstanceExtensionProperties(nullptr, &count,
info.extensions.data());
if (result != VK_SUCCESS) {
return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceExtensionProperties");
}
@ -122,17 +124,18 @@ namespace dawn_native { namespace vulkan {
return info;
}
ResultOrError<std::vector<VkPhysicalDevice>> GetPhysicalDevices(const Device& device) {
VkInstance instance = device.GetInstance();
ResultOrError<std::vector<VkPhysicalDevice>> GetPhysicalDevices(const Backend& backend) {
VkInstance instance = backend.GetVkInstance();
const VulkanFunctions& vkFunctions = backend.GetFunctions();
uint32_t count = 0;
VkResult result = device.fn.EnumeratePhysicalDevices(instance, &count, nullptr);
VkResult result = vkFunctions.EnumeratePhysicalDevices(instance, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return DAWN_CONTEXT_LOST_ERROR("vkEnumeratePhysicalDevices");
}
std::vector<VkPhysicalDevice> physicalDevices(count);
result = device.fn.EnumeratePhysicalDevices(instance, &count, physicalDevices.data());
result = vkFunctions.EnumeratePhysicalDevices(instance, &count, physicalDevices.data());
if (result != VK_SUCCESS) {
return DAWN_CONTEXT_LOST_ERROR("vkEnumeratePhysicalDevices");
}
@ -140,18 +143,19 @@ namespace dawn_native { namespace vulkan {
return physicalDevices;
}
ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Device& device,
VkPhysicalDevice physicalDevice) {
ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Adapter& adapter) {
VulkanDeviceInfo info = {};
VkPhysicalDevice physicalDevice = adapter.GetPhysicalDevice();
const VulkanFunctions& vkFunctions = adapter.GetBackend()->GetFunctions();
// Gather general info about the device
device.fn.GetPhysicalDeviceProperties(physicalDevice, &info.properties);
device.fn.GetPhysicalDeviceFeatures(physicalDevice, &info.features);
vkFunctions.GetPhysicalDeviceProperties(physicalDevice, &info.properties);
vkFunctions.GetPhysicalDeviceFeatures(physicalDevice, &info.features);
// Gather info about device memory.
{
VkPhysicalDeviceMemoryProperties memory;
device.fn.GetPhysicalDeviceMemoryProperties(physicalDevice, &memory);
vkFunctions.GetPhysicalDeviceMemoryProperties(physicalDevice, &memory);
info.memoryTypes.assign(memory.memoryTypes,
memory.memoryTypes + memory.memoryTypeCount);
@ -162,25 +166,25 @@ namespace dawn_native { namespace vulkan {
// Gather info about device queue families
{
uint32_t count = 0;
device.fn.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr);
vkFunctions.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr);
info.queueFamilies.resize(count);
device.fn.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count,
info.queueFamilies.data());
vkFunctions.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count,
info.queueFamilies.data());
}
// Gather the info about the device layers
{
uint32_t count = 0;
VkResult result =
device.fn.EnumerateDeviceLayerProperties(physicalDevice, &count, nullptr);
vkFunctions.EnumerateDeviceLayerProperties(physicalDevice, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceLayerProperties");
}
info.layers.resize(count);
result = device.fn.EnumerateDeviceLayerProperties(physicalDevice, &count,
info.layers.data());
result = vkFunctions.EnumerateDeviceLayerProperties(physicalDevice, &count,
info.layers.data());
if (result != VK_SUCCESS) {
return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceLayerProperties");
}
@ -189,15 +193,15 @@ namespace dawn_native { namespace vulkan {
// Gather the info about the device extensions
{
uint32_t count = 0;
VkResult result = device.fn.EnumerateDeviceExtensionProperties(physicalDevice, nullptr,
&count, nullptr);
VkResult result = vkFunctions.EnumerateDeviceExtensionProperties(
physicalDevice, nullptr, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceExtensionProperties");
}
info.extensions.resize(count);
result = device.fn.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &count,
info.extensions.data());
result = vkFunctions.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &count,
info.extensions.data());
if (result != VK_SUCCESS) {
return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceExtensionProperties");
}
@ -214,14 +218,15 @@ namespace dawn_native { namespace vulkan {
return info;
}
MaybeError GatherSurfaceInfo(const Device& device,
MaybeError GatherSurfaceInfo(const Adapter& adapter,
VkSurfaceKHR surface,
VulkanSurfaceInfo* info) {
VkPhysicalDevice physicalDevice = device.GetPhysicalDevice();
VkPhysicalDevice physicalDevice = adapter.GetPhysicalDevice();
const VulkanFunctions& vkFunctions = adapter.GetBackend()->GetFunctions();
// Get the surface capabilities
{
VkResult result = device.fn.GetPhysicalDeviceSurfaceCapabilitiesKHR(
VkResult result = vkFunctions.GetPhysicalDeviceSurfaceCapabilitiesKHR(
physicalDevice, surface, &info->capabilities);
if (result != VK_SUCCESS) {
return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
@ -230,13 +235,13 @@ namespace dawn_native { namespace vulkan {
// Query which queue families support presenting this surface
{
size_t nQueueFamilies = device.GetDeviceInfo().queueFamilies.size();
size_t nQueueFamilies = adapter.GetDeviceInfo().queueFamilies.size();
info->supportedQueueFamilies.resize(nQueueFamilies, false);
for (uint32_t i = 0; i < nQueueFamilies; ++i) {
VkBool32 supported = VK_FALSE;
VkResult result = device.fn.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i,
surface, &supported);
VkResult result = vkFunctions.GetPhysicalDeviceSurfaceSupportKHR(
physicalDevice, i, surface, &supported);
if (result != VK_SUCCESS) {
return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceSupportKHR");
@ -249,15 +254,15 @@ namespace dawn_native { namespace vulkan {
// Gather supported formats
{
uint32_t count = 0;
VkResult result = device.fn.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface,
&count, nullptr);
VkResult result = vkFunctions.GetPhysicalDeviceSurfaceFormatsKHR(
physicalDevice, surface, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR");
}
info->formats.resize(count);
result = device.fn.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &count,
info->formats.data());
result = vkFunctions.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &count,
info->formats.data());
if (result != VK_SUCCESS) {
return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR");
}
@ -266,14 +271,14 @@ namespace dawn_native { namespace vulkan {
// Gather supported presents modes
{
uint32_t count = 0;
VkResult result = device.fn.GetPhysicalDeviceSurfacePresentModesKHR(
VkResult result = vkFunctions.GetPhysicalDeviceSurfacePresentModesKHR(
physicalDevice, surface, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfacePresentModesKHR");
}
info->presentModes.resize(count);
result = device.fn.GetPhysicalDeviceSurfacePresentModesKHR(
result = vkFunctions.GetPhysicalDeviceSurfacePresentModesKHR(
physicalDevice, surface, &count, info->presentModes.data());
if (result != VK_SUCCESS) {
return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfacePresentModesKHR");

View File

@ -22,7 +22,8 @@
namespace dawn_native { namespace vulkan {
class Device;
class Adapter;
class Backend;
extern const char kLayerNameLunargStandardValidation[];
extern const char kLayerNameLunargVKTrace[];
@ -87,11 +88,10 @@ namespace dawn_native { namespace vulkan {
std::vector<bool> supportedQueueFamilies;
};
ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Device& device);
ResultOrError<std::vector<VkPhysicalDevice>> GetPhysicalDevices(const Device& device);
ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Device& device,
VkPhysicalDevice physicalDevice);
MaybeError GatherSurfaceInfo(const Device& device,
ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Backend& backend);
ResultOrError<std::vector<VkPhysicalDevice>> GetPhysicalDevices(const Backend& backend);
ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Adapter& adapter);
MaybeError GatherSurfaceInfo(const Adapter& adapter,
VkSurfaceKHR surface,
VulkanSurfaceInfo* info);
}} // namespace dawn_native::vulkan

View File

@ -15,17 +15,14 @@
#ifndef DAWNNATIVE_VULKANBACKEND_H_
#define DAWNNATIVE_VULKANBACKEND_H_
#include <dawn/dawn.h>
#include <dawn/dawn_wsi.h>
#include <dawn_native/dawn_native_export.h>
#include <dawn_native/DawnNative.h>
#include <vulkan/vulkan.h>
#include <vector>
namespace dawn_native { namespace vulkan {
DAWN_NATIVE_EXPORT dawnDevice CreateDevice();
DAWN_NATIVE_EXPORT VkInstance GetInstance(dawnDevice device);
DAWN_NATIVE_EXPORT dawnSwapChainImplementation CreateNativeSwapChainImpl(dawnDevice device,

View File

@ -28,8 +28,20 @@ namespace utils {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
}
dawnDevice CreateDevice() override {
mDevice = dawn_native::vulkan::CreateDevice();
return mDevice;
// Make an instance and find a Vulkan adapter
mInstance = std::make_unique<dawn_native::Instance>();
mInstance->DiscoverDefaultAdapters();
std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters();
for (dawn_native::Adapter adapter : adapters) {
if (adapter.GetBackendType() == dawn_native::BackendType::Vulkan) {
mDevice = adapter.CreateDevice();
return mDevice;
}
}
UNREACHABLE();
return {};
}
uint64_t GetSwapChainImplementation() override {
if (mSwapchainImpl.userData == nullptr) {
@ -49,7 +61,8 @@ namespace utils {
}
private:
dawnDevice mDevice;
std::unique_ptr<dawn_native::Instance> mInstance;
dawnDevice mDevice = nullptr;
dawnSwapChainImplementation mSwapchainImpl = {};
};