diff --git a/scripts/generate_vk_helpers.py b/scripts/generate_vk_helpers.py index bf53b9ab6..38fd456b8 100755 --- a/scripts/generate_vk_helpers.py +++ b/scripts/generate_vk_helpers.py @@ -219,7 +219,10 @@ def get_instance_cmds(): ] -EXTENSIONS_TO_CHECK = [ +INSTANCE_EXTENSIONS_TO_CHECK = [ + "VK_EXT_display_surface_counter", +] +DEVICE_EXTENSIONS_TO_CHECK = [ "VK_KHR_timeline_semaphore", "VK_EXT_global_priority", "VK_EXT_robustness2", @@ -353,24 +356,27 @@ def make_ext_name_define(ext: str): return "{}_EXTENSION_NAME".format(ext.upper()).replace("2", "_2") -def generate_ext_members(): - for ext in EXTENSIONS_TO_CHECK: +def generate_ext_members(exts): + for ext in exts: yield "\tbool {};".format(make_ext_member_name(ext)) -def generate_ext_check(): +def generate_ext_check(exts): yield "\t// Reset before filling out." - for ext in EXTENSIONS_TO_CHECK: + for ext in exts: yield "\tvk->{} = false;".format(make_ext_member_name(ext)) yield "" - yield "\tfor (uint32_t i = 0; i < device_extension_count; i++) {" - yield "\t\tconst char *ext = device_extensions[i];" + yield "\tconst char *const *exts = u_string_list_get_data(ext_list);" + yield "\tuint32_t ext_count = u_string_list_get_size(ext_list);" + yield "" + yield "\tfor (uint32_t i = 0; i < ext_count; i++) {" + yield "\t\tconst char *ext = exts[i];" yield "" conditional = ConditionalGenerator() - for ext in EXTENSIONS_TO_CHECK: + for ext in exts: condition_line = conditional.process_condition(compute_condition((ext,))) if condition_line: yield condition_line @@ -401,9 +407,13 @@ INSTANCE_TEMPLATES = { "BEGIN": BEGIN_TEMPLATE % "instance loader", "END": END_TEMPLATE % "instance loader", } +INSTANCE_EXT_TEMPLATES = { + "BEGIN": BEGIN_TEMPLATE % "instance extension", + "END": END_TEMPLATE % "instance extension", +} EXT_TEMPLATES = { - "BEGIN": BEGIN_TEMPLATE % "extension", - "END": END_TEMPLATE % "extension", + "BEGIN": BEGIN_TEMPLATE % "device extension", + "END": END_TEMPLATE % "device extension", } @@ -424,11 +434,19 @@ def process_header(): DEVICE_TEMPLATES["END"], list(generate_structure_members(get_device_cmds())), ) + + lines = replace_middle( + lines, + INSTANCE_EXT_TEMPLATES["BEGIN"], + INSTANCE_EXT_TEMPLATES["END"], + list(generate_ext_members(INSTANCE_EXTENSIONS_TO_CHECK)), + ) + lines = replace_middle( lines, EXT_TEMPLATES["BEGIN"], EXT_TEMPLATES["END"], - list(generate_ext_members()), + list(generate_ext_members(DEVICE_EXTENSIONS_TO_CHECK)), ) with open(str(HEADER_FN), "w", encoding="utf-8") as fp: @@ -454,11 +472,18 @@ def process_impl(): list(generate_proc_macro("GET_DEV_PROC", get_device_cmds())), ) + lines = replace_middle( + lines, + INSTANCE_EXT_TEMPLATES["BEGIN"], + INSTANCE_EXT_TEMPLATES["END"], + list(generate_ext_check(INSTANCE_EXTENSIONS_TO_CHECK)), + ) + lines = replace_middle( lines, EXT_TEMPLATES["BEGIN"], EXT_TEMPLATES["END"], - list(generate_ext_check()), + list(generate_ext_check(DEVICE_EXTENSIONS_TO_CHECK)), ) with open(str(IMPL_FN), "w", encoding="utf-8") as fp: diff --git a/src/xrt/auxiliary/vk/vk_helpers.c b/src/xrt/auxiliary/vk/vk_helpers.c index 0ba9a1023..eef1640e3 100644 --- a/src/xrt/auxiliary/vk/vk_helpers.c +++ b/src/xrt/auxiliary/vk/vk_helpers.c @@ -1230,18 +1230,44 @@ vk_check_extension(struct vk_bundle *vk, VkExtensionProperties *props, uint32_t return false; } -static void -fill_in_has_extensions(struct vk_bundle *vk, const char *const *device_extensions, uint32_t device_extension_count) +void +vk_fill_in_has_instance_extensions(struct vk_bundle *vk, struct u_string_list *ext_list) { - // beginning of GENERATED extension code - do not modify - used by scripts + // beginning of GENERATED instance extension code - do not modify - used by scripts + // Reset before filling out. + vk->has_EXT_display_surface_counter = false; + + const char *const *exts = u_string_list_get_data(ext_list); + uint32_t ext_count = u_string_list_get_size(ext_list); + + for (uint32_t i = 0; i < ext_count; i++) { + const char *ext = exts[i]; + +#if defined(VK_EXT_display_surface_counter) + if (strcmp(ext, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME) == 0) { + vk->has_EXT_display_surface_counter = true; + continue; + } +#endif // defined(VK_EXT_display_surface_counter) + } + // end of GENERATED instance extension code - do not modify - used by scripts +} + +static void +fill_in_has_device_extensions(struct vk_bundle *vk, struct u_string_list *ext_list) +{ + // beginning of GENERATED device extension code - do not modify - used by scripts // Reset before filling out. vk->has_KHR_timeline_semaphore = false; vk->has_EXT_global_priority = false; vk->has_EXT_robustness2 = false; vk->has_GOOGLE_display_timing = false; - for (uint32_t i = 0; i < device_extension_count; i++) { - const char *ext = device_extensions[i]; + const char *const *exts = u_string_list_get_data(ext_list); + uint32_t ext_count = u_string_list_get_size(ext_list); + + for (uint32_t i = 0; i < ext_count; i++) { + const char *ext = exts[i]; #if defined(VK_KHR_timeline_semaphore) if (strcmp(ext, VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME) == 0) { @@ -1271,7 +1297,82 @@ fill_in_has_extensions(struct vk_bundle *vk, const char *const *device_extension } #endif // defined(VK_GOOGLE_display_timing) } - // end of GENERATED extension code - do not modify - used by scripts + // end of GENERATED device extension code - do not modify - used by scripts +} + +static bool +vk_should_skip_optional_instance_ext(struct vk_bundle *vk, + struct u_string_list *required_instance_ext_list, + struct u_string_list *optional_instance_ext_listconst, + const char *ext) +{ +#ifdef VK_EXT_display_surface_counter + if (strcmp(ext, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME) == 0) { + // it does not make sense to enable surface counter on anything that does not use a VkDisplayKHR + if (!u_string_list_contains(required_instance_ext_list, VK_KHR_DISPLAY_EXTENSION_NAME)) { + VK_DEBUG(vk, "Skipping optional instance extension %s because %s is not enabled", ext, + VK_KHR_DISPLAY_EXTENSION_NAME); + return true; + } + VK_DEBUG(vk, "Not skipping optional instance extension %s because %s is enabled", ext, + VK_KHR_DISPLAY_EXTENSION_NAME); + } +#endif + return false; +} + +static bool +vk_is_instance_ext_supported(VkExtensionProperties *props, uint32_t prop_count, const char *ext) +{ + for (uint32_t j = 0; j < prop_count; j++) { + if (strcmp(ext, props[j].extensionName) == 0) { + return true; + } + } + return false; +} + +struct u_string_list * +vk_build_instance_extensions(struct vk_bundle *vk, + struct u_string_list *required_instance_ext_list, + struct u_string_list *optional_instance_ext_list) +{ + VkResult res; + + uint32_t prop_count = 0; + res = vk->vkEnumerateInstanceExtensionProperties(NULL, &prop_count, NULL); + vk_check_error("vkEnumerateInstanceExtensionProperties", res, NULL); + + VkExtensionProperties *props = U_TYPED_ARRAY_CALLOC(VkExtensionProperties, prop_count); + res = vk->vkEnumerateInstanceExtensionProperties(NULL, &prop_count, props); + vk_check_error_with_free("vkEnumerateInstanceExtensionProperties", res, NULL, props); + + struct u_string_list *ret = u_string_list_create_from_list(required_instance_ext_list); + + uint32_t optional_instance_ext_count = u_string_list_get_size(optional_instance_ext_list); + const char *const *optional_instance_exts = u_string_list_get_data(optional_instance_ext_list); + for (uint32_t i = 0; i < optional_instance_ext_count; i++) { + const char *optional_ext = optional_instance_exts[i]; + + if (vk_should_skip_optional_instance_ext(vk, required_instance_ext_list, optional_instance_ext_list, + optional_ext)) { + continue; + } + + if (!vk_is_instance_ext_supported(props, prop_count, optional_ext)) { + VK_DEBUG(vk, "Optional instance extension %s not enabled, unsupported", optional_ext); + continue; + } + + int added = u_string_list_append_unique(ret, optional_ext); + if (added == 1) { + VK_DEBUG(vk, "Using optional instance ext %s", optional_ext); + } else { + VK_WARN(vk, "Duplicate instance extension %s not added twice", optional_ext); + } + break; + } + return ret; } static VkResult @@ -1345,8 +1446,7 @@ vk_build_device_extensions(struct vk_bundle *vk, } // Fill this out here. - fill_in_has_extensions(vk, u_string_list_get_data(*out_device_ext_list), - u_string_list_get_size(*out_device_ext_list)); + fill_in_has_device_extensions(vk, *out_device_ext_list); free(props); diff --git a/src/xrt/auxiliary/vk/vk_helpers.h b/src/xrt/auxiliary/vk/vk_helpers.h index d9ba39d4c..bdc447a84 100644 --- a/src/xrt/auxiliary/vk/vk_helpers.h +++ b/src/xrt/auxiliary/vk/vk_helpers.h @@ -57,12 +57,16 @@ struct vk_bundle struct os_mutex queue_mutex; - // beginning of GENERATED extension code - do not modify - used by scripts + // beginning of GENERATED instance extension code - do not modify - used by scripts + bool has_EXT_display_surface_counter; + // end of GENERATED instance extension code - do not modify - used by scripts + + // beginning of GENERATED device extension code - do not modify - used by scripts bool has_KHR_timeline_semaphore; bool has_EXT_global_priority; bool has_EXT_robustness2; bool has_GOOGLE_display_timing; - // end of GENERATED extension code - do not modify - used by scripts + // end of GENERATED device extension code - do not modify - used by scripts bool is_tegra; @@ -426,6 +430,14 @@ struct vk_device_features bool timeline_semaphore; }; +/*! + * @ingroup aux_vk + */ +struct u_string_list * +vk_build_instance_extensions(struct vk_bundle *vk, + struct u_string_list *required_instance_ext_list, + struct u_string_list *optional_instance_ext_list); + /*! * @ingroup aux_vk */ @@ -790,6 +802,11 @@ vk_begin_command_buffer(struct vk_bundle *vk, VkCommandBuffer command_buffer); VkResult vk_end_command_buffer(struct vk_bundle *vk, VkCommandBuffer command_buffer); +/*! + * Fills in has_* in vk_bundle given a string of prefiltered instance extensions + */ +void +vk_fill_in_has_instance_extensions(struct vk_bundle *vk, struct u_string_list *ext_list); #ifdef __cplusplus } diff --git a/src/xrt/compositor/main/comp_compositor.c b/src/xrt/compositor/main/comp_compositor.c index 6aa1eb608..1580b8440 100644 --- a/src/xrt/compositor/main/comp_compositor.c +++ b/src/xrt/compositor/main/comp_compositor.c @@ -629,10 +629,10 @@ static const char *optional_device_extensions[] = { }; static bool -append_all(struct comp_compositor *c, struct u_string_list *list, const char *const *arr, uint32_t size) +append_all(struct comp_compositor *c, struct u_string_list *required, const char *const *arr, uint32_t size) { for (uint32_t i = 0; i < size; i++) { - int ret = u_string_list_append(list, arr[i]); + int ret = u_string_list_append(required, arr[i]); if (ret < 0) { COMP_ERROR(c, "Failed to add %s to instance extension list: %d", arr[i], ret); return false; @@ -642,46 +642,53 @@ append_all(struct comp_compositor *c, struct u_string_list *list, const char *co } static VkResult -select_instances_extensions(struct comp_compositor *c, struct u_string_list *list) +select_instances_extensions(struct comp_compositor *c, struct u_string_list *required, struct u_string_list *optional) { switch (c->settings.window_type) { - case WINDOW_NONE: append_all(c, list, instance_extensions_none, ARRAY_SIZE(instance_extensions_none)); break; + case WINDOW_NONE: + append_all(c, required, instance_extensions_none, ARRAY_SIZE(instance_extensions_none)); + break; #ifdef VK_USE_PLATFORM_WAYLAND_KHR case WINDOW_DIRECT_WAYLAND: - append_all(c, list, instance_extensions_direct_wayland, ARRAY_SIZE(instance_extensions_direct_wayland)); + append_all(c, required, instance_extensions_direct_wayland, + ARRAY_SIZE(instance_extensions_direct_wayland)); break; case WINDOW_WAYLAND: - append_all(c, list, instance_extensions_wayland, ARRAY_SIZE(instance_extensions_wayland)); + append_all(c, required, instance_extensions_wayland, ARRAY_SIZE(instance_extensions_wayland)); break; #endif #ifdef VK_USE_PLATFORM_XCB_KHR - case WINDOW_XCB: append_all(c, list, instance_extensions_xcb, ARRAY_SIZE(instance_extensions_xcb)); break; + case WINDOW_XCB: append_all(c, required, instance_extensions_xcb, ARRAY_SIZE(instance_extensions_xcb)); break; #endif #ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT case WINDOW_DIRECT_RANDR: case WINDOW_DIRECT_NVIDIA: - append_all(c, list, instance_extensions_direct_mode, ARRAY_SIZE(instance_extensions_direct_mode)); + append_all(c, required, instance_extensions_direct_mode, ARRAY_SIZE(instance_extensions_direct_mode)); break; #endif #ifdef VK_USE_PLATFORM_ANDROID_KHR case WINDOW_ANDROID: - append_all(c, list, instance_extensions_android, ARRAY_SIZE(instance_extensions_android)); + append_all(c, required, instance_extensions_android, ARRAY_SIZE(instance_extensions_android)); break; #endif #ifdef VK_USE_PLATFORM_WIN32_KHR case WINDOW_MSWIN: - append_all(c, list, instance_extensions_windows, ARRAY_SIZE(instance_extensions_windows)); + append_all(c, required, instance_extensions_windows, ARRAY_SIZE(instance_extensions_windows)); break; #endif #ifdef VK_USE_PLATFORM_DISPLAY_KHR case WINDOW_VK_DISPLAY: - append_all(c, list, instance_extensions_vk_display, ARRAY_SIZE(instance_extensions_vk_display)); + append_all(c, required, instance_extensions_vk_display, ARRAY_SIZE(instance_extensions_vk_display)); break; #endif default: return VK_ERROR_INITIALIZATION_FAILED; } +#ifdef VK_EXT_display_surface_counter + u_string_list_append(optional, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME); +#endif + return VK_SUCCESS; } @@ -692,13 +699,16 @@ compositor_init_vulkan(struct comp_compositor *c) VkResult ret; // every backend needs at least as many extensions as the none window - struct u_string_list *instance_extension_list = + struct u_string_list *required_instance_ext_list = u_string_list_create_with_capacity(ARRAY_SIZE(instance_extensions_none)); - ret = select_instances_extensions(c, instance_extension_list); + struct u_string_list *optional_instance_ext_list = u_string_list_create(); + + ret = select_instances_extensions(c, required_instance_ext_list, optional_instance_ext_list); if (ret != VK_SUCCESS) { CVK_ERROR(c, "select_instances_extensions", "Failed to select instance extensions.", ret); - u_string_list_destroy(&instance_extension_list); + u_string_list_destroy(&required_instance_ext_list); + u_string_list_destroy(&optional_instance_ext_list); return ret; } @@ -714,7 +724,8 @@ compositor_init_vulkan(struct comp_compositor *c) struct comp_vulkan_arguments vk_args = { .get_instance_proc_address = vkGetInstanceProcAddr, - .required_instance_extensions = instance_extension_list, + .required_instance_extensions = required_instance_ext_list, + .optional_instance_extensions = optional_instance_ext_list, .required_device_extensions = required_device_extension_list, .optional_device_extensions = optional_device_extension_list, .log_level = c->settings.log_level, @@ -726,7 +737,8 @@ compositor_init_vulkan(struct comp_compositor *c) struct comp_vulkan_results vk_res = {0}; bool bundle_ret = comp_vulkan_init_bundle(vk, &vk_args, &vk_res); - u_string_list_destroy(&instance_extension_list); + u_string_list_destroy(&required_instance_ext_list); + u_string_list_destroy(&optional_instance_ext_list); u_string_list_destroy(&required_device_extension_list); u_string_list_destroy(&optional_device_extension_list); diff --git a/src/xrt/compositor/util/comp_vulkan.c b/src/xrt/compositor/util/comp_vulkan.c index b9cd67642..a1986b7ee 100644 --- a/src/xrt/compositor/util/comp_vulkan.c +++ b/src/xrt/compositor/util/comp_vulkan.c @@ -98,7 +98,6 @@ fill_in_results(struct vk_bundle *vk, const struct comp_vulkan_arguments *vk_arg return VK_SUCCESS; } - /* * * Creation functions. @@ -110,30 +109,16 @@ create_instance(struct vk_bundle *vk, const struct comp_vulkan_arguments *vk_arg { VkResult ret; - uint32_t prop_count = 0; - vk->vkEnumerateInstanceExtensionProperties(NULL, &prop_count, NULL); + struct u_string_list *instance_ext_list = vk_build_instance_extensions( + vk, vk_args->required_instance_extensions, vk_args->optional_instance_extensions); - VkExtensionProperties *props = U_TYPED_ARRAY_CALLOC(VkExtensionProperties, prop_count); - vk->vkEnumerateInstanceExtensionProperties(NULL, &prop_count, props); - - struct u_string_list *instance_ext_list = u_string_list_create_from_list(vk_args->required_instance_extensions); - - - uint32_t optional_instance_ext_count = u_string_list_get_size(vk_args->optional_instance_extensions); - const char *const *optional_instance_exts = u_string_list_get_data(vk_args->optional_instance_extensions); - for (uint32_t i = 0; i < optional_instance_ext_count; i++) { - const char *optional_ext = optional_instance_exts[i]; - for (uint32_t j = 0; j < prop_count; j++) { - if (strcmp(optional_ext, props[j].extensionName) == 0) { - int added = u_string_list_append_unique(instance_ext_list, optional_ext); - if (added == 0) { - VK_ERROR(vk, "Duplicate device extension %s not added twice", optional_ext); - } - break; - } - } + if (!instance_ext_list) { + return VK_ERROR_EXTENSION_NOT_PRESENT; } + // Fill this out here. + vk_fill_in_has_instance_extensions(vk, instance_ext_list); + VkApplicationInfo app_info = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pApplicationName = "Monado Compositor",