From c962da0ddb4ac458171bafd26719c849fc8f5c30 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Thu, 13 Jun 2019 12:47:08 -0400 Subject: [PATCH] add video setting to select gpu (currently implemented for vulkan) --- config.def.h | 4 ++++ configuration.c | 3 +++ configuration.h | 3 +++ gfx/common/vulkan_common.c | 42 +++++++++++++++++++++++++++++++++++++- gfx/video_driver.c | 39 +++++++++++++++++++++++++++++++++++ gfx/video_driver.h | 6 ++++++ intl/msg_hash_ja.h | 2 ++ intl/msg_hash_lbl.h | 2 ++ intl/msg_hash_us.h | 2 ++ menu/cbs/menu_cbs_left.c | 34 ++++++++++++++++++++++++++++++ menu/cbs/menu_cbs_right.c | 34 ++++++++++++++++++++++++++++++ menu/menu_displaylist.c | 3 +++ menu/menu_setting.c | 39 ++++++++++++++++++++++++++++++++++- msg_hash.h | 1 + 14 files changed, 212 insertions(+), 2 deletions(-) diff --git a/config.def.h b/config.def.h index 3ec80177eb..55ffb2e530 100644 --- a/config.def.h +++ b/config.def.h @@ -868,6 +868,10 @@ static const bool sustained_performance_mode = false; static const bool vibrate_on_keypress = false; static const bool enable_device_vibration = false; +#ifdef HAVE_VULKAN +static const int vulkan_gpu_index = 0; +#endif + #if defined(HAKCHI) static char buildbot_server_url[] = "http://hakchicloud.com/Libretro_Cores/"; #elif defined(ANDROID) diff --git a/configuration.c b/configuration.c index 3674e0e220..d81bf48efd 100644 --- a/configuration.c +++ b/configuration.c @@ -1885,6 +1885,9 @@ static struct config_int_setting *populate_settings_int(settings_t *settings, in SETTING_INT("audio_wasapi_sh_buffer_length", &settings->ints.audio_wasapi_sh_buffer_length, true, wasapi_sh_buffer_length, false); #endif SETTING_INT("crt_switch_center_adjust", &settings->ints.crt_switch_center_adjust, false, 0 /* TODO */, false); +#ifdef HAVE_VULKAN + SETTING_INT("vulkan_gpu_index", &settings->ints.vulkan_gpu_index, true, vulkan_gpu_index, false); +#endif *size = count; diff --git a/configuration.h b/configuration.h index 6f47f1f56b..8a33d8fd34 100644 --- a/configuration.h +++ b/configuration.h @@ -388,6 +388,9 @@ typedef struct settings int state_slot; int audio_wasapi_sh_buffer_length; int crt_switch_center_adjust; +#ifdef HAVE_VULKAN + int vulkan_gpu_index; +#endif } ints; struct diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index 16b1faf9ee..83ec6ab279 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -35,6 +35,7 @@ #include "vksym.h" #include #include +#include #define VENDOR_ID_AMD 0x1002 #define VENDOR_ID_NV 0x10DE @@ -48,6 +49,7 @@ static dylib_t vulkan_library; static VkInstance cached_instance_vk; static VkDevice cached_device_vk; static retro_vulkan_destroy_device_t cached_destroy_device_vk; +static struct string_list *vulkan_gpu_list = NULL; //#define WSI_HARDENING_TEST #ifdef WSI_HARDENING_TEST @@ -1596,6 +1598,9 @@ static bool vulkan_context_init_gpu(gfx_ctx_vulkan_data_t *vk) { uint32_t gpu_count = 0; VkPhysicalDevice *gpus = NULL; + int i; + union string_list_elem_attr attr = {0}; + settings_t *settings = config_get_ptr(); if (vk->context.gpu != VK_NULL_HANDLE) return true; @@ -1629,7 +1634,36 @@ static bool vulkan_context_init_gpu(gfx_ctx_vulkan_data_t *vk) return false; } - vk->context.gpu = gpus[0]; + if (vulkan_gpu_list) + string_list_free(vulkan_gpu_list); + + vulkan_gpu_list = string_list_new(); + + for (i = 0; i < gpu_count; i++) + { + VkPhysicalDeviceProperties gpu_properties; + + vkGetPhysicalDeviceProperties(gpus[i], + &gpu_properties); + + RARCH_LOG("[Vulkan]: Found GPU: %s\n", gpu_properties.deviceName); + + string_list_append(vulkan_gpu_list, gpu_properties.deviceName, attr); + } + + video_driver_set_gpu_api_devices(GFX_CTX_VULKAN_API, vulkan_gpu_list); + + if (0 <= settings->ints.vulkan_gpu_index && settings->ints.vulkan_gpu_index < gpu_count) + { + RARCH_LOG("[Vulkan]: Using GPU index %d.\n", settings->ints.vulkan_gpu_index); + vk->context.gpu = gpus[settings->ints.vulkan_gpu_index]; + } + else + { + RARCH_WARN("[Vulkan]: Invalid GPU index %d, using first device found.\n", settings->ints.vulkan_gpu_index); + vk->context.gpu = gpus[0]; + } + free(gpus); return true; } @@ -2650,6 +2684,12 @@ void vulkan_context_destroy(gfx_ctx_vulkan_data_t *vk, } } } + + if (vulkan_gpu_list) + { + string_list_free(vulkan_gpu_list); + vulkan_gpu_list = NULL; + } } static void vulkan_acquire_clear_fences(gfx_ctx_vulkan_data_t *vk) diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 55eafa3102..2bebde5025 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -436,6 +437,15 @@ static const gfx_ctx_driver_t *gfx_ctx_drivers[] = { NULL }; +typedef struct { + enum gfx_ctx_api api; + struct string_list *list; +} gfx_api_gpu_map; + +static gfx_api_gpu_map gpu_map[] = { + { GFX_CTX_VULKAN_API, NULL } +}; + bool video_driver_started_fullscreen(void) { return video_started_fullscreen; @@ -3353,3 +3363,32 @@ const char* video_driver_get_gpu_api_version_string(void) { return video_driver_gpu_api_version_string; } + +/* string list stays owned by the caller and must be available at all times after the video driver is inited */ +void video_driver_set_gpu_api_devices(enum gfx_ctx_api api, struct string_list *list) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(gpu_map); i++) + { + if (api == gpu_map[i].api) + { + gpu_map[i].list = list; + break; + } + } +} + +struct string_list* video_driver_get_gpu_api_devices(enum gfx_ctx_api api) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(gpu_map); i++) + { + if (api == gpu_map[i].api) + return gpu_map[i].list; + } + + return NULL; +} + diff --git a/gfx/video_driver.h b/gfx/video_driver.h index 8115b64e25..d53bcceebc 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef HAVE_CONFIG_H #include "../config.h" @@ -1211,6 +1212,11 @@ void video_driver_set_gpu_api_version_string(const char *str); const char* video_driver_get_gpu_api_version_string(void); +/* string list stays owned by the caller and must be available at all times after the video driver is inited */ +void video_driver_set_gpu_api_devices(enum gfx_ctx_api api, struct string_list *list); + +struct string_list* video_driver_get_gpu_api_devices(enum gfx_ctx_api api); + static INLINE bool gl_set_core_context(enum retro_hw_context_type ctx_type) { gfx_ctx_flags_t flags; diff --git a/intl/msg_hash_ja.h b/intl/msg_hash_ja.h index d8abeb5dbb..27aaa87585 100644 --- a/intl/msg_hash_ja.h +++ b/intl/msg_hash_ja.h @@ -8945,3 +8945,5 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_XMB_ANIMATION_OPENING_MAIN_MENU, "メインメニュー開閉時のアニメーション" ) +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_GPU_INDEX, + "GPUインデックス") diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 20cef02698..7216f94eb9 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -1917,3 +1917,5 @@ MSG_HASH(MENU_ENUM_LABEL_MENU_XMB_ANIMATION_OPENING_MAIN_MENU, "xmb_menu_animation_opening_main_menu") MSG_HASH(MENU_ENUM_LABEL_VIDEO_RECORD_THREADS, "video_record_threads") +MSG_HASH(MENU_ENUM_LABEL_VIDEO_GPU_INDEX, + "gpu_index") diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 81c892fbeb..2ad7bc4b6b 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -8877,3 +8877,5 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_XMB_ANIMATION_MOVE_UP_DOWN, "Animation Move Up/Down") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_XMB_ANIMATION_OPENING_MAIN_MENU, "Animation Main Menu Opens/Closes") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_GPU_INDEX, + "GPU Index") diff --git a/menu/cbs/menu_cbs_left.c b/menu/cbs/menu_cbs_left.c index 11fa9744d8..e8373889e0 100644 --- a/menu/cbs/menu_cbs_left.c +++ b/menu/cbs/menu_cbs_left.c @@ -444,6 +444,37 @@ static int disk_options_disk_idx_left(unsigned type, const char *label, return 0; } +static int action_left_video_gpu_index(unsigned type, const char *label, + bool wraparound) +{ + settings_t *settings = config_get_ptr(); + enum gfx_ctx_api api = video_context_driver_get_api(); + + switch (api) + { +#ifdef HAVE_VULKAN + case GFX_CTX_VULKAN_API: + { + struct string_list *list = video_driver_get_gpu_api_devices(api); + + if (list) + { + if (settings->ints.vulkan_gpu_index > 0) + settings->ints.vulkan_gpu_index--; + else + settings->ints.vulkan_gpu_index = list->size - 1; + } + + break; + } +#endif + default: + break; + } + + return 0; +} + static int bind_left_generic(unsigned type, const char *label, bool wraparound) { @@ -571,6 +602,9 @@ static int menu_cbs_init_bind_left_compare_label(menu_file_list_cbs_t *cbs, BIND_ACTION_LEFT(cbs, action_left_mainmenu); break; } + case MENU_ENUM_LABEL_VIDEO_GPU_INDEX: + BIND_ACTION_LEFT(cbs, action_left_video_gpu_index); + break; default: return -1; } diff --git a/menu/cbs/menu_cbs_right.c b/menu/cbs/menu_cbs_right.c index 31ef9963af..1d16f9043c 100644 --- a/menu/cbs/menu_cbs_right.c +++ b/menu/cbs/menu_cbs_right.c @@ -371,6 +371,37 @@ static int action_right_shader_num_passes(unsigned type, const char *label, return 0; } +static int action_right_video_gpu_index(unsigned type, const char *label, + bool wraparound) +{ + settings_t *settings = config_get_ptr(); + enum gfx_ctx_api api = video_context_driver_get_api(); + + switch (api) + { +#ifdef HAVE_VULKAN + case GFX_CTX_VULKAN_API: + { + struct string_list *list = video_driver_get_gpu_api_devices(api); + + if (list) + { + if (settings->ints.vulkan_gpu_index < list->size - 1) + settings->ints.vulkan_gpu_index++; + else if (settings->ints.vulkan_gpu_index == list->size - 1) + settings->ints.vulkan_gpu_index = 0; + } + + break; + } +#endif + default: + break; + } + + return 0; +} + static int action_right_shader_watch_for_changes(unsigned type, const char *label, bool wraparound) { @@ -706,6 +737,9 @@ static int menu_cbs_init_bind_right_compare_label(menu_file_list_cbs_t *cbs, BIND_ACTION_RIGHT(cbs, action_right_mainmenu); break; } + case MENU_ENUM_LABEL_VIDEO_GPU_INDEX: + BIND_ACTION_RIGHT(cbs, action_right_video_gpu_index); + break; default: return -1; } diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 3f734bb276..f31234d719 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -6151,6 +6151,9 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist_parse_settings_enum(info->list, MENU_ENUM_LABEL_VIDEO_MONITOR_INDEX, PARSE_ONLY_UINT, false); + menu_displaylist_parse_settings_enum(info->list, + MENU_ENUM_LABEL_VIDEO_GPU_INDEX, + PARSE_ONLY_INT, false); menu_displaylist_parse_settings_enum(info->list, MENU_ENUM_LABEL_VIDEO_FULLSCREEN, PARSE_ONLY_BOOL, false); diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 63c09edd05..48bd1829e1 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -784,6 +784,20 @@ int setting_generic_action_ok_default(rarch_setting_t *setting, bool wraparound) return 0; } +static void setting_get_string_representation_int_gpu_index(rarch_setting_t *setting, + char *s, size_t len) +{ + if (setting) + { + struct string_list *list = video_driver_get_gpu_api_devices(video_context_driver_get_api()); + + if (list && *setting->value.target.integer < list->size) + snprintf(s, len, "%d - %s", *setting->value.target.integer, list->elems[*setting->value.target.integer].data); + else + snprintf(s, len, "%d", *setting->value.target.integer); + } +} + static void setting_get_string_representation_int(rarch_setting_t *setting, char *s, size_t len) { @@ -4982,7 +4996,7 @@ static void menu_settings_list_current_add_range( unsigned idx = list_info->index - 1; if ((*list)[idx].type == ST_FLOAT) - (*list)[list_info->index - 1].ui_type + (*list)[list_info->index - 1].ui_type = ST_UI_TYPE_FLOAT_SLIDER_AND_SPINBOX; (*list)[idx].min = min; @@ -8331,6 +8345,29 @@ static bool setting_append_list( (*list)[list_info->index - 1].get_string_representation = &setting_get_string_representation_uint_video_monitor_index; + /* prevent unused function warning on unsupported builds */ + (void)setting_get_string_representation_int_gpu_index; + +#ifdef HAVE_VULKAN + if (string_is_equal(video_driver_get_ident(), "vulkan")) + { + CONFIG_INT( + list, list_info, + &settings->ints.vulkan_gpu_index, + MENU_ENUM_LABEL_VIDEO_GPU_INDEX, + MENU_ENUM_LABEL_VALUE_VIDEO_GPU_INDEX, + 0, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + menu_settings_list_current_add_range(list, list_info, 0, 15, 1, true, true); + (*list)[list_info->index - 1].get_string_representation = + &setting_get_string_representation_int_gpu_index; + } +#endif + if (video_driver_has_windowed()) { CONFIG_BOOL( diff --git a/msg_hash.h b/msg_hash.h index 3ab0514c19..31e7cf2b8c 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -2414,6 +2414,7 @@ enum msg_hash_enums MENU_LABEL(VIBRATE_ON_KEYPRESS), MENU_LABEL(ENABLE_DEVICE_VIBRATION), + MENU_LABEL(VIDEO_GPU_INDEX), MSG_LAST };