[Vulkan] Check each device capabilities before selecting it.
Split instance and physical device selection function and move device selection to window creation, to reject devices without present capability. Add device preferred type check in discrete > integrated > virtual > cpu > other order. Add device list printout. Add command line argument to override device selection.
This commit is contained in:
parent
f2beac49bb
commit
b11e619b19
|
@ -186,6 +186,10 @@ bool Engine::is_abort_on_gpu_errors_enabled() const {
|
||||||
return abort_on_gpu_errors;
|
return abort_on_gpu_errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t Engine::get_gpu_index() const {
|
||||||
|
return gpu_idx;
|
||||||
|
}
|
||||||
|
|
||||||
bool Engine::is_validation_layers_enabled() const {
|
bool Engine::is_validation_layers_enabled() const {
|
||||||
return use_validation_layers;
|
return use_validation_layers;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ private:
|
||||||
double _physics_interpolation_fraction = 0.0f;
|
double _physics_interpolation_fraction = 0.0f;
|
||||||
bool abort_on_gpu_errors = false;
|
bool abort_on_gpu_errors = false;
|
||||||
bool use_validation_layers = false;
|
bool use_validation_layers = false;
|
||||||
|
int32_t gpu_idx = -1;
|
||||||
|
|
||||||
uint64_t _process_frames = 0;
|
uint64_t _process_frames = 0;
|
||||||
bool _in_physics = false;
|
bool _in_physics = false;
|
||||||
|
@ -135,6 +136,7 @@ public:
|
||||||
|
|
||||||
bool is_abort_on_gpu_errors_enabled() const;
|
bool is_abort_on_gpu_errors_enabled() const;
|
||||||
bool is_validation_layers_enabled() const;
|
bool is_validation_layers_enabled() const;
|
||||||
|
int32_t get_gpu_index() const;
|
||||||
|
|
||||||
Engine();
|
Engine();
|
||||||
virtual ~Engine() {}
|
virtual ~Engine() {}
|
||||||
|
|
|
@ -597,7 +597,7 @@ Error VulkanContext::_check_capabilities() {
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error VulkanContext::_create_physical_device() {
|
Error VulkanContext::_create_instance() {
|
||||||
/* obtain version */
|
/* obtain version */
|
||||||
_obtain_vulkan_version();
|
_obtain_vulkan_version();
|
||||||
|
|
||||||
|
@ -662,8 +662,6 @@ Error VulkanContext::_create_physical_device() {
|
||||||
inst_info.pNext = &dbg_report_callback_create_info;
|
inst_info.pNext = &dbg_report_callback_create_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t gpu_count;
|
|
||||||
|
|
||||||
VkResult err = vkCreateInstance(&inst_info, nullptr, &inst);
|
VkResult err = vkCreateInstance(&inst_info, nullptr, &inst);
|
||||||
ERR_FAIL_COND_V_MSG(err == VK_ERROR_INCOMPATIBLE_DRIVER, ERR_CANT_CREATE,
|
ERR_FAIL_COND_V_MSG(err == VK_ERROR_INCOMPATIBLE_DRIVER, ERR_CANT_CREATE,
|
||||||
"Cannot find a compatible Vulkan installable client driver (ICD).\n\n"
|
"Cannot find a compatible Vulkan installable client driver (ICD).\n\n"
|
||||||
|
@ -684,10 +682,85 @@ Error VulkanContext::_create_physical_device() {
|
||||||
volkLoadInstance(inst);
|
volkLoadInstance(inst);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Make initial call to query gpu_count, then second call for gpu info*/
|
if (enabled_debug_utils) {
|
||||||
err = vkEnumeratePhysicalDevices(inst, &gpu_count, nullptr);
|
// Setup VK_EXT_debug_utils function pointers always (we use them for
|
||||||
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
|
// debug labels and names).
|
||||||
|
CreateDebugUtilsMessengerEXT =
|
||||||
|
(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugUtilsMessengerEXT");
|
||||||
|
DestroyDebugUtilsMessengerEXT =
|
||||||
|
(PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(inst, "vkDestroyDebugUtilsMessengerEXT");
|
||||||
|
SubmitDebugUtilsMessageEXT =
|
||||||
|
(PFN_vkSubmitDebugUtilsMessageEXT)vkGetInstanceProcAddr(inst, "vkSubmitDebugUtilsMessageEXT");
|
||||||
|
CmdBeginDebugUtilsLabelEXT =
|
||||||
|
(PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetInstanceProcAddr(inst, "vkCmdBeginDebugUtilsLabelEXT");
|
||||||
|
CmdEndDebugUtilsLabelEXT =
|
||||||
|
(PFN_vkCmdEndDebugUtilsLabelEXT)vkGetInstanceProcAddr(inst, "vkCmdEndDebugUtilsLabelEXT");
|
||||||
|
CmdInsertDebugUtilsLabelEXT =
|
||||||
|
(PFN_vkCmdInsertDebugUtilsLabelEXT)vkGetInstanceProcAddr(inst, "vkCmdInsertDebugUtilsLabelEXT");
|
||||||
|
SetDebugUtilsObjectNameEXT =
|
||||||
|
(PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(inst, "vkSetDebugUtilsObjectNameEXT");
|
||||||
|
if (nullptr == CreateDebugUtilsMessengerEXT || nullptr == DestroyDebugUtilsMessengerEXT ||
|
||||||
|
nullptr == SubmitDebugUtilsMessageEXT || nullptr == CmdBeginDebugUtilsLabelEXT ||
|
||||||
|
nullptr == CmdEndDebugUtilsLabelEXT || nullptr == CmdInsertDebugUtilsLabelEXT ||
|
||||||
|
nullptr == SetDebugUtilsObjectNameEXT) {
|
||||||
|
ERR_FAIL_V_MSG(ERR_CANT_CREATE,
|
||||||
|
"GetProcAddr: Failed to init VK_EXT_debug_utils\n"
|
||||||
|
"GetProcAddr: Failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
err = CreateDebugUtilsMessengerEXT(inst, &dbg_messenger_create_info, nullptr, &dbg_messenger);
|
||||||
|
switch (err) {
|
||||||
|
case VK_SUCCESS:
|
||||||
|
break;
|
||||||
|
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||||
|
ERR_FAIL_V_MSG(ERR_CANT_CREATE,
|
||||||
|
"CreateDebugUtilsMessengerEXT: out of host memory\n"
|
||||||
|
"CreateDebugUtilsMessengerEXT Failure");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERR_FAIL_V_MSG(ERR_CANT_CREATE,
|
||||||
|
"CreateDebugUtilsMessengerEXT: unknown failure\n"
|
||||||
|
"CreateDebugUtilsMessengerEXT Failure");
|
||||||
|
ERR_FAIL_V(ERR_CANT_CREATE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (enabled_debug_report) {
|
||||||
|
CreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT");
|
||||||
|
DebugReportMessageEXT = (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT");
|
||||||
|
DestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT");
|
||||||
|
|
||||||
|
if (nullptr == CreateDebugReportCallbackEXT || nullptr == DebugReportMessageEXT || nullptr == DestroyDebugReportCallbackEXT) {
|
||||||
|
ERR_FAIL_V_MSG(ERR_CANT_CREATE,
|
||||||
|
"GetProcAddr: Failed to init VK_EXT_debug_report\n"
|
||||||
|
"GetProcAddr: Failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
err = CreateDebugReportCallbackEXT(inst, &dbg_report_callback_create_info, nullptr, &dbg_debug_report);
|
||||||
|
switch (err) {
|
||||||
|
case VK_SUCCESS:
|
||||||
|
break;
|
||||||
|
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||||
|
ERR_FAIL_V_MSG(ERR_CANT_CREATE,
|
||||||
|
"CreateDebugReportCallbackEXT: out of host memory\n"
|
||||||
|
"CreateDebugReportCallbackEXT Failure");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERR_FAIL_V_MSG(ERR_CANT_CREATE,
|
||||||
|
"CreateDebugReportCallbackEXT: unknown failure\n"
|
||||||
|
"CreateDebugReportCallbackEXT Failure");
|
||||||
|
ERR_FAIL_V(ERR_CANT_CREATE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
|
||||||
|
/* Make initial call to query gpu_count, then second call for gpu info*/
|
||||||
|
uint32_t gpu_count = 0;
|
||||||
|
VkResult err = vkEnumeratePhysicalDevices(inst, &gpu_count, nullptr);
|
||||||
|
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
|
||||||
ERR_FAIL_COND_V_MSG(gpu_count == 0, ERR_CANT_CREATE,
|
ERR_FAIL_COND_V_MSG(gpu_count == 0, ERR_CANT_CREATE,
|
||||||
"vkEnumeratePhysicalDevices reported zero accessible devices.\n\n"
|
"vkEnumeratePhysicalDevices reported zero accessible devices.\n\n"
|
||||||
"Do you have a compatible Vulkan installable client driver (ICD) installed?\n"
|
"Do you have a compatible Vulkan installable client driver (ICD) installed?\n"
|
||||||
|
@ -700,36 +773,6 @@ Error VulkanContext::_create_physical_device() {
|
||||||
ERR_FAIL_V(ERR_CANT_CREATE);
|
ERR_FAIL_V(ERR_CANT_CREATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: At least on Linux Laptops integrated GPUs fail with Vulkan in many instances.
|
|
||||||
// The device should really be a preference, but for now choosing a discrete GPU over the
|
|
||||||
// integrated one is better than the default.
|
|
||||||
|
|
||||||
// Default to first device
|
|
||||||
uint32_t device_index = 0;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < gpu_count; ++i) {
|
|
||||||
VkPhysicalDeviceProperties props;
|
|
||||||
vkGetPhysicalDeviceProperties(physical_devices[i], &props);
|
|
||||||
|
|
||||||
if (props.deviceType == VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
|
|
||||||
// Prefer discrete GPU.
|
|
||||||
device_index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gpu = physical_devices[device_index];
|
|
||||||
free(physical_devices);
|
|
||||||
|
|
||||||
/* Look for device extensions */
|
|
||||||
uint32_t device_extension_count = 0;
|
|
||||||
VkBool32 swapchainExtFound = 0;
|
|
||||||
enabled_extension_count = 0;
|
|
||||||
memset(extension_names, 0, sizeof(extension_names));
|
|
||||||
|
|
||||||
/* Get identifier properties */
|
|
||||||
vkGetPhysicalDeviceProperties(gpu, &gpu_props);
|
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -743,6 +786,119 @@ Error VulkanContext::_create_physical_device() {
|
||||||
{ 0x8086, "Intel" },
|
{ 0x8086, "Intel" },
|
||||||
{ 0, nullptr },
|
{ 0, nullptr },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: At least on Linux Laptops integrated GPUs fail with Vulkan in many instances.
|
||||||
|
// The device should really be a preference, but for now choosing a discrete GPU over the
|
||||||
|
// integrated one is better than the default.
|
||||||
|
|
||||||
|
int32_t device_index = -1;
|
||||||
|
int type_selected = -1;
|
||||||
|
print_verbose("Vulkan devices:");
|
||||||
|
for (uint32_t i = 0; i < gpu_count; ++i) {
|
||||||
|
VkPhysicalDeviceProperties props;
|
||||||
|
vkGetPhysicalDeviceProperties(physical_devices[i], &props);
|
||||||
|
|
||||||
|
bool present_supported = false;
|
||||||
|
|
||||||
|
uint32_t device_queue_family_count = 0;
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &device_queue_family_count, nullptr);
|
||||||
|
VkQueueFamilyProperties *device_queue_props = (VkQueueFamilyProperties *)malloc(device_queue_family_count * sizeof(VkQueueFamilyProperties));
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &device_queue_family_count, device_queue_props);
|
||||||
|
for (uint32_t j = 0; j < device_queue_family_count; j++) {
|
||||||
|
VkBool32 supports;
|
||||||
|
vkGetPhysicalDeviceSurfaceSupportKHR(physical_devices[i], j, p_surface, &supports);
|
||||||
|
if (supports && ((device_queue_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)) {
|
||||||
|
present_supported = true;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String name = props.deviceName;
|
||||||
|
String vendor = "Unknown";
|
||||||
|
String dev_type;
|
||||||
|
switch (props.deviceType) {
|
||||||
|
case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: {
|
||||||
|
dev_type = "Discrete";
|
||||||
|
} break;
|
||||||
|
case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: {
|
||||||
|
dev_type = "Integrated";
|
||||||
|
} break;
|
||||||
|
case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: {
|
||||||
|
dev_type = "Virtual";
|
||||||
|
} break;
|
||||||
|
case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU: {
|
||||||
|
dev_type = "CPU";
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
dev_type = "Other";
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
uint32_t vendor_idx = 0;
|
||||||
|
while (vendor_names[vendor_idx].name != nullptr) {
|
||||||
|
if (props.vendorID == vendor_names[vendor_idx].id) {
|
||||||
|
vendor = vendor_names[vendor_idx].name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vendor_idx++;
|
||||||
|
}
|
||||||
|
free(device_queue_props);
|
||||||
|
print_verbose(" #" + itos(i) + ": " + vendor + " " + name + " - " + (present_supported ? "Supported" : "Unsupported") + ", " + dev_type);
|
||||||
|
|
||||||
|
if (present_supported) { // Select first supported device of preffered type: Discrete > Integrated > Virtual > CPU > Other.
|
||||||
|
switch (props.deviceType) {
|
||||||
|
case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: {
|
||||||
|
if (type_selected < 4) {
|
||||||
|
type_selected = 4;
|
||||||
|
device_index = i;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: {
|
||||||
|
if (type_selected < 3) {
|
||||||
|
type_selected = 3;
|
||||||
|
device_index = i;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: {
|
||||||
|
if (type_selected < 2) {
|
||||||
|
type_selected = 2;
|
||||||
|
device_index = i;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU: {
|
||||||
|
if (type_selected < 1) {
|
||||||
|
type_selected = 1;
|
||||||
|
device_index = i;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
if (type_selected < 0) {
|
||||||
|
type_selected = 0;
|
||||||
|
device_index = i;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t user_device_index = Engine::get_singleton()->get_gpu_index(); // Force user selected GPU.
|
||||||
|
if (user_device_index >= 0 && user_device_index < (int32_t)gpu_count) {
|
||||||
|
device_index = user_device_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V_MSG(device_index == -1, ERR_CANT_CREATE, "None of Vulkan devices supports both graphics and present queues.");
|
||||||
|
|
||||||
|
gpu = physical_devices[device_index];
|
||||||
|
free(physical_devices);
|
||||||
|
|
||||||
|
/* Look for device extensions */
|
||||||
|
uint32_t device_extension_count = 0;
|
||||||
|
VkBool32 swapchainExtFound = 0;
|
||||||
|
enabled_extension_count = 0;
|
||||||
|
memset(extension_names, 0, sizeof(extension_names));
|
||||||
|
|
||||||
|
/* Get identifier properties */
|
||||||
|
vkGetPhysicalDeviceProperties(gpu, &gpu_props);
|
||||||
|
|
||||||
device_name = gpu_props.deviceName;
|
device_name = gpu_props.deviceName;
|
||||||
pipeline_cache_id = String::hex_encode_buffer(gpu_props.pipelineCacheUUID, VK_UUID_SIZE);
|
pipeline_cache_id = String::hex_encode_buffer(gpu_props.pipelineCacheUUID, VK_UUID_SIZE);
|
||||||
pipeline_cache_id += "-driver-" + itos(gpu_props.driverVersion);
|
pipeline_cache_id += "-driver-" + itos(gpu_props.driverVersion);
|
||||||
|
@ -834,77 +990,6 @@ Error VulkanContext::_create_physical_device() {
|
||||||
" extension.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\n"
|
" extension.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\n"
|
||||||
"vkCreateInstance Failure");
|
"vkCreateInstance Failure");
|
||||||
|
|
||||||
if (enabled_debug_utils) {
|
|
||||||
// Setup VK_EXT_debug_utils function pointers always (we use them for
|
|
||||||
// debug labels and names).
|
|
||||||
CreateDebugUtilsMessengerEXT =
|
|
||||||
(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugUtilsMessengerEXT");
|
|
||||||
DestroyDebugUtilsMessengerEXT =
|
|
||||||
(PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(inst, "vkDestroyDebugUtilsMessengerEXT");
|
|
||||||
SubmitDebugUtilsMessageEXT =
|
|
||||||
(PFN_vkSubmitDebugUtilsMessageEXT)vkGetInstanceProcAddr(inst, "vkSubmitDebugUtilsMessageEXT");
|
|
||||||
CmdBeginDebugUtilsLabelEXT =
|
|
||||||
(PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetInstanceProcAddr(inst, "vkCmdBeginDebugUtilsLabelEXT");
|
|
||||||
CmdEndDebugUtilsLabelEXT =
|
|
||||||
(PFN_vkCmdEndDebugUtilsLabelEXT)vkGetInstanceProcAddr(inst, "vkCmdEndDebugUtilsLabelEXT");
|
|
||||||
CmdInsertDebugUtilsLabelEXT =
|
|
||||||
(PFN_vkCmdInsertDebugUtilsLabelEXT)vkGetInstanceProcAddr(inst, "vkCmdInsertDebugUtilsLabelEXT");
|
|
||||||
SetDebugUtilsObjectNameEXT =
|
|
||||||
(PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(inst, "vkSetDebugUtilsObjectNameEXT");
|
|
||||||
if (nullptr == CreateDebugUtilsMessengerEXT || nullptr == DestroyDebugUtilsMessengerEXT ||
|
|
||||||
nullptr == SubmitDebugUtilsMessageEXT || nullptr == CmdBeginDebugUtilsLabelEXT ||
|
|
||||||
nullptr == CmdEndDebugUtilsLabelEXT || nullptr == CmdInsertDebugUtilsLabelEXT ||
|
|
||||||
nullptr == SetDebugUtilsObjectNameEXT) {
|
|
||||||
ERR_FAIL_V_MSG(ERR_CANT_CREATE,
|
|
||||||
"GetProcAddr: Failed to init VK_EXT_debug_utils\n"
|
|
||||||
"GetProcAddr: Failure");
|
|
||||||
}
|
|
||||||
|
|
||||||
err = CreateDebugUtilsMessengerEXT(inst, &dbg_messenger_create_info, nullptr, &dbg_messenger);
|
|
||||||
switch (err) {
|
|
||||||
case VK_SUCCESS:
|
|
||||||
break;
|
|
||||||
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
|
||||||
ERR_FAIL_V_MSG(ERR_CANT_CREATE,
|
|
||||||
"CreateDebugUtilsMessengerEXT: out of host memory\n"
|
|
||||||
"CreateDebugUtilsMessengerEXT Failure");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERR_FAIL_V_MSG(ERR_CANT_CREATE,
|
|
||||||
"CreateDebugUtilsMessengerEXT: unknown failure\n"
|
|
||||||
"CreateDebugUtilsMessengerEXT Failure");
|
|
||||||
ERR_FAIL_V(ERR_CANT_CREATE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (enabled_debug_report) {
|
|
||||||
CreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT");
|
|
||||||
DebugReportMessageEXT = (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT");
|
|
||||||
DestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT");
|
|
||||||
|
|
||||||
if (nullptr == CreateDebugReportCallbackEXT || nullptr == DebugReportMessageEXT || nullptr == DestroyDebugReportCallbackEXT) {
|
|
||||||
ERR_FAIL_V_MSG(ERR_CANT_CREATE,
|
|
||||||
"GetProcAddr: Failed to init VK_EXT_debug_report\n"
|
|
||||||
"GetProcAddr: Failure");
|
|
||||||
}
|
|
||||||
|
|
||||||
err = CreateDebugReportCallbackEXT(inst, &dbg_report_callback_create_info, nullptr, &dbg_debug_report);
|
|
||||||
switch (err) {
|
|
||||||
case VK_SUCCESS:
|
|
||||||
break;
|
|
||||||
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
|
||||||
ERR_FAIL_V_MSG(ERR_CANT_CREATE,
|
|
||||||
"CreateDebugReportCallbackEXT: out of host memory\n"
|
|
||||||
"CreateDebugReportCallbackEXT Failure");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERR_FAIL_V_MSG(ERR_CANT_CREATE,
|
|
||||||
"CreateDebugReportCallbackEXT: unknown failure\n"
|
|
||||||
"CreateDebugReportCallbackEXT Failure");
|
|
||||||
ERR_FAIL_V(ERR_CANT_CREATE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call with nullptr data to get count */
|
/* Call with nullptr data to get count */
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, nullptr);
|
vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, nullptr);
|
||||||
ERR_FAIL_COND_V(queue_family_count == 0, ERR_CANT_CREATE);
|
ERR_FAIL_COND_V(queue_family_count == 0, ERR_CANT_CREATE);
|
||||||
|
@ -940,6 +1025,7 @@ Error VulkanContext::_create_physical_device() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device_initialized = true;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1192,25 +1278,17 @@ bool VulkanContext::_use_validation_layers() {
|
||||||
Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, VkSurfaceKHR p_surface, int p_width, int p_height) {
|
Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, VkSurfaceKHR p_surface, int p_width, int p_height) {
|
||||||
ERR_FAIL_COND_V(windows.has(p_window_id), ERR_INVALID_PARAMETER);
|
ERR_FAIL_COND_V(windows.has(p_window_id), ERR_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
if (!device_initialized) {
|
||||||
|
Error err = _create_physical_device(p_surface);
|
||||||
|
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
if (!queues_initialized) {
|
if (!queues_initialized) {
|
||||||
// We use a single GPU, but we need a surface to initialize the
|
// We use a single GPU, but we need a surface to initialize the
|
||||||
// queues, so this process must be deferred until a surface
|
// queues, so this process must be deferred until a surface
|
||||||
// is created.
|
// is created.
|
||||||
Error err = _initialize_queues(p_surface);
|
Error err = _initialize_queues(p_surface);
|
||||||
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
||||||
} else {
|
|
||||||
// make sure any of the surfaces supports present (validation layer complains if this is not done).
|
|
||||||
bool any_supports_present = false;
|
|
||||||
for (uint32_t i = 0; i < queue_family_count; i++) {
|
|
||||||
VkBool32 supports;
|
|
||||||
fpGetPhysicalDeviceSurfaceSupportKHR(gpu, i, p_surface, &supports);
|
|
||||||
if (supports) {
|
|
||||||
any_supports_present = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR_FAIL_COND_V_MSG(!any_supports_present, ERR_CANT_CREATE, "Surface passed for sub-window creation does not support presenting");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Window window;
|
Window window;
|
||||||
|
@ -1677,12 +1755,12 @@ Error VulkanContext::initialize() {
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Error err = _create_physical_device();
|
|
||||||
if (err) {
|
Error err = _create_instance();
|
||||||
|
if (err != OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
device_initialized = true;
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,9 @@ private:
|
||||||
const char *pMessage,
|
const char *pMessage,
|
||||||
void *pUserData);
|
void *pUserData);
|
||||||
|
|
||||||
Error _create_physical_device();
|
Error _create_instance();
|
||||||
|
|
||||||
|
Error _create_physical_device(VkSurfaceKHR p_surface);
|
||||||
|
|
||||||
Error _initialize_queues(VkSurfaceKHR p_surface);
|
Error _initialize_queues(VkSurfaceKHR p_surface);
|
||||||
|
|
||||||
|
|
|
@ -323,6 +323,7 @@ void Main::print_help(const char *p_binary) {
|
||||||
OS::get_singleton()->print("].\n");
|
OS::get_singleton()->print("].\n");
|
||||||
|
|
||||||
OS::get_singleton()->print(" --rendering-driver <driver> Rendering driver (depends on display driver).\n");
|
OS::get_singleton()->print(" --rendering-driver <driver> Rendering driver (depends on display driver).\n");
|
||||||
|
OS::get_singleton()->print(" --gpu-index <device_index> Use a specific GPU (run with --verbose to get available device list).\n");
|
||||||
|
|
||||||
OS::get_singleton()->print(" --text-driver <driver> Text driver (Fonts, BiDi, shaping)\n");
|
OS::get_singleton()->print(" --text-driver <driver> Text driver (Fonts, BiDi, shaping)\n");
|
||||||
|
|
||||||
|
@ -789,6 +790,14 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
||||||
} else if (I->get() == "-w" || I->get() == "--windowed") { // force windowed window
|
} else if (I->get() == "-w" || I->get() == "--windowed") { // force windowed window
|
||||||
|
|
||||||
init_windowed = true;
|
init_windowed = true;
|
||||||
|
} else if (I->get() == "--gpu-index") {
|
||||||
|
if (I->next()) {
|
||||||
|
Engine::singleton->gpu_idx = I->next()->get().to_int();
|
||||||
|
N = I->next()->next();
|
||||||
|
} else {
|
||||||
|
OS::get_singleton()->print("Missing gpu index argument, aborting.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
} else if (I->get() == "--vk-layers") {
|
} else if (I->get() == "--vk-layers") {
|
||||||
Engine::singleton->use_validation_layers = true;
|
Engine::singleton->use_validation_layers = true;
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
|
Loading…
Reference in New Issue