VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
return VK_SUCCESS;
}
+
VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
if (pLayerName && string_eq(pLayerName, layer.unique_name.c_str())) {
VkLayerProperties* pProperties) {
return VK_SUCCESS;
}
+
VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) {
return VK_ERROR_INVALID_SHADER_NV;
}
+
VKAPI_ATTR void VKAPI_CALL test_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator) {
layer.instance_dispatch_table.DestroyInstance(instance, pAllocator);
}
return get_instance_func(instance, pName);
}
FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL test_override_vkGetInstanceProcAddr(VkInstance instance, const char* pName) {
- if (string_eq(pName, "vkCreateInstance")) return TO_VOID_PFN(test_override_vkCreateInstance);
+ if (string_eq(pName, "vkCreateInstance")) return to_vkVoidFunction(test_override_vkCreateInstance);
return get_instance_func(instance, pName);
}
#endif
ASSERT_EQ(0, count);
}
}
+
+// Verify that VK_INSTANCE_LAYERS work. To test this, make sure that an explicit layer does not affect an instance until
+// it is set with VK_INSTANCE_LAYERS
+TEST(TestLayers, EnvironEnableExplicitLayer) {
+ FrameworkEnvironment env;
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6, VK_MAKE_API_VERSION(0, 1, 2, 0)));
+ env.get_test_icd().icd_api_version = VK_MAKE_API_VERSION(0, 1, 2, 0);
+ VkPhysicalDeviceProperties properties{};
+ properties.apiVersion = VK_MAKE_API_VERSION(0, 1, 2, 0);
+ env.get_test_icd().add_physical_device({});
+ env.get_test_icd().physical_devices.back().set_properties(properties);
+
+ const char* explicit_layer_name = "VK_LAYER_LUNARG_wrap_objects";
+ env.add_explicit_layer(
+ ManifestLayer{}.add_layer(
+ ManifestLayer::LayerDescription{}
+ .set_name(explicit_layer_name)
+ .set_lib_path(TEST_LAYER_WRAP_OBJECTS_3)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))
+ .add_device_extension({VK_KHR_MAINTENANCE1_EXTENSION_NAME, 1, {"vkTrimCommandPoolKHR"}})
+ .add_device_extension({VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME, 1, {"vkGetSwapchainStatusKHR"}})),
+ "explicit_wrap_layer_both_dev.json");
+
+ // First, test an instance/device without the layer forced on. The extensions shouldn't be present and
+ // the function pointers should be NULL.
+ InstWrapper inst1{env.vulkan_functions};
+ inst1.CheckCreate();
+ VkPhysicalDevice phys_dev1 = inst1.GetPhysDev();
+
+ // Make sure the extensions in the layer aren't present
+ uint32_t extension_count = 40;
+ std::array<VkExtensionProperties, 40> extensions;
+ EXPECT_EQ(VK_SUCCESS,
+ env.vulkan_functions.vkEnumerateDeviceExtensionProperties(phys_dev1, nullptr, &extension_count, extensions.data()));
+ for (uint32_t ext = 0; ext < extension_count; ++ext) {
+ if (string_eq(extensions[ext].extensionName, VK_KHR_MAINTENANCE1_EXTENSION_NAME) ||
+ string_eq(extensions[ext].extensionName, VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME)) {
+ ASSERT_EQ(false, true);
+ }
+ }
+
+ // Create a device and query the function pointers
+ DeviceWrapper dev1{inst1};
+ dev1.create_info.add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f));
+ dev1.CheckCreate(phys_dev1);
+ PFN_vkTrimCommandPoolKHR pfn_TrimCommandPoolBefore =
+ reinterpret_cast<PFN_vkTrimCommandPoolKHR>(dev1->vkGetDeviceProcAddr(dev1.dev, "vkTrimCommandPoolKHR"));
+ PFN_vkGetSwapchainStatusKHR pfn_GetSwapchainStatusBefore =
+ reinterpret_cast<PFN_vkGetSwapchainStatusKHR>(dev1->vkGetDeviceProcAddr(dev1.dev, "vkGetSwapchainStatusKHR"));
+ handle_assert_null(pfn_TrimCommandPoolBefore);
+ handle_assert_null(pfn_GetSwapchainStatusBefore);
+
+ // Now setup the instance layer
+ set_env_var("VK_INSTANCE_LAYERS", explicit_layer_name);
+
+ // Now, test an instance/device with the layer forced on. The extensions should be present and
+ // the function pointers should be valid.
+ InstWrapper inst2{env.vulkan_functions};
+ inst2.CheckCreate();
+ VkPhysicalDevice phys_dev2 = inst2.GetPhysDev();
+
+ // Make sure the extensions in the layer aren't present
+ extension_count = 40;
+ EXPECT_EQ(VK_SUCCESS,
+ env.vulkan_functions.vkEnumerateDeviceExtensionProperties(phys_dev2, nullptr, &extension_count, extensions.data()));
+ bool maint_found = false;
+ bool pres_found = false;
+ for (uint32_t ext = 0; ext < extension_count; ++ext) {
+ if (string_eq(extensions[ext].extensionName, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) {
+ maint_found = true;
+ }
+ if (string_eq(extensions[ext].extensionName, VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME)) {
+ pres_found = true;
+ }
+ }
+ ASSERT_EQ(true, maint_found);
+ ASSERT_EQ(true, pres_found);
+
+ DeviceWrapper dev2{inst2};
+ dev2.create_info.add_extension(VK_KHR_MAINTENANCE1_EXTENSION_NAME)
+ .add_extension(VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME)
+ .add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f));
+ dev2.CheckCreate(phys_dev2);
+
+ PFN_vkTrimCommandPoolKHR pfn_TrimCommandPoolAfter =
+ reinterpret_cast<PFN_vkTrimCommandPoolKHR>(dev2->vkGetDeviceProcAddr(dev2.dev, "vkTrimCommandPoolKHR"));
+ PFN_vkGetSwapchainStatusKHR pfn_GetSwapchainStatusAfter =
+ reinterpret_cast<PFN_vkGetSwapchainStatusKHR>(dev2->vkGetDeviceProcAddr(dev2.dev, "vkGetSwapchainStatusKHR"));
+ handle_assert_has_value(pfn_TrimCommandPoolAfter);
+ handle_assert_has_value(pfn_GetSwapchainStatusAfter);
+
+ ASSERT_EQ(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR, pfn_GetSwapchainStatusAfter(dev2.dev, VK_NULL_HANDLE));
+
+ remove_env_var("VK_INSTANCE_LAYERS");
+}