"ICD": {
"library_path": "path to driver library",
"api_version": "1.2.205",
+ "library_arch" : "64",
"is_portability_driver": false
}
}
other than it should end with the appropriate suffix (".DLL" on
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
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:
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
```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",
<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>
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
// 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) \
char *vkNegotiateLoaderLayerInterfaceVersion = NULL;
char *spec_version = NULL;
char **entry_array = NULL;
+ char *library_arch = NULL;
cJSON *app_keys = NULL;
// Layer interface functions
}
}
+ 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:
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);
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;
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;
dev.queueCreateInfoCount = static_cast<uint32_t>(device_queue_infos.size());
dev.pQueueCreateInfos = device_queue_infos.data();
return &dev;
-}
\ No newline at end of file
+}
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;
};
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;
buffer[ret] = '\0';
return buffer;
}
-#endif
\ No newline at end of file
+#endif
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));