diff --git a/pressure-vessel/runtime.c b/pressure-vessel/runtime.c index cd3c368a7f21b4c9d8be4ea39282bf6ee512064f..e15f2e026a2163dc2163003397320f34441159f0 100644 --- a/pressure-vessel/runtime.c +++ b/pressure-vessel/runtime.c @@ -2399,125 +2399,175 @@ pv_runtime_search_in_path_and_bin (PvRuntime *self, return NULL; } +/* + * setup_vulkan_loadable_json: + * @self: The runtime + * @bwrap: Append arguments to this bubblewrap invocation to make files + * available in the container + * @sub_dir: `icd.d`, `explicit_layer.d` or `implicit_layer.d` + * @write_to_dir: Path to `/overrides/share/vulkan/${sub_dir}` in the + * current execution environment + * @details: An #IcdDetails holding a #SrtVulkanLayer or #SrtVulkanIcd, + * whichever is appropriate for @sub_dir + * @seq: Sequence number of @details, used to make unique filenames + * @vulkan_path: Used to build `$VK_ICD_FILENAMES` or a similar search path + * @error: Used to raise an error on failure + * + * Make a single Vulkan layer or ICD available in the container. + */ static gboolean setup_vulkan_loadable_json (PvRuntime *self, FlatpakBwrap *bwrap, const gchar *sub_dir, - GPtrArray *vulkan_details, + const gchar *write_to_dir, + IcdDetails *details, + gsize seq, GString *vulkan_path, GError **error) { - gsize i, j; - g_autofree gchar *write_to_dir = NULL; + SrtVulkanLayer *layer = NULL; + SrtVulkanIcd *icd = NULL; + gboolean need_provider_json = FALSE; + gsize i; - write_to_dir = g_build_filename (self->overrides, - "share", "vulkan", sub_dir, NULL); + if (SRT_IS_VULKAN_LAYER (details->icd)) + layer = SRT_VULKAN_LAYER (details->icd); + else if (SRT_IS_VULKAN_ICD (details->icd)) + icd = SRT_VULKAN_ICD (details->icd); + else + g_return_val_if_reached (FALSE); - if (g_mkdir_with_parents (write_to_dir, 0700) != 0) + /* If the layer failed to load, there's nothing to make available */ + if (layer != NULL) { - glnx_throw_errno_prefix (error, "Unable to create %s", write_to_dir); - return FALSE; + if (!srt_vulkan_layer_check_error (layer, NULL)) + return TRUE; } - - for (j = 0; j < vulkan_details->len; j++) + else { - SrtVulkanLayer *layer = NULL; - SrtVulkanIcd *icd = NULL; - IcdDetails *details = g_ptr_array_index (vulkan_details, j); - gboolean need_provider_json = FALSE; + if (!srt_vulkan_icd_check_error (icd, NULL)) + return TRUE; + } - if (SRT_IS_VULKAN_LAYER (details->icd)) - layer = SRT_VULKAN_LAYER (details->icd); - else if (SRT_IS_VULKAN_ICD (details->icd)) - icd = SRT_VULKAN_ICD (details->icd); - else - g_return_val_if_reached (FALSE); + for (i = 0; i < G_N_ELEMENTS (multiarch_tuples) - 1; i++) + { + g_assert (i < G_N_ELEMENTS (details->kinds)); + g_assert (i < G_N_ELEMENTS (details->paths_in_container)); - if (layer != NULL) + if (details->kinds[i] == ICD_KIND_ABSOLUTE) { - if (!srt_vulkan_layer_check_error (layer, NULL)) - continue; - } - else - { - if (!srt_vulkan_icd_check_error (icd, NULL)) - continue; - } + g_autofree gchar *write_to_file = NULL; + g_autofree gchar *json_in_container = NULL; + g_autofree gchar *json_base = NULL; - for (i = 0; i < G_N_ELEMENTS (multiarch_tuples) - 1; i++) - { - g_assert (i < G_N_ELEMENTS (details->kinds)); - g_assert (i < G_N_ELEMENTS (details->paths_in_container)); + g_assert (details->paths_in_container[i] != NULL); - if (details->kinds[i] == ICD_KIND_ABSOLUTE) + json_base = g_strdup_printf ("%" G_GSIZE_FORMAT "-%s.json", + seq, multiarch_tuples[i]); + write_to_file = g_build_filename (write_to_dir, json_base, NULL); + json_in_container = g_build_filename (self->overrides_in_container, + "share", "vulkan", sub_dir, + json_base, NULL); + + if (layer != NULL) { - g_autofree gchar *write_to_file = NULL; - g_autofree gchar *json_in_container = NULL; - g_autofree gchar *json_base = NULL; + g_autoptr(SrtVulkanLayer) replacement = NULL; + replacement = srt_vulkan_layer_new_replace_library_path (layer, + details->paths_in_container[i]); - g_assert (details->paths_in_container[i] != NULL); + if (!srt_vulkan_layer_write_to_file (replacement, write_to_file, error)) + return FALSE; + } + else + { + g_autoptr(SrtVulkanIcd) replacement = NULL; + replacement = srt_vulkan_icd_new_replace_library_path (icd, + details->paths_in_container[i]); - json_base = g_strdup_printf ("%" G_GSIZE_FORMAT "-%s.json", - j, multiarch_tuples[i]); - write_to_file = g_build_filename (write_to_dir, json_base, NULL); - json_in_container = g_build_filename (self->overrides_in_container, - "share", "vulkan", sub_dir, - json_base, NULL); + if (!srt_vulkan_icd_write_to_file (replacement, write_to_file, error)) + return FALSE; + } - if (layer != NULL) - { - g_autoptr(SrtVulkanLayer) replacement = NULL; - replacement = srt_vulkan_layer_new_replace_library_path (layer, - details->paths_in_container[i]); + pv_search_path_append (vulkan_path, json_in_container); + } + else if (details->kinds[i] == ICD_KIND_SONAME + || details->kinds[i] == ICD_KIND_META_LAYER) + { + need_provider_json = TRUE; + } + } - if (!srt_vulkan_layer_write_to_file (replacement, write_to_file, error)) - return FALSE; - } - else - { - g_autoptr(SrtVulkanIcd) replacement = NULL; - replacement = srt_vulkan_icd_new_replace_library_path (icd, - details->paths_in_container[i]); + if (need_provider_json) + { + g_autofree gchar *json_in_container = NULL; + g_autofree gchar *json_base = NULL; + const char *json_in_provider = NULL; + if (layer != NULL) + json_in_provider = srt_vulkan_layer_get_json_path (layer); + else + json_in_provider = srt_vulkan_icd_get_json_path (icd); - if (!srt_vulkan_icd_write_to_file (replacement, write_to_file, error)) - return FALSE; - } + json_base = g_strdup_printf ("%" G_GSIZE_FORMAT ".json", seq); + json_in_container = g_build_filename (self->overrides_in_container, + "share", "vulkan", sub_dir, + json_base, NULL); + if (!pv_runtime_take_from_provider (self, bwrap, + json_in_provider, + json_in_container, + TAKE_FROM_PROVIDER_FLAGS_COPY_FALLBACK, + error)) + return FALSE; - pv_search_path_append (vulkan_path, json_in_container); - } - else if (details->kinds[i] == ICD_KIND_SONAME - || details->kinds[i] == ICD_KIND_META_LAYER) - { - need_provider_json = TRUE; - } - } + pv_search_path_append (vulkan_path, json_in_container); + } - if (need_provider_json) - { - g_autofree gchar *json_in_container = NULL; - g_autofree gchar *json_base = NULL; - const char *json_in_provider = NULL; - if (layer != NULL) - json_in_provider = srt_vulkan_layer_get_json_path (layer); - else - json_in_provider = srt_vulkan_icd_get_json_path (icd); + return TRUE; +} - json_base = g_strdup_printf ("%" G_GSIZE_FORMAT ".json", j); - json_in_container = g_build_filename (self->overrides_in_container, - "share", "vulkan", sub_dir, - json_base, NULL); +/* + * setup_vulkan_loadable_json: + * @self: The runtime + * @bwrap: Append arguments to this bubblewrap invocation to make files + * available in the container + * @sub_dir: `icd.d`, `explicit_layer.d` or `implicit_layer.d` + * @write_to_dir: Path to `/overrides/share/vulkan/${sub_dir}` in the + * current execution environment + * @vulkan_details: (element-type IcdDetails): A list of #IcdDetails + * holding #SrtVulkanLayer or #SrtVulkanIcd, as appropriate for @sub_dir + * @vulkan_path: Used to build `$VK_ICD_FILENAMES` or a similar search path + * @error: Used to raise an error on failure + * + * Make a list of Vulkan layers or ICDs available in the container. + */ +static gboolean +setup_each_vulkan_loadable_json (PvRuntime *self, + FlatpakBwrap *bwrap, + const gchar *sub_dir, + GPtrArray *vulkan_details, + GString *vulkan_path, + GError **error) +{ + gsize j; + g_autofree gchar *write_to_dir = NULL; - if (!pv_runtime_take_from_provider (self, bwrap, - json_in_provider, - json_in_container, - TAKE_FROM_PROVIDER_FLAGS_COPY_FALLBACK, - error)) - return FALSE; + write_to_dir = g_build_filename (self->overrides, + "share", "vulkan", sub_dir, NULL); - pv_search_path_append (vulkan_path, json_in_container); - } + if (g_mkdir_with_parents (write_to_dir, 0700) != 0) + { + glnx_throw_errno_prefix (error, "Unable to create %s", write_to_dir); + return FALSE; } + + for (j = 0; j < vulkan_details->len; j++) + { + if (!setup_vulkan_loadable_json (self, bwrap, sub_dir, write_to_dir, + g_ptr_array_index (vulkan_details, j), + j, vulkan_path, error)) + return FALSE; + } + return TRUE; } @@ -3512,22 +3562,23 @@ pv_runtime_use_provider_graphics_stack (PvRuntime *self, } g_debug ("Setting up Vulkan ICD JSON..."); - if (!setup_vulkan_loadable_json (self, bwrap, "icd.d", vulkan_icd_details, - vulkan_path, error)) + if (!setup_each_vulkan_loadable_json (self, bwrap, "icd.d", + vulkan_icd_details, + vulkan_path, error)) return FALSE; if (self->flags & PV_RUNTIME_FLAGS_IMPORT_VULKAN_LAYERS) { g_debug ("Setting up Vulkan explicit layer JSON..."); - if (!setup_vulkan_loadable_json (self, bwrap, "explicit_layer.d", - vulkan_exp_layer_details, - vulkan_exp_layer_path, error)) + if (!setup_each_vulkan_loadable_json (self, bwrap, "explicit_layer.d", + vulkan_exp_layer_details, + vulkan_exp_layer_path, error)) return FALSE; g_debug ("Setting up Vulkan implicit layer JSON..."); - if (!setup_vulkan_loadable_json (self, bwrap, "implicit_layer.d", - vulkan_imp_layer_details, - vulkan_imp_layer_path, error)) + if (!setup_each_vulkan_loadable_json (self, bwrap, "implicit_layer.d", + vulkan_imp_layer_details, + vulkan_imp_layer_path, error)) return FALSE; }