Merge pull request #55020 from bruvzg/vlk_device_surface_check
This commit is contained in:
commit
d9a4ff7583
5 changed files with 219 additions and 124 deletions
|
@ -186,6 +186,10 @@ bool Engine::is_abort_on_gpu_errors_enabled() const {
|
|||
return abort_on_gpu_errors;
|
||||
}
|
||||
|
||||
int32_t Engine::get_gpu_index() const {
|
||||
return gpu_idx;
|
||||
}
|
||||
|
||||
bool Engine::is_validation_layers_enabled() const {
|
||||
return use_validation_layers;
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ private:
|
|||
double _physics_interpolation_fraction = 0.0f;
|
||||
bool abort_on_gpu_errors = false;
|
||||
bool use_validation_layers = false;
|
||||
int32_t gpu_idx = -1;
|
||||
|
||||
uint64_t _process_frames = 0;
|
||||
bool _in_physics = false;
|
||||
|
@ -135,6 +136,7 @@ public:
|
|||
|
||||
bool is_abort_on_gpu_errors_enabled() const;
|
||||
bool is_validation_layers_enabled() const;
|
||||
int32_t get_gpu_index() const;
|
||||
|
||||
Engine();
|
||||
virtual ~Engine() {}
|
||||
|
|
|
@ -615,7 +615,7 @@ Error VulkanContext::_check_capabilities() {
|
|||
return OK;
|
||||
}
|
||||
|
||||
Error VulkanContext::_create_physical_device() {
|
||||
Error VulkanContext::_create_instance() {
|
||||
/* obtain version */
|
||||
_obtain_vulkan_version();
|
||||
|
||||
|
@ -678,8 +678,6 @@ Error VulkanContext::_create_physical_device() {
|
|||
inst_info.pNext = &dbg_report_callback_create_info;
|
||||
}
|
||||
|
||||
uint32_t gpu_count;
|
||||
|
||||
VkResult err = vkCreateInstance(&inst_info, nullptr, &inst);
|
||||
ERR_FAIL_COND_V_MSG(err == VK_ERROR_INCOMPATIBLE_DRIVER, ERR_CANT_CREATE,
|
||||
"Cannot find a compatible Vulkan installable client driver (ICD).\n\n"
|
||||
|
@ -700,10 +698,85 @@ Error VulkanContext::_create_physical_device() {
|
|||
volkLoadInstance(inst);
|
||||
#endif
|
||||
|
||||
/* Make initial call to query gpu_count, then second call for gpu info*/
|
||||
err = vkEnumeratePhysicalDevices(inst, &gpu_count, nullptr);
|
||||
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
"vkEnumeratePhysicalDevices reported zero accessible devices.\n\n"
|
||||
"Do you have a compatible Vulkan installable client driver (ICD) installed?\n"
|
||||
|
@ -716,36 +789,6 @@ Error VulkanContext::_create_physical_device() {
|
|||
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 {
|
||||
uint32_t id;
|
||||
const char *name;
|
||||
|
@ -759,6 +802,119 @@ Error VulkanContext::_create_physical_device() {
|
|||
{ 0x8086, "Intel" },
|
||||
{ 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_type = gpu_props.deviceType;
|
||||
pipeline_cache_id = String::hex_encode_buffer(gpu_props.pipelineCacheUUID, VK_UUID_SIZE);
|
||||
|
@ -851,77 +1007,6 @@ Error VulkanContext::_create_physical_device() {
|
|||
" extension.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\n"
|
||||
"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 */
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, nullptr);
|
||||
ERR_FAIL_COND_V(queue_family_count == 0, ERR_CANT_CREATE);
|
||||
|
@ -957,6 +1042,7 @@ Error VulkanContext::_create_physical_device() {
|
|||
}
|
||||
}
|
||||
|
||||
device_initialized = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -1209,25 +1295,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) {
|
||||
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) {
|
||||
// We use a single GPU, but we need a surface to initialize the
|
||||
// queues, so this process must be deferred until a surface
|
||||
// is created.
|
||||
Error err = _initialize_queues(p_surface);
|
||||
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;
|
||||
|
@ -1694,12 +1772,12 @@ Error VulkanContext::initialize() {
|
|||
return FAILED;
|
||||
}
|
||||
#endif
|
||||
Error err = _create_physical_device();
|
||||
if (err) {
|
||||
|
||||
Error err = _create_instance();
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
device_initialized = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -224,7 +224,9 @@ private:
|
|||
const char *pMessage,
|
||||
void *pUserData);
|
||||
|
||||
Error _create_physical_device();
|
||||
Error _create_instance();
|
||||
|
||||
Error _create_physical_device(VkSurfaceKHR p_surface);
|
||||
|
||||
Error _initialize_queues(VkSurfaceKHR p_surface);
|
||||
|
||||
|
|
|
@ -325,6 +325,7 @@ void Main::print_help(const char *p_binary) {
|
|||
OS::get_singleton()->print("].\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");
|
||||
|
||||
|
@ -793,6 +794,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
|
||||
|
||||
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") {
|
||||
Engine::singleton->use_validation_layers = true;
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
|
Loading…
Reference in a new issue