memcpy(&loader_create_info, pCreateInfo, sizeof(VkInstanceCreateInfo));
+ if (pCreateInfo->enabledLayerCount > 0 && pCreateInfo->ppEnabledLayerNames != NULL) {
+ inst->enabled_layer_count = pCreateInfo->enabledLayerCount;
+
+ inst->enabled_layer_names = (char **)loader_instance_heap_alloc(inst, sizeof(char *) * pCreateInfo->enabledLayerCount,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+
+ for (uint32_t i = 0, n = inst->enabled_layer_count; i < n; ++i) {
+ size_t size = strlen(pCreateInfo->ppEnabledLayerNames[i]) + 1;
+ inst->enabled_layer_names[i] = (char *)loader_instance_heap_alloc(inst, sizeof(char) * size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ memset(inst->enabled_layer_names[i], '\0', sizeof(char) * size);
+ strcpy(inst->enabled_layer_names[i], pCreateInfo->ppEnabledLayerNames[i]);
+ }
+ }
+
if (inst->expanded_activated_layer_list.count > 0) {
chain_info.u.pLayerInfo = NULL;
chain_info.pNext = pCreateInfo->pNext;
memcpy(&loader_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
+ if (loader_create_info.enabledLayerCount > 0 && loader_create_info.ppEnabledLayerNames != NULL) {
+ bool invalid_device_layer_usage = false;
+
+ if (loader_create_info.enabledLayerCount != inst->enabled_layer_count && loader_create_info.enabledLayerCount > 0) {
+ invalid_device_layer_usage = true;
+ } else if (loader_create_info.enabledLayerCount > 0 && loader_create_info.ppEnabledLayerNames == NULL) {
+ invalid_device_layer_usage = true;
+ } else if (loader_create_info.enabledLayerCount == 0 && loader_create_info.ppEnabledLayerNames != NULL) {
+ invalid_device_layer_usage = true;
+ } else if (inst->enabled_layer_names != NULL) {
+ for (uint32_t i = 0; i < loader_create_info.enabledLayerCount; i++) {
+ const char *device_layer_names = loader_create_info.ppEnabledLayerNames[i];
+
+ if (strcmp(device_layer_names, inst->enabled_layer_names[i]) != 0) {
+ invalid_device_layer_usage = true;
+ break;
+ }
+ }
+ }
+
+ if (invalid_device_layer_usage) {
+ loader_log(
+ inst, VULKAN_LOADER_WARN_BIT, 0,
+ "loader_create_device_chain: Using deprecated and ignored 'ppEnabledLayerNames' member of 'VkDeviceCreateInfo' "
+ "when creating a Vulkan device.");
+ }
+ }
+
// Before we continue, we need to find out if the KHR_device_group extension is in the enabled list. If it is, we then
// need to look for the corresponding VkDeviceGroupDeviceCreateInfoKHR struct in the device list. This is because we
// need to replace all the incoming physical device values (which are really loader trampoline physical device values)
}
loader_free_dev_ext_table(ptr_instance);
loader_free_phys_dev_ext_table(ptr_instance);
+
+ for (uint32_t i = 0, n = ptr_instance->enabled_layer_count; i < n; ++i) {
+ loader_instance_heap_free(ptr_instance, ptr_instance->enabled_layer_names[i]);
+ }
+
+ if (ptr_instance->enabled_layer_count > 0) {
+ loader_instance_heap_free(ptr_instance, ptr_instance->enabled_layer_names);
+ memset(&ptr_instance->enabled_layer_names, 0, sizeof(ptr_instance->enabled_layer_names));
+ }
}
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
struct loader_msg_callback_map_entry *icd_msg_callback_map;
+ uint32_t enabled_layer_count;
+ char **enabled_layer_names;
+
struct loader_layer_list instance_layer_list;
bool override_layer_present;
ASSERT_EQ(result_to_check, functions->vkCreateInstance(create_info.get(), callbacks, &inst));
}
+void InstWrapper::CheckCreateWithInfo(InstanceCreateInfo& create_info, VkResult result_to_check) {
+ ASSERT_EQ(result_to_check, functions->vkCreateInstance(create_info.get(), callbacks, &inst));
+}
+
+
std::vector<VkPhysicalDevice> InstWrapper::GetPhysDevs(uint32_t phys_dev_count, VkResult result_to_check) {
uint32_t physical_count = phys_dev_count;
std::vector<VkPhysicalDevice> physical_devices;
// Construct this VkInstance using googletest to assert if it succeeded
void CheckCreate(VkResult result_to_check = VK_SUCCESS);
+ void CheckCreateWithInfo(InstanceCreateInfo& create_info, VkResult result_to_check = VK_SUCCESS);
// Convenience
operator VkInstance() { return inst; }
dev.CheckCreate(phys_dev);
}
+// Device layers are deprecated.
+// Ensure that no error occur if instance and device are created with the same list of layers.
+// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
+TEST(CreateDevice, MatchInstanceAndDeviceLayers) {
+ 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)),
+ "test_layer.json");
+
+ InstWrapper inst{env.vulkan_functions};
+ inst.create_info.add_layer(layer_name);
+ inst.CheckCreate();
+
+ VkPhysicalDevice phys_dev = inst.GetPhysDev();
+
+ DeviceWrapper dev{inst};
+ dev.create_info.add_layer(layer_name).add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f));
+
+ dev.CheckCreate(phys_dev);
+}
+
+// Device layers are deprecated.
+// Ensure that a message is generated when instance and device are created with different list of layers.
+// At best , the user can list only instance layers in the device layer list
+// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
+TEST(CreateDevice, UnmatchInstanceAndDeviceLayers) {
+ 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)),
+ "test_layer.json");
+
+ DebugUtilsLogger debug_log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT};
+ InstWrapper inst{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst.create_info, debug_log);
+ inst.CheckCreate();
+
+ DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT};
+ CreateDebugUtilsMessenger(log);
+
+ VkPhysicalDevice phys_dev = inst.GetPhysDev();
+
+ DeviceWrapper dev{inst};
+ dev.create_info.add_layer(layer_name).add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f));
+
+ dev.CheckCreate(phys_dev);
+
+ ASSERT_TRUE(log.find("loader_create_device_chain: Using deprecated and ignored 'ppEnabledLayerNames' member of 'VkDeviceCreateInfo' when creating a Vulkan device."));
+}
+
+// Device layers are deprecated.
+// Ensure that when VkInstanceCreateInfo is deleted, the check of the instance layer lists is running correctly during VkDevice creation
+// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
+TEST(CreateDevice, CheckCopyOfInstanceLayerNames) {
+ 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)),
+ "test_layer.json");
+
+ InstWrapper inst{env.vulkan_functions};
+ {
+ // We intentionally create a local InstanceCreateInfo that goes out of scope at the } so that when dev.CheckCreate is called the layer name pointers are no longer valid
+ InstanceCreateInfo create_info{};
+ create_info.add_layer(layer_name);
+ inst.CheckCreateWithInfo(create_info);
+ }
+
+ VkPhysicalDevice phys_dev = inst.GetPhysDev();
+
+ DeviceWrapper dev{inst};
+ dev.create_info.add_layer(layer_name).add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f));
+
+ dev.CheckCreate(phys_dev);
+}
+
TEST(CreateDevice, ConsecutiveCreate) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));