diff options
author | Charles Giessen <charles@lunarg.com> | 2022-06-20 23:38:56 +0300 |
---|---|---|
committer | Charles Giessen <46324611+charles-lunarg@users.noreply.github.com> | 2022-06-22 19:28:18 +0300 |
commit | 865626abbafda93a236398ac35627407d62dbe6f (patch) | |
tree | bd901e10f9f367f8743bc3cb58ed7533c766517f | |
parent | 8d3d6d4e1635aabfe0cd66b628ba30278179b5d9 (diff) |
Add 32 & 64 bit field to json manifests
Allows drivers and layers to specify if they are 32 bit or 64 bit in the
manifest file. This makes the loader able to prune manifests without
loading the library and finding that it failed to load.
-rw-r--r-- | docs/LoaderDriverInterface.md | 14 | ||||
-rw-r--r-- | docs/LoaderLayerInterface.md | 18 | ||||
-rw-r--r-- | loader/loader.c | 31 | ||||
-rw-r--r-- | tests/framework/test_util.cpp | 13 | ||||
-rw-r--r-- | tests/framework/test_util.h | 4 | ||||
-rw-r--r-- | tests/loader_regression_tests.cpp | 36 |
6 files changed, 110 insertions, 6 deletions
diff --git a/docs/LoaderDriverInterface.md b/docs/LoaderDriverInterface.md index 12c964a58..1021dd41d 100644 --- a/docs/LoaderDriverInterface.md +++ b/docs/LoaderDriverInterface.md @@ -516,6 +516,7 @@ Here is an example driver JSON Manifest file: "ICD": { "library_path": "path to driver library", "api_version": "1.2.205", + "library_arch" : "64", "is_portability_driver": false } } @@ -551,6 +552,14 @@ Here is an example driver JSON Manifest file: Windows, ".so" on Linux and ".dylib" on macOS).</td> </tr> <tr> + <td>"library_arch"</td> + <td>Optional field which specifies the architecture of the binary associated + with "library_path". <br /> + Allows the loader to quickly determine if the architecture of the driver + matches that of the running application. <br /> + The only valid values are "32" and "64".</td> + </tr> + <tr> <td>"api_version" </td> <td>The major.minor.patch version number of the maximum Vulkan API supported by the driver. @@ -574,7 +583,7 @@ Here is an example driver JSON Manifest file: versions of text manifest file format versions, it must have separate JSON files for each (all of which may point to the same shared library). -#### Driver Manifest File Versions +### Driver Manifest File Versions The current highest supported Layer Manifest file format supported is 1.0.1. Information about each version is detailed in the following sub-sections: @@ -596,6 +605,9 @@ they contain VkPhysicalDevices which support the VK_KHR_portability_subset extension. This is an optional field. Omitting the field has the same effect as setting the field to `false`. +Added the "library\_arch" field to the driver manifest to allow the loader to +quickly determine if the driver matches the architecture of the current running +application. This field is optional. ## Driver Vulkan Entry Point Discovery diff --git a/docs/LoaderLayerInterface.md b/docs/LoaderLayerInterface.md index ba9d6afde..36631684c 100644 --- a/docs/LoaderLayerInterface.md +++ b/docs/LoaderLayerInterface.md @@ -1437,11 +1437,12 @@ Here is an example layer JSON Manifest file with a single layer: ```json { - "file_format_version" : "1.0.0", + "file_format_version" : "1.2.1", "layer": { "name": "VK_LAYER_LUNARG_overlay", "type": "INSTANCE", "library_path": "vkOverlayLayer.dll", + "library_arch" : "64", "api_version" : "1.0.5", "implementation_version" : "2", "description" : "LunarG HUD layer", @@ -1708,6 +1709,15 @@ Here's an example of a meta-layer manifest file: <td>"layer"/"layers"</td> <td><small>N/A</small></td> </tr> + <td>"library_arch"</td> + <td>Optional field which specifies the architecture of the binary associated + with "library_path". <br /> + Allows the loader to quickly determine if the architecture of the layer + matches that of the running application. <br /> + The only valid values are "32" and "64".</td> + <td><small>N/A</small></td> + </tr> + <tr> <tr> <td>"name"</td> <td>The string used to uniquely identify this layer to applications.</td> @@ -1764,6 +1774,12 @@ Here's an example of a meta-layer manifest file: The current highest supported Layer Manifest file format supported is 1.2.0. Information about each version is detailed in the following sub-sections: +### Layer Manifest File Version 1.2.1 + +Added the "library\_arch" field to the layer manifest to allow the loader to +quickly determine if the layer matches the architecture of the current running +application. + #### Layer Manifest File Version 1.2.0 The ability to define the layer settings as defined by the diff --git a/loader/loader.c b/loader/loader.c index 6e565f5aa..fd59f199c 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -2256,6 +2256,7 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc // instance_extensions // device_extensions // enable_environment (implicit layers only) +// library_arch #define GET_JSON_OBJECT(node, var) \ { var = cJSON_GetObjectItem(node, #var); } #define GET_JSON_ITEM(inst, node, var) \ @@ -2282,6 +2283,7 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc char *vkNegotiateLoaderLayerInterfaceVersion = NULL; char *spec_version = NULL; char **entry_array = NULL; + char *library_arch = NULL; cJSON *app_keys = NULL; // Layer interface functions @@ -2511,6 +2513,16 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc } } + GET_JSON_ITEM(inst, layer_node, library_arch) + if (library_arch != NULL) { + if ((strncmp(library_arch, "32", 2) == 0 && sizeof(void *) != 4) || + (strncmp(library_arch, "64", 2) == 0 && sizeof(void *) != 8)) { + loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, + "Layer library architecture doesn't match the current running architecture, skipping this layer"); + goto out; + } + } + result = VK_SUCCESS; out: @@ -3538,6 +3550,25 @@ VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_t continue; } + item = cJSON_GetObjectItem(itemICD, "library_arch"); + if (item != NULL) { + temp = cJSON_Print(item); + if (NULL != temp) { + // cJSON includes the quotes by default, so we need to look for those here + if ((strncmp(temp, "\"32\"", 4) == 0 && sizeof(void *) != 4) || + (strncmp(temp, "\"64\"", 4) == 0 && sizeof(void *) != 8)) { + loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, + "loader_icd_scan: Driver library architecture doesn't match the current running " + "architecture, skipping this driver"); + loader_instance_heap_free(inst, temp); + cJSON_Delete(json); + json = NULL; + continue; + } + } + loader_instance_heap_free(inst, temp); + } + VkResult icd_add_res = VK_SUCCESS; enum loader_layer_library_status lib_status; icd_add_res = loader_scanned_icd_add(inst, icd_tramp_list, fullpath, vers, &lib_status); diff --git a/tests/framework/test_util.cpp b/tests/framework/test_util.cpp index 3acc64050..6b796e7ce 100644 --- a/tests/framework/test_util.cpp +++ b/tests/framework/test_util.cpp @@ -137,7 +137,12 @@ std::string ManifestICD::get_manifest_str() const { out += " \"ICD\": {\n"; out += " \"library_path\": \"" + fs::fixup_backslashes_in_path(lib_path) + "\",\n"; out += " \"api_version\": \"" + version_to_string(api_version) + "\",\n"; - out += " \"is_portability_driver\": " + to_text(is_portability_driver) + "\n"; + out += " \"is_portability_driver\": " + to_text(is_portability_driver); + if (!library_arch.empty()) { + out += ",\n \"library_arch\": \"" + library_arch + "\"\n"; + } else { + out += "\n"; + } out += " }\n"; out += "}\n"; return out; @@ -176,7 +181,9 @@ std::string ManifestLayer::LayerDescription::get_manifest_str() const { print_vector_of_strings(out, "override_paths", override_paths); print_vector_of_strings(out, "app_keys", app_keys); print_list_of_t(out, "pre_instance_functions", pre_instance_functions); - + if (!library_arch.empty()) { + out += ",\n\t\t\"library_arch\": \"" + library_arch + "\""; + } out += "\n\t}"; return out; @@ -664,4 +671,4 @@ VkDeviceCreateInfo* DeviceCreateInfo::get() noexcept { dev.queueCreateInfoCount = static_cast<uint32_t>(device_queue_infos.size()); dev.pQueueCreateInfos = device_queue_infos.data(); return &dev; -}
\ No newline at end of file +} diff --git a/tests/framework/test_util.h b/tests/framework/test_util.h index 2ab87645f..376602414 100644 --- a/tests/framework/test_util.h +++ b/tests/framework/test_util.h @@ -543,6 +543,7 @@ struct ManifestICD { BUILDER_VALUE(ManifestICD, uint32_t, api_version, 0) BUILDER_VALUE(ManifestICD, std::string, lib_path, {}) BUILDER_VALUE(ManifestICD, bool, is_portability_driver, false) + BUILDER_VALUE(ManifestICD, std::string, library_arch, "") std::string get_manifest_str() const; }; @@ -589,6 +590,7 @@ struct ManifestLayer { BUILDER_VECTOR(LayerDescription, std::string, override_paths, override_path) BUILDER_VECTOR(LayerDescription, FunctionOverride, pre_instance_functions, pre_instance_function) BUILDER_VECTOR(LayerDescription, std::string, app_keys, app_key) + BUILDER_VALUE(LayerDescription, std::string, library_arch, "") std::string get_manifest_str() const; VkLayerProperties get_layer_properties() const; @@ -963,4 +965,4 @@ static inline std::string test_platform_executable_path() { buffer[ret] = '\0'; return buffer; } -#endif
\ No newline at end of file +#endif diff --git a/tests/loader_regression_tests.cpp b/tests/loader_regression_tests.cpp index 141c1aa79..bd8fdeebf 100644 --- a/tests/loader_regression_tests.cpp +++ b/tests/loader_regression_tests.cpp @@ -1303,6 +1303,42 @@ TEST(TryLoadWrongBinaries, BadExplicitAndImplicit) { ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name_1) + std::string(" failed to load."))); } +TEST(TryLoadWrongBinaries, WrongArchDriver) { + FrameworkEnvironment env{}; + // Intentionally set the wrong arch + env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}.icd_manifest.set_library_arch(sizeof(void*) == 4 ? "64" : "32")); + + env.get_test_icd().physical_devices.emplace_back("physical_device_0"); + + DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT}; + InstWrapper inst{env.vulkan_functions}; + FillDebugUtilsCreateDetails(inst.create_info, log); + inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER); + ASSERT_TRUE(log.find( + "loader_icd_scan: Driver library architecture doesn't match the current running architecture, skipping this driver")); +} + +TEST(TryLoadWrongBinaries, WrongArchLayer) { + FrameworkEnvironment env{}; + env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}); + env.get_test_icd().physical_devices.emplace_back("physical_device_0"); + + const char* layer_name = "TestLayer"; + env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} + .set_name(layer_name) + .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) + // Intentionally set the wrong arch + .set_library_arch(sizeof(void*) == 4 ? "64" : "32")), + "test_layer.json"); + + DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT}; + InstWrapper inst{env.vulkan_functions}; + FillDebugUtilsCreateDetails(inst.create_info, log); + inst.create_info.add_layer(layer_name); + inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT); + ASSERT_TRUE(log.find("Layer library architecture doesn't match the current running architecture, skipping this layer")); +} + TEST(EnumeratePhysicalDeviceGroups, OneCall) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); |