The open source OpenXR runtime

c/main: fix missing vk instance extensions for comp_window_peek

Depending on the start-up config, when comp_window_peek
is enabled, in some cases the required Vulkan instance
extensions for SDL2 are not being enabled, causing
functions such as SDL_Vulkan_CreateSurface to fail.

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2561>

authored by

Korcan Hussein and committed by
Marge Bot
eaff7a09 2ed83e87

+110 -3
+18
src/xrt/compositor/main/comp_compositor.c
··· 609 609 }; 610 610 611 611 static bool 612 + select_instances_extensions(struct comp_compositor *c, struct u_string_list *required, struct u_string_list *optional) 613 + { 614 + #ifdef XRT_FEATURE_WINDOW_PEEK 615 + if (!comp_window_peek_get_vk_instance_exts(required)) { 616 + COMP_ERROR(c, "Failed to get required vulkan instance extensions for peek window."); 617 + return false; 618 + } 619 + #endif 620 + return true; 621 + } 622 + 623 + static bool 612 624 compositor_init_vulkan(struct comp_compositor *c) 613 625 { 614 626 COMP_TRACE_MARKER(); ··· 643 655 optional_instance_extensions, // 644 656 ARRAY_SIZE(optional_instance_extensions)); // 645 657 658 + if (!select_instances_extensions(c, required_instance_ext_list, optional_instance_ext_list)) { 659 + COMP_ERROR(c, "Failed to select additional instance extensions."); 660 + u_string_list_destroy(&required_instance_ext_list); 661 + u_string_list_destroy(&optional_instance_ext_list); 662 + return false; 663 + } 646 664 647 665 /* 648 666 * Device extensions.
+82 -3
src/xrt/compositor/main/comp_window_peek.c
··· 13 13 #include "main/comp_window_peek.h" 14 14 15 15 #include "util/u_debug.h" 16 + #include "util/u_string_list.h" 16 17 17 18 #ifdef XRT_HAVE_SDL2 18 19 #include <SDL2/SDL.h> ··· 185 186 * SDL 186 187 */ 187 188 188 - if (SDL_Init(SDL_INIT_VIDEO) < 0) { 189 - COMP_ERROR(c, "Failed to init SDL2"); 190 - goto err_pool; 189 + // Only initialize SDL if it hasn't been initialized yet 190 + if (SDL_WasInit(SDL_INIT_VIDEO) == 0) { 191 + if (SDL_Init(SDL_INIT_VIDEO) < 0) { 192 + COMP_ERROR(c, "Failed to init SDL2"); 193 + goto err_pool; 194 + } 191 195 } 196 + 192 197 193 198 int x = SDL_WINDOWPOS_UNDEFINED; 194 199 int y = SDL_WINDOWPOS_UNDEFINED; ··· 466 471 { 467 472 return w->eye; 468 473 } 474 + 475 + bool 476 + comp_window_peek_get_vk_instance_exts(struct u_string_list *out_required_list) 477 + { 478 + if (out_required_list == NULL) { 479 + U_LOG_E("comp_window_peek: out_required_list is null."); 480 + return false; 481 + } 482 + 483 + // Only initialize SDL if it hasn't been initialized yet 484 + if (SDL_WasInit(SDL_INIT_VIDEO) == 0) { 485 + if (SDL_Init(SDL_INIT_VIDEO) < 0) { 486 + U_LOG_E("comp_window_peek: Failed to init SDL2"); 487 + return false; 488 + } 489 + } 490 + 491 + /*! 492 + * NOTE: The SDL2 function SDL_Vulkan_GetInstanceExtensions requires an SDL_Window 493 + * but the compositor needs to know which vk (instance) extensions are required 494 + * much earlier than when comp_window_peek is created. 495 + * 496 + * API docs for SDL_Vulkan_GetInstanceExtensions states that in future versions 497 + * this parameter will be removed so for now just create a temporary, tiny window. 498 + */ 499 + 500 + const char **instance_ext_names = NULL; 501 + const int x = SDL_WINDOWPOS_UNDEFINED; 502 + const int y = SDL_WINDOWPOS_UNDEFINED; 503 + const int flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_VULKAN; 504 + SDL_Window *tmp_window = SDL_CreateWindow(__func__, x, y, 2, 2, flags); 505 + if (tmp_window == NULL) { 506 + U_LOG_E("comp_window_peek: Failed create temp SDL_Window for getting vk instance extensions."); 507 + return false; 508 + } 509 + 510 + /*! 511 + * WARNING: The extension name strings will not be deeply copied, the docs for 512 + * SDL_Vulkan_GetInstanceExtensions do not state the life time of these strings. 513 + * 514 + * based on looking the current codebase these are copied from function-level static 515 + * arrays containing string literals (expanded from vulkan header macros, e.g. VK_FOO_EXTENSION_NAME) 516 + * so we can assume it's safe to pass around but future versions this may change, 517 + * they may get destroyed when deleting the SDL_Window (although check note comment above). 518 + */ 519 + 520 + uint32_t size = 0; 521 + if (!SDL_Vulkan_GetInstanceExtensions(tmp_window, &size, NULL)) { 522 + U_LOG_E("comp_window_peek: Failed Failed get vk instance extensions for SDL2."); 523 + goto err_free; 524 + } 525 + 526 + if (size > 0) { 527 + instance_ext_names = U_TYPED_ARRAY_CALLOC(const char *, size); 528 + if (!SDL_Vulkan_GetInstanceExtensions(tmp_window, &size, instance_ext_names)) { 529 + U_LOG_E("comp_window_peek: Failed Failed get vk instance extensions for SDL2."); 530 + goto err_free; 531 + } 532 + } 533 + 534 + for (uint32_t i = 0; i < size; ++i) { 535 + if (u_string_list_append_unique(out_required_list, instance_ext_names[i]) == 0) { 536 + U_LOG_T("comp_window_peek: required instance extension: %s already exits, ignored.", 537 + instance_ext_names[i]); 538 + } else { 539 + U_LOG_T("comp_window_peek: added required instance extension: %s", instance_ext_names[i]); 540 + } 541 + } 542 + 543 + err_free: 544 + free(instance_ext_names); 545 + SDL_DestroyWindow(tmp_window); 546 + return true; 547 + }
+10
src/xrt/compositor/main/comp_window_peek.h
··· 53 53 enum comp_window_peek_eye 54 54 comp_window_peek_get_eye(struct comp_window_peek *w); 55 55 56 + /*! 57 + * Gets the required vulkan instance extensions for comp_window_peek support 58 + * 59 + * @param[inout] out_required_list list of string containing the required instance extensions to enable, 60 + * the list may already contain some/all of the required, duplicates will 61 + * not be added. 62 + */ 63 + bool 64 + comp_window_peek_get_vk_instance_exts(struct u_string_list *out_required_list); 65 + 56 66 #ifdef __cplusplus 57 67 } 58 68 #endif