Vulkan: Handle errors on device creation.

This is both something we should strive for for robustness of the
backends and in this case helped debug what the issue was on the
linux-dawn-rel builder that was failing all Vulkan tests.

BUG=dawn:19

Change-Id: Ibe9f5ad76b7766575bb74fe4993625cf82cdf13f
Reviewed-on: https://dawn-review.googlesource.com/c/2702
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Corentin Wallez 2018-12-03 12:49:56 +00:00 committed by Commit Bot service account
parent 0f8b507888
commit 85df07a1e5
9 changed files with 142 additions and 143 deletions

View File

@ -19,7 +19,7 @@
namespace dawn_native { namespace dawn_native {
ErrorData* MakeError(ErrorType type, ErrorData* MakeError(ErrorType type,
const char* message, std::string message,
const char* file, const char* file,
const char* function, const char* function,
int line) { int line) {

View File

@ -17,6 +17,8 @@
#include "common/Result.h" #include "common/Result.h"
#include <string>
namespace dawn_native { namespace dawn_native {
// This is the content of an error value for MaybeError or ResultOrError, split off to its own // This is the content of an error value for MaybeError or ResultOrError, split off to its own
@ -85,7 +87,7 @@ namespace dawn_native {
// Implementation detail of DAWN_MAKE_ERROR // Implementation detail of DAWN_MAKE_ERROR
ErrorData* MakeError(ErrorType type, ErrorData* MakeError(ErrorType type,
const char* message, std::string message,
const char* file, const char* file,
const char* function, const char* function,
int line); int line);

View File

@ -83,66 +83,47 @@ namespace dawn_native { namespace vulkan {
// Device // Device
Device::Device(const std::vector<const char*>& requiredInstanceExtensions) { Device::Device(const std::vector<const char*>& requiredInstanceExtensions) {
if (!mVulkanLib.Open(kVulkanLibName)) { if (ConsumedError(Initialize(requiredInstanceExtensions))) {
ASSERT(false); ASSERT(false);
return; return;
} }
}
MaybeError Device::Initialize(const std::vector<const char*>& requiredInstanceExtensions) {
if (!mVulkanLib.Open(kVulkanLibName)) {
return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't open ") + kVulkanLibName);
}
VulkanFunctions* functions = GetMutableFunctions(); VulkanFunctions* functions = GetMutableFunctions();
DAWN_TRY(functions->LoadGlobalProcs(mVulkanLib));
if (!functions->LoadGlobalProcs(mVulkanLib)) { DAWN_TRY_ASSIGN(mGlobalInfo, GatherGlobalInfo(*this));
ASSERT(false);
return;
}
if (!GatherGlobalInfo(*this, &mGlobalInfo)) {
ASSERT(false);
return;
}
VulkanGlobalKnobs usedGlobalKnobs = {}; VulkanGlobalKnobs usedGlobalKnobs = {};
if (!CreateInstance(&usedGlobalKnobs, requiredInstanceExtensions)) { DAWN_TRY_ASSIGN(usedGlobalKnobs, CreateInstance(requiredInstanceExtensions));
ASSERT(false);
return;
}
*static_cast<VulkanGlobalKnobs*>(&mGlobalInfo) = usedGlobalKnobs; *static_cast<VulkanGlobalKnobs*>(&mGlobalInfo) = usedGlobalKnobs;
if (!functions->LoadInstanceProcs(mInstance, usedGlobalKnobs)) { DAWN_TRY(functions->LoadInstanceProcs(mInstance, mGlobalInfo));
ASSERT(false);
return;
}
if (usedGlobalKnobs.debugReport) { if (usedGlobalKnobs.debugReport) {
if (!RegisterDebugReport()) { DAWN_TRY(RegisterDebugReport());
ASSERT(false);
return;
}
} }
std::vector<VkPhysicalDevice> physicalDevices; std::vector<VkPhysicalDevice> physicalDevices;
if (!GetPhysicalDevices(*this, &physicalDevices) || physicalDevices.empty()) { DAWN_TRY_ASSIGN(physicalDevices, GetPhysicalDevices(*this));
ASSERT(false); if (physicalDevices.empty()) {
return; return DAWN_CONTEXT_LOST_ERROR("No physical devices");
} }
// TODO(cwallez@chromium.org): Choose the physical device based on ??? // TODO(cwallez@chromium.org): Choose the physical device based on ???
mPhysicalDevice = physicalDevices[0]; mPhysicalDevice = physicalDevices[0];
if (!GatherDeviceInfo(*this, mPhysicalDevice, &mDeviceInfo)) { DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this, mPhysicalDevice));
ASSERT(false);
return;
}
VulkanDeviceKnobs usedDeviceKnobs = {}; VulkanDeviceKnobs usedDeviceKnobs = {};
if (!CreateDevice(&usedDeviceKnobs)) { DAWN_TRY_ASSIGN(usedDeviceKnobs, CreateDevice());
ASSERT(false);
return;
}
*static_cast<VulkanDeviceKnobs*>(&mDeviceInfo) = usedDeviceKnobs; *static_cast<VulkanDeviceKnobs*>(&mDeviceInfo) = usedDeviceKnobs;
if (!functions->LoadDeviceProcs(mVkDevice, usedDeviceKnobs)) { DAWN_TRY(functions->LoadDeviceProcs(mVkDevice, mDeviceInfo));
ASSERT(false);
return;
}
GatherQueueFromDevice(); GatherQueueFromDevice();
@ -155,6 +136,8 @@ namespace dawn_native { namespace vulkan {
mPCIInfo.deviceId = mDeviceInfo.properties.deviceID; mPCIInfo.deviceId = mDeviceInfo.properties.deviceID;
mPCIInfo.vendorId = mDeviceInfo.properties.vendorID; mPCIInfo.vendorId = mDeviceInfo.properties.vendorID;
mPCIInfo.name = mDeviceInfo.properties.deviceName; mPCIInfo.name = mDeviceInfo.properties.deviceName;
return {};
} }
Device::~Device() { Device::~Device() {
@ -418,8 +401,10 @@ namespace dawn_native { namespace vulkan {
mWaitSemaphores.push_back(semaphore); mWaitSemaphores.push_back(semaphore);
} }
bool Device::CreateInstance(VulkanGlobalKnobs* usedKnobs, ResultOrError<VulkanGlobalKnobs> Device::CreateInstance(
const std::vector<const char*>& requiredExtensions) { const std::vector<const char*>& requiredExtensions) {
VulkanGlobalKnobs usedKnobs = {};
std::vector<const char*> layersToRequest; std::vector<const char*> layersToRequest;
std::vector<const char*> extensionsToRequest = requiredExtensions; std::vector<const char*> extensionsToRequest = requiredExtensions;
@ -441,7 +426,7 @@ namespace dawn_native { namespace vulkan {
#if defined(DAWN_USE_VKTRACE) #if defined(DAWN_USE_VKTRACE)
if (mGlobalInfo.vktrace) { if (mGlobalInfo.vktrace) {
layersToRequest.push_back(kLayerNameLunargVKTrace); layersToRequest.push_back(kLayerNameLunargVKTrace);
usedKnobs->vktrace = true; usedKnobs.vktrace = true;
} }
#endif #endif
// RenderDoc installs a layer at the system level for its capture but we don't want to use // RenderDoc installs a layer at the system level for its capture but we don't want to use
@ -449,22 +434,22 @@ namespace dawn_native { namespace vulkan {
#if defined(DAWN_USE_RENDERDOC) #if defined(DAWN_USE_RENDERDOC)
if (mGlobalInfo.renderDocCapture) { if (mGlobalInfo.renderDocCapture) {
layersToRequest.push_back(kLayerNameRenderDocCapture); layersToRequest.push_back(kLayerNameRenderDocCapture);
usedKnobs->renderDocCapture = true; usedKnobs.renderDocCapture = true;
} }
#endif #endif
#if defined(DAWN_ENABLE_ASSERTS) #if defined(DAWN_ENABLE_ASSERTS)
if (mGlobalInfo.standardValidation) { if (mGlobalInfo.standardValidation) {
layersToRequest.push_back(kLayerNameLunargStandardValidation); layersToRequest.push_back(kLayerNameLunargStandardValidation);
usedKnobs->standardValidation = true; usedKnobs.standardValidation = true;
} }
if (mGlobalInfo.debugReport) { if (mGlobalInfo.debugReport) {
AddExtensionIfNotPresent(&extensionsToRequest, kExtensionNameExtDebugReport); AddExtensionIfNotPresent(&extensionsToRequest, kExtensionNameExtDebugReport);
usedKnobs->debugReport = true; usedKnobs.debugReport = true;
} }
#endif #endif
if (mGlobalInfo.surface) { if (mGlobalInfo.surface) {
AddExtensionIfNotPresent(&extensionsToRequest, kExtensionNameKhrSurface); AddExtensionIfNotPresent(&extensionsToRequest, kExtensionNameKhrSurface);
usedKnobs->surface = true; usedKnobs.surface = true;
} }
VkApplicationInfo appInfo; VkApplicationInfo appInfo;
@ -487,13 +472,15 @@ namespace dawn_native { namespace vulkan {
createInfo.ppEnabledExtensionNames = extensionsToRequest.data(); createInfo.ppEnabledExtensionNames = extensionsToRequest.data();
if (fn.CreateInstance(&createInfo, nullptr, &mInstance) != VK_SUCCESS) { if (fn.CreateInstance(&createInfo, nullptr, &mInstance) != VK_SUCCESS) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkCreateInstance failed");
} }
return true; return usedKnobs;
} }
bool Device::CreateDevice(VulkanDeviceKnobs* usedKnobs) { ResultOrError<VulkanDeviceKnobs> Device::CreateDevice() {
VulkanDeviceKnobs usedKnobs = {};
float zero = 0.0f; float zero = 0.0f;
std::vector<const char*> layersToRequest; std::vector<const char*> layersToRequest;
std::vector<const char*> extensionsToRequest; std::vector<const char*> extensionsToRequest;
@ -501,13 +488,13 @@ namespace dawn_native { namespace vulkan {
if (mDeviceInfo.swapchain) { if (mDeviceInfo.swapchain) {
extensionsToRequest.push_back(kExtensionNameKhrSwapchain); extensionsToRequest.push_back(kExtensionNameKhrSwapchain);
usedKnobs->swapchain = true; usedKnobs.swapchain = true;
} }
// Always require independentBlend because it is a core Dawn feature // Always require independentBlend because it is a core Dawn feature
usedKnobs->features.independentBlend = VK_TRUE; usedKnobs.features.independentBlend = VK_TRUE;
// Always require imageCubeArray because it is a core Dawn feature // Always require imageCubeArray because it is a core Dawn feature
usedKnobs->features.imageCubeArray = VK_TRUE; usedKnobs.features.imageCubeArray = VK_TRUE;
// Find a universal queue family // Find a universal queue family
{ {
@ -523,7 +510,7 @@ namespace dawn_native { namespace vulkan {
} }
if (universalQueueFamily == -1) { if (universalQueueFamily == -1) {
return false; return DAWN_CONTEXT_LOST_ERROR("No universal queue family");
} }
mQueueFamily = static_cast<uint32_t>(universalQueueFamily); mQueueFamily = static_cast<uint32_t>(universalQueueFamily);
} }
@ -551,20 +538,20 @@ namespace dawn_native { namespace vulkan {
createInfo.ppEnabledLayerNames = layersToRequest.data(); createInfo.ppEnabledLayerNames = layersToRequest.data();
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensionsToRequest.size()); createInfo.enabledExtensionCount = static_cast<uint32_t>(extensionsToRequest.size());
createInfo.ppEnabledExtensionNames = extensionsToRequest.data(); createInfo.ppEnabledExtensionNames = extensionsToRequest.data();
createInfo.pEnabledFeatures = &usedKnobs->features; createInfo.pEnabledFeatures = &usedKnobs.features;
if (fn.CreateDevice(mPhysicalDevice, &createInfo, nullptr, &mVkDevice) != VK_SUCCESS) { if (fn.CreateDevice(mPhysicalDevice, &createInfo, nullptr, &mVkDevice) != VK_SUCCESS) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkCreateDevice failed");
} }
return true; return usedKnobs;
} }
void Device::GatherQueueFromDevice() { void Device::GatherQueueFromDevice() {
fn.GetDeviceQueue(mVkDevice, mQueueFamily, 0, &mQueue); fn.GetDeviceQueue(mVkDevice, mQueueFamily, 0, &mQueue);
} }
bool Device::RegisterDebugReport() { MaybeError Device::RegisterDebugReport() {
VkDebugReportCallbackCreateInfoEXT createInfo; VkDebugReportCallbackCreateInfoEXT createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
createInfo.pNext = nullptr; createInfo.pNext = nullptr;
@ -574,10 +561,10 @@ namespace dawn_native { namespace vulkan {
if (fn.CreateDebugReportCallbackEXT(mInstance, &createInfo, nullptr, if (fn.CreateDebugReportCallbackEXT(mInstance, &createInfo, nullptr,
&mDebugReportCallback) != VK_SUCCESS) { &mDebugReportCallback) != VK_SUCCESS) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkCreateDebugReportCallbackEXT failed");
} }
return true; return {};
} }
VKAPI_ATTR VkBool32 VKAPI_CALL VKAPI_ATTR VkBool32 VKAPI_CALL

View File

@ -97,12 +97,13 @@ namespace dawn_native { namespace vulkan {
TextureBase* texture, TextureBase* texture,
const TextureViewDescriptor* descriptor) override; const TextureViewDescriptor* descriptor) override;
bool CreateInstance(VulkanGlobalKnobs* usedKnobs, MaybeError Initialize(const std::vector<const char*>& requiredInstanceExtensions);
const std::vector<const char*>& requiredExtensions); ResultOrError<VulkanGlobalKnobs> CreateInstance(
bool CreateDevice(VulkanDeviceKnobs* usedKnobs); const std::vector<const char*>& requiredExtensions);
ResultOrError<VulkanDeviceKnobs> CreateDevice();
void GatherQueueFromDevice(); void GatherQueueFromDevice();
bool RegisterDebugReport(); MaybeError RegisterDebugReport();
static VKAPI_ATTR VkBool32 VKAPI_CALL static VKAPI_ATTR VkBool32 VKAPI_CALL
OnDebugReportCallback(VkDebugReportFlagsEXT flags, OnDebugReportCallback(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType, VkDebugReportObjectTypeEXT objectType,
@ -117,8 +118,8 @@ namespace dawn_native { namespace vulkan {
// the Device is allowed to mutate them through these private methods. // the Device is allowed to mutate them through these private methods.
VulkanFunctions* GetMutableFunctions(); VulkanFunctions* GetMutableFunctions();
VulkanGlobalInfo mGlobalInfo; VulkanGlobalInfo mGlobalInfo = {};
VulkanDeviceInfo mDeviceInfo; VulkanDeviceInfo mDeviceInfo = {};
DynamicLib mVulkanLib; DynamicLib mVulkanLib;

View File

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

View File

@ -22,29 +22,29 @@ namespace dawn_native { namespace vulkan {
#define GET_GLOBAL_PROC(name) \ #define GET_GLOBAL_PROC(name) \
name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(nullptr, "vk" #name)); \ name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(nullptr, "vk" #name)); \
if (name == nullptr) { \ if (name == nullptr) { \
return false; \ return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't get proc vk") + #name); \
} }
bool VulkanFunctions::LoadGlobalProcs(const DynamicLib& vulkanLib) { MaybeError VulkanFunctions::LoadGlobalProcs(const DynamicLib& vulkanLib) {
if (!vulkanLib.GetProc(&GetInstanceProcAddr, "vkGetInstanceProcAddr")) { if (!vulkanLib.GetProc(&GetInstanceProcAddr, "vkGetInstanceProcAddr")) {
return false; return DAWN_CONTEXT_LOST_ERROR("Couldn't get vkGetInstanceProcAddr");
} }
GET_GLOBAL_PROC(CreateInstance); GET_GLOBAL_PROC(CreateInstance);
GET_GLOBAL_PROC(EnumerateInstanceExtensionProperties); GET_GLOBAL_PROC(EnumerateInstanceExtensionProperties);
GET_GLOBAL_PROC(EnumerateInstanceLayerProperties); GET_GLOBAL_PROC(EnumerateInstanceLayerProperties);
return true; return {};
} }
#define GET_INSTANCE_PROC(name) \ #define GET_INSTANCE_PROC(name) \
name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(instance, "vk" #name)); \ name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(instance, "vk" #name)); \
if (name == nullptr) { \ if (name == nullptr) { \
return false; \ return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't get proc vk") + #name); \
} }
bool VulkanFunctions::LoadInstanceProcs(VkInstance instance, MaybeError VulkanFunctions::LoadInstanceProcs(VkInstance instance,
const VulkanGlobalKnobs& usedKnobs) { const VulkanGlobalKnobs& usedKnobs) {
// Load this proc first so that we can destroy the instance even if some other // Load this proc first so that we can destroy the instance even if some other
// GET_INSTANCE_PROC fails // GET_INSTANCE_PROC fails
GET_INSTANCE_PROC(DestroyInstance); GET_INSTANCE_PROC(DestroyInstance);
@ -77,16 +77,17 @@ namespace dawn_native { namespace vulkan {
GET_INSTANCE_PROC(GetPhysicalDeviceSurfacePresentModesKHR); GET_INSTANCE_PROC(GetPhysicalDeviceSurfacePresentModesKHR);
} }
return true; return {};
} }
#define GET_DEVICE_PROC(name) \ #define GET_DEVICE_PROC(name) \
name = reinterpret_cast<decltype(name)>(GetDeviceProcAddr(device, "vk" #name)); \ name = reinterpret_cast<decltype(name)>(GetDeviceProcAddr(device, "vk" #name)); \
if (name == nullptr) { \ if (name == nullptr) { \
return false; \ return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't get proc vk") + #name); \
} }
bool VulkanFunctions::LoadDeviceProcs(VkDevice device, const VulkanDeviceKnobs& usedKnobs) { MaybeError VulkanFunctions::LoadDeviceProcs(VkDevice device,
const VulkanDeviceKnobs& usedKnobs) {
GET_DEVICE_PROC(AllocateCommandBuffers); GET_DEVICE_PROC(AllocateCommandBuffers);
GET_DEVICE_PROC(AllocateDescriptorSets); GET_DEVICE_PROC(AllocateDescriptorSets);
GET_DEVICE_PROC(AllocateMemory); GET_DEVICE_PROC(AllocateMemory);
@ -215,7 +216,7 @@ namespace dawn_native { namespace vulkan {
GET_DEVICE_PROC(QueuePresentKHR); GET_DEVICE_PROC(QueuePresentKHR);
} }
return true; return {};
} }
}} // namespace dawn_native::vulkan }} // namespace dawn_native::vulkan

View File

@ -17,6 +17,8 @@
#include "common/vulkan_platform.h" #include "common/vulkan_platform.h"
#include "dawn_native/Error.h"
class DynamicLib; class DynamicLib;
namespace dawn_native { namespace vulkan { namespace dawn_native { namespace vulkan {
@ -27,9 +29,9 @@ namespace dawn_native { namespace vulkan {
// Stores the Vulkan entry points. Also loads them from the dynamic library // Stores the Vulkan entry points. Also loads them from the dynamic library
// and the vkGet*ProcAddress entry points. // and the vkGet*ProcAddress entry points.
struct VulkanFunctions { struct VulkanFunctions {
bool LoadGlobalProcs(const DynamicLib& vulkanLib); MaybeError LoadGlobalProcs(const DynamicLib& vulkanLib);
bool LoadInstanceProcs(VkInstance instance, const VulkanGlobalKnobs& usedGlobals); MaybeError LoadInstanceProcs(VkInstance instance, const VulkanGlobalKnobs& usedGlobals);
bool LoadDeviceProcs(VkDevice device, const VulkanDeviceKnobs& usedKnobs); MaybeError LoadDeviceProcs(VkDevice device, const VulkanDeviceKnobs& usedKnobs);
// ---------- Global procs // ---------- Global procs

View File

@ -38,7 +38,9 @@ namespace dawn_native { namespace vulkan {
const char kExtensionNameKhrSurface[] = "VK_KHR_surface"; const char kExtensionNameKhrSurface[] = "VK_KHR_surface";
const char kExtensionNameKhrSwapchain[] = "VK_KHR_swapchain"; const char kExtensionNameKhrSwapchain[] = "VK_KHR_swapchain";
bool GatherGlobalInfo(const Device& device, VulkanGlobalInfo* info) { ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Device& device) {
VulkanGlobalInfo info = {};
// Gather the info about the instance layers // Gather the info about the instance layers
{ {
uint32_t count = 0; uint32_t count = 0;
@ -47,24 +49,24 @@ namespace dawn_native { namespace vulkan {
// incomplete otherwise. This means that both values represent a success. // incomplete otherwise. This means that both values represent a success.
// This is the same for all Enumarte functions // This is the same for all Enumarte functions
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceLayerProperties");
} }
info->layers.resize(count); info.layers.resize(count);
result = device.fn.EnumerateInstanceLayerProperties(&count, info->layers.data()); result = device.fn.EnumerateInstanceLayerProperties(&count, info.layers.data());
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceLayerProperties");
} }
for (const auto& layer : info->layers) { for (const auto& layer : info.layers) {
if (IsLayerName(layer, kLayerNameLunargStandardValidation)) { if (IsLayerName(layer, kLayerNameLunargStandardValidation)) {
info->standardValidation = true; info.standardValidation = true;
} }
if (IsLayerName(layer, kLayerNameLunargVKTrace)) { if (IsLayerName(layer, kLayerNameLunargVKTrace)) {
info->vktrace = true; info.vktrace = true;
} }
if (IsLayerName(layer, kLayerNameRenderDocCapture)) { if (IsLayerName(layer, kLayerNameRenderDocCapture)) {
info->renderDocCapture = true; info.renderDocCapture = true;
} }
} }
} }
@ -75,65 +77,66 @@ namespace dawn_native { namespace vulkan {
VkResult result = VkResult result =
device.fn.EnumerateInstanceExtensionProperties(nullptr, &count, nullptr); device.fn.EnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceExtensionProperties");
} }
info->extensions.resize(count); info.extensions.resize(count);
result = device.fn.EnumerateInstanceExtensionProperties(nullptr, &count, result = device.fn.EnumerateInstanceExtensionProperties(nullptr, &count,
info->extensions.data()); info.extensions.data());
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceExtensionProperties");
} }
for (const auto& extension : info->extensions) { for (const auto& extension : info.extensions) {
if (IsExtensionName(extension, kExtensionNameExtDebugReport)) { if (IsExtensionName(extension, kExtensionNameExtDebugReport)) {
info->debugReport = true; info.debugReport = true;
} }
if (IsExtensionName(extension, kExtensionNameKhrSurface)) { if (IsExtensionName(extension, kExtensionNameKhrSurface)) {
info->surface = true; info.surface = true;
} }
} }
} }
// TODO(cwallez@chromium:org): Each layer can expose additional extensions, query them? // TODO(cwallez@chromium:org): Each layer can expose additional extensions, query them?
return true; return info;
} }
bool GetPhysicalDevices(const Device& device, std::vector<VkPhysicalDevice>* physicalDevices) { ResultOrError<std::vector<VkPhysicalDevice>> GetPhysicalDevices(const Device& device) {
VkInstance instance = device.GetInstance(); VkInstance instance = device.GetInstance();
uint32_t count = 0; uint32_t count = 0;
VkResult result = device.fn.EnumeratePhysicalDevices(instance, &count, nullptr); VkResult result = device.fn.EnumeratePhysicalDevices(instance, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkEnumeratePhysicalDevices");
} }
physicalDevices->resize(count); std::vector<VkPhysicalDevice> physicalDevices(count);
result = device.fn.EnumeratePhysicalDevices(instance, &count, physicalDevices->data()); result = device.fn.EnumeratePhysicalDevices(instance, &count, physicalDevices.data());
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkEnumeratePhysicalDevices");
} }
return true; return physicalDevices;
} }
bool GatherDeviceInfo(const Device& device, ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Device& device,
VkPhysicalDevice physicalDevice, VkPhysicalDevice physicalDevice) {
VulkanDeviceInfo* info) { VulkanDeviceInfo info = {};
// Gather general info about the device // Gather general info about the device
device.fn.GetPhysicalDeviceProperties(physicalDevice, &info->properties); device.fn.GetPhysicalDeviceProperties(physicalDevice, &info.properties);
device.fn.GetPhysicalDeviceFeatures(physicalDevice, &info->features); device.fn.GetPhysicalDeviceFeatures(physicalDevice, &info.features);
// Gather info about device memory. // Gather info about device memory.
{ {
VkPhysicalDeviceMemoryProperties memory; VkPhysicalDeviceMemoryProperties memory;
device.fn.GetPhysicalDeviceMemoryProperties(physicalDevice, &memory); device.fn.GetPhysicalDeviceMemoryProperties(physicalDevice, &memory);
info->memoryTypes.assign(memory.memoryTypes, info.memoryTypes.assign(memory.memoryTypes,
memory.memoryTypes + memory.memoryTypeCount); memory.memoryTypes + memory.memoryTypeCount);
info->memoryHeaps.assign(memory.memoryHeaps, info.memoryHeaps.assign(memory.memoryHeaps,
memory.memoryHeaps + memory.memoryHeapCount); memory.memoryHeaps + memory.memoryHeapCount);
} }
// Gather info about device queue families // Gather info about device queue families
@ -141,9 +144,9 @@ namespace dawn_native { namespace vulkan {
uint32_t count = 0; uint32_t count = 0;
device.fn.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr); device.fn.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr);
info->queueFamilies.resize(count); info.queueFamilies.resize(count);
device.fn.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, device.fn.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count,
info->queueFamilies.data()); info.queueFamilies.data());
} }
// Gather the info about the device layers // Gather the info about the device layers
@ -152,14 +155,14 @@ namespace dawn_native { namespace vulkan {
VkResult result = VkResult result =
device.fn.EnumerateDeviceLayerProperties(physicalDevice, &count, nullptr); device.fn.EnumerateDeviceLayerProperties(physicalDevice, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceLayerProperties");
} }
info->layers.resize(count); info.layers.resize(count);
result = device.fn.EnumerateDeviceLayerProperties(physicalDevice, &count, result = device.fn.EnumerateDeviceLayerProperties(physicalDevice, &count,
info->layers.data()); info.layers.data());
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceLayerProperties");
} }
} }
@ -169,29 +172,31 @@ namespace dawn_native { namespace vulkan {
VkResult result = device.fn.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, VkResult result = device.fn.EnumerateDeviceExtensionProperties(physicalDevice, nullptr,
&count, nullptr); &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceExtensionProperties");
} }
info->extensions.resize(count); info.extensions.resize(count);
result = device.fn.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &count, result = device.fn.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &count,
info->extensions.data()); info.extensions.data());
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceExtensionProperties");
} }
for (const auto& extension : info->extensions) { for (const auto& extension : info.extensions) {
if (IsExtensionName(extension, kExtensionNameKhrSwapchain)) { if (IsExtensionName(extension, kExtensionNameKhrSwapchain)) {
info->swapchain = true; info.swapchain = true;
} }
} }
} }
// TODO(cwallez@chromium.org): gather info about formats // TODO(cwallez@chromium.org): gather info about formats
return true; return info;
} }
bool GatherSurfaceInfo(const Device& device, VkSurfaceKHR surface, VulkanSurfaceInfo* info) { MaybeError GatherSurfaceInfo(const Device& device,
VkSurfaceKHR surface,
VulkanSurfaceInfo* info) {
VkPhysicalDevice physicalDevice = device.GetPhysicalDevice(); VkPhysicalDevice physicalDevice = device.GetPhysicalDevice();
// Get the surface capabilities // Get the surface capabilities
@ -199,7 +204,7 @@ namespace dawn_native { namespace vulkan {
VkResult result = device.fn.GetPhysicalDeviceSurfaceCapabilitiesKHR( VkResult result = device.fn.GetPhysicalDeviceSurfaceCapabilitiesKHR(
physicalDevice, surface, &info->capabilities); physicalDevice, surface, &info->capabilities);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
} }
} }
@ -214,7 +219,7 @@ namespace dawn_native { namespace vulkan {
surface, &supported); surface, &supported);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceSupportKHR");
} }
info->supportedQueueFamilies[i] = (supported == VK_TRUE); info->supportedQueueFamilies[i] = (supported == VK_TRUE);
@ -227,14 +232,14 @@ namespace dawn_native { namespace vulkan {
VkResult result = device.fn.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, VkResult result = device.fn.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface,
&count, nullptr); &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR");
} }
info->formats.resize(count); info->formats.resize(count);
result = device.fn.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &count, result = device.fn.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &count,
info->formats.data()); info->formats.data());
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR");
} }
} }
@ -244,18 +249,18 @@ namespace dawn_native { namespace vulkan {
VkResult result = device.fn.GetPhysicalDeviceSurfacePresentModesKHR( VkResult result = device.fn.GetPhysicalDeviceSurfacePresentModesKHR(
physicalDevice, surface, &count, nullptr); physicalDevice, surface, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfacePresentModesKHR");
} }
info->presentModes.resize(count); info->presentModes.resize(count);
result = device.fn.GetPhysicalDeviceSurfacePresentModesKHR( result = device.fn.GetPhysicalDeviceSurfacePresentModesKHR(
physicalDevice, surface, &count, info->presentModes.data()); physicalDevice, surface, &count, info->presentModes.data());
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return false; return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfacePresentModesKHR");
} }
} }
return true; return {};
} }
}} // namespace dawn_native::vulkan }} // namespace dawn_native::vulkan

View File

@ -16,6 +16,7 @@
#define DAWNNATIVE_VULKAN_VULKANINFO_H_ #define DAWNNATIVE_VULKAN_VULKANINFO_H_
#include "common/vulkan_platform.h" #include "common/vulkan_platform.h"
#include "dawn_native/Error.h"
#include <vector> #include <vector>
@ -76,13 +77,13 @@ namespace dawn_native { namespace vulkan {
std::vector<bool> supportedQueueFamilies; std::vector<bool> supportedQueueFamilies;
}; };
bool GatherGlobalInfo(const Device& device, VulkanGlobalInfo* info); ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Device& device);
bool GetPhysicalDevices(const Device& device, std::vector<VkPhysicalDevice>* physicalDevices); ResultOrError<std::vector<VkPhysicalDevice>> GetPhysicalDevices(const Device& device);
bool GatherDeviceInfo(const Device& device, ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Device& device,
VkPhysicalDevice physicalDevice, VkPhysicalDevice physicalDevice);
VulkanDeviceInfo* info); MaybeError GatherSurfaceInfo(const Device& device,
bool GatherSurfaceInfo(const Device& device, VkSurfaceKHR surface, VulkanSurfaceInfo* info); VkSurfaceKHR surface,
VulkanSurfaceInfo* info);
}} // namespace dawn_native::vulkan }} // namespace dawn_native::vulkan
#endif // DAWNNATIVE_VULKAN_VULKANINFO_H_ #endif // DAWNNATIVE_VULKAN_VULKANINFO_H_