tests: Round out object-tracker layer validation tests
Change-Id: I6aad451a44cf2053b078eca98adca6b72acbd0a0
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index bd8b106..46cb414 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -1329,9 +1329,214 @@
#endif // MEM_TRACKER_TESTS
#if OBJ_TRACKER_TESTS
+
+TEST_F(VkLayerTest, LeakAnObject) {
+ VkResult err;
+
+ TEST_DESCRIPTION(
+ "Create a fence and destroy its device without first destroying the fence.");
+
+ // Note that we have to create a new device since destroying the
+ // framework's device causes Teardown() to fail and just calling Teardown
+ // will destroy the errorMonitor.
+
+ m_errorMonitor->SetDesiredFailureMsg(
+ VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ "OBJ ERROR : VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT object");
+
+ ASSERT_NO_FATAL_FAILURE(InitState());
+
+ const std::vector<VkQueueFamilyProperties> queue_props =
+ m_device->queue_props;
+ std::vector<VkDeviceQueueCreateInfo> queue_info;
+ queue_info.reserve(queue_props.size());
+ std::vector<std::vector<float>> queue_priorities;
+ for (uint32_t i = 0; i < (uint32_t)queue_props.size(); i++) {
+ VkDeviceQueueCreateInfo qi = {};
+ qi.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ qi.pNext = NULL;
+ qi.queueFamilyIndex = i;
+ qi.queueCount = queue_props[i].queueCount;
+ queue_priorities.emplace_back(qi.queueCount, 0.0f);
+ qi.pQueuePriorities = queue_priorities[i].data();
+ queue_info.push_back(qi);
+ }
+
+ std::vector<const char *> device_layer_names;
+ std::vector<const char *> device_extension_names;
+ device_layer_names.push_back("VK_LAYER_GOOGLE_threading");
+ device_layer_names.push_back("VK_LAYER_LUNARG_parameter_validation");
+ device_layer_names.push_back("VK_LAYER_LUNARG_object_tracker");
+ device_layer_names.push_back("VK_LAYER_LUNARG_core_validation");
+ device_layer_names.push_back("VK_LAYER_LUNARG_device_limits");
+ device_layer_names.push_back("VK_LAYER_LUNARG_image");
+ device_layer_names.push_back("VK_LAYER_GOOGLE_unique_objects");
+
+ // The sacrificial device object
+ VkDevice testDevice;
+ VkDeviceCreateInfo device_create_info = {};
+ auto features = m_device->phy().features();
+ device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ device_create_info.pNext = NULL;
+ device_create_info.queueCreateInfoCount = queue_info.size();
+ device_create_info.pQueueCreateInfos = queue_info.data();
+ device_create_info.enabledLayerCount = device_layer_names.size();
+ device_create_info.ppEnabledLayerNames = device_layer_names.data();
+ device_create_info.pEnabledFeatures = &features;
+ err = vkCreateDevice(gpu(), &device_create_info, NULL, &testDevice);
+ ASSERT_VK_SUCCESS(err);
+
+ VkFence fence;
+ VkFenceCreateInfo fence_create_info = {};
+ fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fence_create_info.pNext = NULL;
+ fence_create_info.flags = 0;
+ err = vkCreateFence(testDevice, &fence_create_info, NULL, &fence);
+ ASSERT_VK_SUCCESS(err);
+
+ // Induce failure by not calling vkDestroyFence
+ vkDestroyDevice(testDevice, NULL);
+ m_errorMonitor->VerifyFound();
+}
+
+TEST_F(VkLayerTest, InvalidCommandPoolConsistency) {
+
+ TEST_DESCRIPTION("Allocate command buffers from one command pool and "
+ "attempt to delete them from another.");
+
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ "FreeCommandBuffers is attempting to free Command Buffer");
+
+ VkCommandPool command_pool_one;
+ VkCommandPool command_pool_two;
+
+ VkCommandPoolCreateInfo pool_create_info{};
+ pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
+ pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+
+ vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr,
+ &command_pool_one);
+
+ vkCreateCommandPool(m_device->device(), &pool_create_info, nullptr,
+ &command_pool_two);
+
+ VkCommandBuffer command_buffer[9];
+ VkCommandBufferAllocateInfo command_buffer_allocate_info{};
+ command_buffer_allocate_info.sType =
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ command_buffer_allocate_info.commandPool = command_pool_one;
+ command_buffer_allocate_info.commandBufferCount = 9;
+ command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info,
+ command_buffer);
+
+ vkFreeCommandBuffers(m_device->device(), command_pool_two, 4,
+ &command_buffer[3]);
+
+ m_errorMonitor->VerifyFound();
+
+ vkDestroyCommandPool(m_device->device(), command_pool_one, NULL);
+ vkDestroyCommandPool(m_device->device(), command_pool_two, NULL);
+}
+
+TEST_F(VkLayerTest, InvalidDescriptorPoolConsistency) {
+ VkResult err;
+
+ TEST_DESCRIPTION("Allocate descriptor sets from one DS pool and "
+ "attempt to delete them from another.");
+
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ "FreeDescriptorSets is attempting to free descriptorSet");
+
+ ASSERT_NO_FATAL_FAILURE(InitState());
+ ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
+
+ VkDescriptorPoolSize ds_type_count = {};
+ ds_type_count.type = VK_DESCRIPTOR_TYPE_SAMPLER;
+ ds_type_count.descriptorCount = 1;
+
+ VkDescriptorPoolCreateInfo ds_pool_ci = {};
+ ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ ds_pool_ci.pNext = NULL;
+ ds_pool_ci.flags = 0;
+ ds_pool_ci.maxSets = 1;
+ ds_pool_ci.poolSizeCount = 1;
+ ds_pool_ci.pPoolSizes = &ds_type_count;
+
+ VkDescriptorPool ds_pool_one;
+ err =
+ vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool_one);
+ ASSERT_VK_SUCCESS(err);
+
+ // Create a second descriptor pool
+ VkDescriptorPool ds_pool_two;
+ err =
+ vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool_two);
+ ASSERT_VK_SUCCESS(err);
+
+ VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
+ dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
+ dsl_binding.descriptorCount = 1;
+ dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
+ dsl_binding.pImmutableSamplers = NULL;
+
+ VkDescriptorSetLayoutCreateInfo ds_layout_ci = {};
+ ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ ds_layout_ci.pNext = NULL;
+ ds_layout_ci.bindingCount = 1;
+ ds_layout_ci.pBindings = &dsl_binding;
+
+ VkDescriptorSetLayout ds_layout;
+ err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL,
+ &ds_layout);
+ ASSERT_VK_SUCCESS(err);
+
+ VkDescriptorSet descriptorSet;
+ VkDescriptorSetAllocateInfo alloc_info = {};
+ alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ alloc_info.descriptorSetCount = 1;
+ alloc_info.descriptorPool = ds_pool_one;
+ alloc_info.pSetLayouts = &ds_layout;
+ err = vkAllocateDescriptorSets(m_device->device(), &alloc_info,
+ &descriptorSet);
+ ASSERT_VK_SUCCESS(err);
+
+ err = vkFreeDescriptorSets(m_device->device(), ds_pool_two, 1, &descriptorSet);
+
+ m_errorMonitor->VerifyFound();
+
+ vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
+ vkDestroyDescriptorPool(m_device->device(), ds_pool_one, NULL);
+ vkDestroyDescriptorPool(m_device->device(), ds_pool_two, NULL);
+}
+
+TEST_F(VkLayerTest, CreateUnknownObject) {
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ "Invalid VkImage Object ");
+
+ TEST_DESCRIPTION(
+ "Pass an invalid image object handle into a Vulkan API call.");
+
+ ASSERT_NO_FATAL_FAILURE(InitState());
+
+ // Pass bogus handle into GetImageMemoryRequirements
+ VkMemoryRequirements mem_reqs;
+ uint64_t fakeImageHandle = 0xCADECADE;
+ VkImage fauxImage = reinterpret_cast<VkImage &>(fakeImageHandle);
+
+ vkGetImageMemoryRequirements(m_device->device(), fauxImage, &mem_reqs);
+
+ m_errorMonitor->VerifyFound();
+}
+
TEST_F(VkLayerTest, PipelineNotBound) {
VkResult err;
+ TEST_DESCRIPTION(
+ "Pass in an invalid pipeline object handle into a Vulkan API call.");
+
m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
"Invalid VkPipeline Object ");