1 /*
2  * Copyright (c) 2015-2020 The Khronos Group Inc.
3  * Copyright (c) 2015-2020 Valve Corporation
4  * Copyright (c) 2015-2020 LunarG, Inc.
5  * Copyright (c) 2015-2020 Google, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Author: Camden Stocker <camden@lunarg.com>
14  */
15 
16 #include "cast_utils.h"
17 #include "layer_validation_tests.h"
18 
InitBestPracticesFramework()19 void VkBestPracticesLayerTest::InitBestPracticesFramework() {
20     // Enable all vendor-specific checks
21     VkLayerSettingValueDataEXT bp_setting_string_value{};
22     bp_setting_string_value.arrayString.pCharArray = "VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_ALL";
23     bp_setting_string_value.arrayString.count = sizeof(bp_setting_string_value.arrayString.pCharArray);
24     VkLayerSettingValueEXT bp_vendor_all_setting_val = {"enables", VK_LAYER_SETTING_VALUE_TYPE_STRING_ARRAY_EXT,
25                                                         bp_setting_string_value};
26     VkLayerSettingsEXT bp_settings{static_cast<VkStructureType>(VK_STRUCTURE_TYPE_INSTANCE_LAYER_SETTINGS_EXT), nullptr, 1,
27                                    &bp_vendor_all_setting_val};
28     features_.pNext = &bp_settings;
29     InitFramework(m_errorMonitor, &features_);
30 }
31 
TEST_F(VkBestPracticesLayerTest,ValidateReturnCodes)32 TEST_F(VkBestPracticesLayerTest, ValidateReturnCodes) {
33     uint32_t version = SetTargetApiVersion(VK_API_VERSION_1_2);
34     if (version < VK_API_VERSION_1_1) {
35         printf("%s At least Vulkan version 1.2 is required, skipping test.\n", kSkipPrefix);
36         return;
37     }
38 
39     if (!AddSurfaceInstanceExtension()) {
40         printf("%s surface extensions not supported, skipping test\n", kSkipPrefix);
41         return;
42     }
43 
44     ASSERT_NO_FATAL_FAILURE(InitBestPracticesFramework());
45 
46     if (!AddSwapchainDeviceExtension()) {
47         printf("%s swapchain extensions not supported, skipping CmdCopySwapchainImage test\n", kSkipPrefix);
48         return;
49     }
50 
51     ASSERT_NO_FATAL_FAILURE(InitState());
52 
53     if (!InitSwapchain()) {
54         printf("%s Cannot create surface or swapchain, skipping CmdCopySwapchainImage test\n", kSkipPrefix);
55         return;
56     }
57 
58     // Attempt to force an invalid return code for an unsupported format
59     VkImageFormatProperties2 image_format_prop = {};
60     image_format_prop.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
61     VkPhysicalDeviceImageFormatInfo2 image_format_info = {};
62     image_format_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
63     image_format_info.format = VK_FORMAT_R32G32B32_SFLOAT;
64     image_format_info.tiling = VK_IMAGE_TILING_LINEAR;
65     image_format_info.type = VK_IMAGE_TYPE_3D;
66     image_format_info.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
67 
68     VkResult result = vk::GetPhysicalDeviceImageFormatProperties2(m_device->phy().handle(), &image_format_info, &image_format_prop);
69     // Only run this test if this super-wierd format is not supported
70     if (VK_SUCCESS != result) {
71         m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-BestPractices-Error-Result");
72         vk::GetPhysicalDeviceImageFormatProperties2(m_device->phy().handle(), &image_format_info, &image_format_prop);
73         m_errorMonitor->VerifyFound();
74     }
75 
76     if (IsPlatform(kMockICD) || DeviceSimulation()) {
77         printf("%s Test not supported by MockICD, skipping test case.\n", kSkipPrefix);
78         return;
79     }
80 
81     // Force a non-success success code by only asking for a subset of query results
82     uint32_t format_count;
83     std::vector<VkSurfaceFormatKHR> formats;
84     result = vk::GetPhysicalDeviceSurfaceFormatsKHR(gpu(), m_surface, &format_count, NULL);
85     if (result != VK_SUCCESS || format_count <= 1) {
86         printf("%s test requires 2 or more extensions available, skipping test.\n", kSkipPrefix);
87         return;
88     }
89     format_count -= 1;
90     formats.resize(format_count);
91 
92     m_errorMonitor->SetDesiredFailureMsg(kInformationBit, "UNASSIGNED-BestPractices-NonSuccess-Result");
93     result = vk::GetPhysicalDeviceSurfaceFormatsKHR(gpu(), m_surface, &format_count, formats.data());
94     m_errorMonitor->VerifyFound();
95 }
96 
TEST_F(VkBestPracticesLayerTest,UseDeprecatedInstanceExtensions)97 TEST_F(VkBestPracticesLayerTest, UseDeprecatedInstanceExtensions) {
98     TEST_DESCRIPTION("Create an instance with a deprecated extension.");
99 
100     uint32_t version = SetTargetApiVersion(VK_API_VERSION_1_1);
101     if (version < VK_API_VERSION_1_1) {
102         printf("%s At least Vulkan version 1.1 is required, skipping test.\n", kSkipPrefix);
103         return;
104     }
105 
106     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
107         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
108     } else {
109         printf("%s Did not find %s extension, skipped.\n", kSkipPrefix, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
110         return;
111     }
112     ASSERT_NO_FATAL_FAILURE(InitBestPracticesFramework());
113 
114     // Create a 1.1 vulkan instance and request an extension promoted to core in 1.1
115     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-BestPractices-vkCreateInstance-deprecated-extension");
116     VkInstance dummy;
117     auto features = features_;
118     auto ici = GetInstanceCreateInfo();
119     features.pNext = ici.pNext;
120     ici.pNext = &features;
121     vk::CreateInstance(&ici, nullptr, &dummy);
122     m_errorMonitor->VerifyFound();
123 
124     // Create a 1.0 vulkan instance and request an extension promoted to core in 1.1
125     m_errorMonitor->ExpectSuccess(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT);
126     m_errorMonitor->SetUnexpectedError("UNASSIGNED-khronos-Validation-debug-build-warning-message");
127     VkApplicationInfo* new_info = new VkApplicationInfo;
128     new_info->apiVersion = VK_API_VERSION_1_0;
129     new_info->pApplicationName = ici.pApplicationInfo->pApplicationName;
130     new_info->applicationVersion = ici.pApplicationInfo->applicationVersion;
131     new_info->pEngineName = ici.pApplicationInfo->pEngineName;
132     new_info->engineVersion = ici.pApplicationInfo->engineVersion;
133     ici.pApplicationInfo = new_info;
134     vk::CreateInstance(&ici, nullptr, &dummy);
135     vk::DestroyInstance(dummy, nullptr);
136     m_errorMonitor->VerifyNotFound();
137 }
138 
TEST_F(VkBestPracticesLayerTest,UseDeprecatedDeviceExtensions)139 TEST_F(VkBestPracticesLayerTest, UseDeprecatedDeviceExtensions) {
140     TEST_DESCRIPTION("Create a device with a deprecated extension.");
141 
142     uint32_t version = SetTargetApiVersion(VK_API_VERSION_1_2);
143     if (version < VK_API_VERSION_1_2) {
144         printf("%s At least Vulkan version 1.2 is required, skipping test.\n", kSkipPrefix);
145         return;
146     }
147 
148     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
149         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
150     } else {
151         printf("%s Did not find %s extension, skipped.\n", kSkipPrefix, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
152         return;
153     }
154 
155     ASSERT_NO_FATAL_FAILURE(InitBestPracticesFramework());
156 
157     if (DeviceValidationVersion() < VK_API_VERSION_1_2) {
158         printf("%s At least Vulkan version 1.2 is required for device, skipping test\n", kSkipPrefix);
159         return;
160     }
161 
162     if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {
163         m_device_extension_names.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
164     } else {
165         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
166         return;
167     }
168 
169     VkDevice local_device;
170     VkDeviceCreateInfo dev_info = {};
171     VkDeviceQueueCreateInfo queue_info = {};
172     queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
173     queue_info.pNext = NULL;
174     queue_info.queueFamilyIndex = 0;
175     queue_info.queueCount = 1;
176     queue_info.pQueuePriorities = nullptr;
177     dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
178     dev_info.pNext = nullptr;
179     dev_info.queueCreateInfoCount = 1;
180     dev_info.pQueueCreateInfos = &queue_info;
181     dev_info.enabledLayerCount = 0;
182     dev_info.ppEnabledLayerNames = NULL;
183     dev_info.enabledExtensionCount = m_device_extension_names.size();
184     dev_info.ppEnabledExtensionNames = m_device_extension_names.data();
185 
186     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-BestPractices-vkCreateDevice-deprecated-extension");
187     vk::CreateDevice(this->gpu(), &dev_info, NULL, &local_device);
188     m_errorMonitor->VerifyFound();
189 }
190 
TEST_F(VkBestPracticesLayerTest,CmdClearAttachmentTest)191 TEST_F(VkBestPracticesLayerTest, CmdClearAttachmentTest) {
192     TEST_DESCRIPTION("Test for validating usage of vkCmdClearAttachments");
193 
194     InitBestPracticesFramework();
195     InitState();
196     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
197 
198     m_commandBuffer->begin();
199     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
200 
201     // Main thing we care about for this test is that the VkImage obj we're
202     // clearing matches Color Attachment of FB
203     //  Also pass down other dummy params to keep driver and paramchecker happy
204     VkClearAttachment color_attachment;
205     color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
206     color_attachment.clearValue.color.float32[0] = 1.0;
207     color_attachment.clearValue.color.float32[1] = 1.0;
208     color_attachment.clearValue.color.float32[2] = 1.0;
209     color_attachment.clearValue.color.float32[3] = 1.0;
210     color_attachment.colorAttachment = 0;
211     VkClearRect clear_rect = {{{0, 0}, {(uint32_t)m_width, (uint32_t)m_height}}, 0, 1};
212 
213     // Call for full-sized FB Color attachment prior to issuing a Draw
214     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-DrawState-ClearCmdBeforeDraw");
215     vk::CmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
216     m_errorMonitor->VerifyFound();
217 }
218 
TEST_F(VkBestPracticesLayerTest,VtxBufferBadIndex)219 TEST_F(VkBestPracticesLayerTest, VtxBufferBadIndex) {
220     InitBestPracticesFramework();
221     InitState();
222 
223     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-DrawState-VtxIndexOutOfBounds");
224 
225     // This test may also trigger other warnings
226     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkAllocateMemory-small-allocation");
227     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkBindMemory-small-dedicated-allocation");
228 
229     ASSERT_NO_FATAL_FAILURE(InitViewport());
230     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
231 
232     VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {};
233     pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
234     pipe_ms_state_ci.pNext = NULL;
235     pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
236     pipe_ms_state_ci.sampleShadingEnable = 0;
237     pipe_ms_state_ci.minSampleShading = 1.0;
238     pipe_ms_state_ci.pSampleMask = NULL;
239 
240     CreatePipelineHelper pipe(*this);
241     pipe.InitInfo();
242     pipe.pipe_ms_state_ci_ = pipe_ms_state_ci;
243     pipe.InitState();
244     pipe.CreateGraphicsPipeline();
245 
246     m_commandBuffer->begin();
247     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
248     vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
249     // Don't care about actual data, just need to get to draw to flag error
250     const float vbo_data[3] = {1.f, 0.f, 1.f};
251     VkConstantBufferObj vbo(m_device, sizeof(vbo_data), (const void*)&vbo_data, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
252     m_commandBuffer->BindVertexBuffer(&vbo, (VkDeviceSize)0, 1);  // VBO idx 1, but no VBO in PSO
253     m_commandBuffer->Draw(1, 0, 0, 0);
254 
255     m_errorMonitor->VerifyFound();
256 
257     m_commandBuffer->EndRenderPass();
258     m_commandBuffer->end();
259 }
260 
261 // This is a positive test. No failures are expected.
TEST_F(VkBestPracticesLayerTest,TestDestroyFreeNullHandles)262 TEST_F(VkBestPracticesLayerTest, TestDestroyFreeNullHandles) {
263     VkResult err;
264 
265     TEST_DESCRIPTION("Call all applicable destroy and free routines with NULL handles, expecting no validation errors");
266 
267     InitBestPracticesFramework();
268     InitState();
269 
270     ASSERT_NO_FATAL_FAILURE(InitViewport());
271     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
272 
273     m_errorMonitor->ExpectSuccess();
274 
275     vk::DestroyBuffer(m_device->device(), VK_NULL_HANDLE, NULL);
276     vk::DestroyBufferView(m_device->device(), VK_NULL_HANDLE, NULL);
277     vk::DestroyCommandPool(m_device->device(), VK_NULL_HANDLE, NULL);
278     vk::DestroyDescriptorPool(m_device->device(), VK_NULL_HANDLE, NULL);
279     vk::DestroyDescriptorSetLayout(m_device->device(), VK_NULL_HANDLE, NULL);
280     vk::DestroyDevice(VK_NULL_HANDLE, NULL);
281     vk::DestroyEvent(m_device->device(), VK_NULL_HANDLE, NULL);
282     vk::DestroyFence(m_device->device(), VK_NULL_HANDLE, NULL);
283     vk::DestroyFramebuffer(m_device->device(), VK_NULL_HANDLE, NULL);
284     vk::DestroyImage(m_device->device(), VK_NULL_HANDLE, NULL);
285     vk::DestroyImageView(m_device->device(), VK_NULL_HANDLE, NULL);
286     vk::DestroyInstance(VK_NULL_HANDLE, NULL);
287     vk::DestroyPipeline(m_device->device(), VK_NULL_HANDLE, NULL);
288     vk::DestroyPipelineCache(m_device->device(), VK_NULL_HANDLE, NULL);
289     vk::DestroyPipelineLayout(m_device->device(), VK_NULL_HANDLE, NULL);
290     vk::DestroyQueryPool(m_device->device(), VK_NULL_HANDLE, NULL);
291     vk::DestroyRenderPass(m_device->device(), VK_NULL_HANDLE, NULL);
292     vk::DestroySampler(m_device->device(), VK_NULL_HANDLE, NULL);
293     vk::DestroySemaphore(m_device->device(), VK_NULL_HANDLE, NULL);
294     vk::DestroyShaderModule(m_device->device(), VK_NULL_HANDLE, NULL);
295 
296     VkCommandPool command_pool;
297     VkCommandPoolCreateInfo pool_create_info{};
298     pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
299     pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
300     pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
301     vk::CreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool);
302     VkCommandBuffer command_buffers[3] = {};
303     VkCommandBufferAllocateInfo command_buffer_allocate_info{};
304     command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
305     command_buffer_allocate_info.commandPool = command_pool;
306     command_buffer_allocate_info.commandBufferCount = 1;
307     command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
308     vk::AllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &command_buffers[1]);
309     vk::FreeCommandBuffers(m_device->device(), command_pool, 3, command_buffers);
310     vk::DestroyCommandPool(m_device->device(), command_pool, NULL);
311 
312     VkDescriptorPoolSize ds_type_count = {};
313     ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
314     ds_type_count.descriptorCount = 1;
315 
316     VkDescriptorPoolCreateInfo ds_pool_ci = {};
317     ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
318     ds_pool_ci.pNext = NULL;
319     ds_pool_ci.maxSets = 1;
320     ds_pool_ci.poolSizeCount = 1;
321     ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
322     ds_pool_ci.pPoolSizes = &ds_type_count;
323 
324     VkDescriptorPool ds_pool;
325     err = vk::CreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
326     ASSERT_VK_SUCCESS(err);
327 
328     VkDescriptorSetLayoutBinding dsl_binding = {};
329     dsl_binding.binding = 2;
330     dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
331     dsl_binding.descriptorCount = 1;
332     dsl_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
333     dsl_binding.pImmutableSamplers = NULL;
334 
335     const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding});
336 
337     VkDescriptorSet descriptor_sets[3] = {};
338     VkDescriptorSetAllocateInfo alloc_info = {};
339     alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
340     alloc_info.descriptorSetCount = 1;
341     alloc_info.descriptorPool = ds_pool;
342     alloc_info.pSetLayouts = &ds_layout.handle();
343     err = vk::AllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_sets[1]);
344     ASSERT_VK_SUCCESS(err);
345     vk::FreeDescriptorSets(m_device->device(), ds_pool, 3, descriptor_sets);
346     vk::DestroyDescriptorPool(m_device->device(), ds_pool, NULL);
347 
348     vk::FreeMemory(m_device->device(), VK_NULL_HANDLE, NULL);
349 
350     m_errorMonitor->VerifyNotFound();
351 }
352 
TEST_F(VkBestPracticesLayerTest,CommandBufferReset)353 TEST_F(VkBestPracticesLayerTest, CommandBufferReset) {
354     TEST_DESCRIPTION("Test for validating usage of vkCreateCommandPool with COMMAND_BUFFER_RESET_BIT");
355 
356     InitBestPracticesFramework();
357     InitState();
358 
359     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
360                                          "UNASSIGNED-BestPractices-vkCreateCommandPool-command-buffer-reset");
361 
362     VkCommandPool command_pool;
363     VkCommandPoolCreateInfo pool_create_info{};
364     pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
365     pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
366     pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
367     vk::CreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool);
368 
369     m_errorMonitor->VerifyFound();
370 }
371 
TEST_F(VkBestPracticesLayerTest,SimultaneousUse)372 TEST_F(VkBestPracticesLayerTest, SimultaneousUse) {
373     TEST_DESCRIPTION("Test for validating usage of vkBeginCommandBuffer with SIMULTANEOUS_USE");
374 
375     InitBestPracticesFramework();
376     InitState();
377 
378     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-vkBeginCommandBuffer-simultaneous-use");
379 
380     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkBeginCommandBuffer-one-time-submit");
381 
382     VkCommandBufferBeginInfo cmd_begin_info{};
383     cmd_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
384     cmd_begin_info.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
385     vk::BeginCommandBuffer(m_commandBuffer->handle(), &cmd_begin_info);
386 
387     m_errorMonitor->VerifyFound();
388 }
389 
TEST_F(VkBestPracticesLayerTest,SmallAllocation)390 TEST_F(VkBestPracticesLayerTest, SmallAllocation) {
391     TEST_DESCRIPTION("Test for small memory allocations");
392 
393     InitBestPracticesFramework();
394     InitState();
395 
396     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-vkAllocateMemory-small-allocation");
397 
398     // Find appropriate memory type for given reqs
399     VkMemoryPropertyFlags mem_props = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
400     VkPhysicalDeviceMemoryProperties dev_mem_props = m_device->phy().memory_properties();
401 
402     uint32_t mem_type_index = 0;
403     for (mem_type_index = 0; mem_type_index < dev_mem_props.memoryTypeCount; ++mem_type_index) {
404         if (mem_props == (mem_props & dev_mem_props.memoryTypes[mem_type_index].propertyFlags)) break;
405     }
406     EXPECT_LT(mem_type_index, dev_mem_props.memoryTypeCount) << "Could not find a suitable memory type.";
407 
408     const uint32_t kSmallAllocationSize = 1024;
409 
410     VkMemoryAllocateInfo alloc_info{};
411     alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
412     alloc_info.allocationSize = kSmallAllocationSize;
413     alloc_info.memoryTypeIndex = mem_type_index;
414 
415     VkDeviceMemory memory;
416     vk::AllocateMemory(m_device->device(), &alloc_info, nullptr, &memory);
417 
418     m_errorMonitor->VerifyFound();
419 }
420 
TEST_F(VkBestPracticesLayerTest,SmallDedicatedAllocation)421 TEST_F(VkBestPracticesLayerTest, SmallDedicatedAllocation) {
422     TEST_DESCRIPTION("Test for small dedicated memory allocations");
423 
424     InitBestPracticesFramework();
425     InitState();
426 
427     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
428                                          "UNASSIGNED-BestPractices-vkBindMemory-small-dedicated-allocation");
429 
430     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkAllocateMemory-small-allocation");
431 
432     VkImageCreateInfo image_info{};
433     image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
434     image_info.extent = {64, 64, 1};
435     image_info.format = VK_FORMAT_R8G8B8A8_UNORM;
436     image_info.imageType = VK_IMAGE_TYPE_2D;
437     image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
438     image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
439     image_info.samples = VK_SAMPLE_COUNT_1_BIT;
440     image_info.arrayLayers = 1;
441     image_info.mipLevels = 1;
442 
443     // Create a small image with a dedicated allocation
444     VkImageObj image(m_device);
445     image.init_no_mem(*m_device, image_info);
446 
447     vk_testing::DeviceMemory mem;
448     mem.init(*m_device, vk_testing::DeviceMemory::get_resource_alloc_info(*m_device, image.memory_requirements(),
449                                                                           VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
450     vk::BindImageMemory(device(), image.handle(), mem.handle(), 0);
451 
452     m_errorMonitor->VerifyFound();
453 }
454 
TEST_F(VkBestPracticesLayerTest,MSImageRequiresMemory)455 TEST_F(VkBestPracticesLayerTest, MSImageRequiresMemory) {
456     TEST_DESCRIPTION("Test for MS image that requires memory");
457 
458     InitBestPracticesFramework();
459     InitState();
460 
461     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
462                                          "UNASSIGNED-BestPractices-vkCreateRenderPass-image-requires-memory");
463 
464     VkAttachmentDescription attachment{};
465     attachment.samples = VK_SAMPLE_COUNT_4_BIT;
466     attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
467     attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
468 
469     VkRenderPassCreateInfo rp_info{};
470     rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
471     rp_info.attachmentCount = 1;
472     rp_info.pAttachments = &attachment;
473 
474     VkRenderPass rp;
475     vk::CreateRenderPass(m_device->device(), &rp_info, nullptr, &rp);
476 
477     m_errorMonitor->VerifyFound();
478 }
479 
TEST_F(VkBestPracticesLayerTest,AttachmentShouldNotBeTransient)480 TEST_F(VkBestPracticesLayerTest, AttachmentShouldNotBeTransient) {
481     TEST_DESCRIPTION("Test for non-lazy multisampled images");
482 
483     InitBestPracticesFramework();
484     InitState();
485 
486     if (IsPlatform(kPixel2XL) || IsPlatform(kPixel3) || IsPlatform(kPixel3aXL) || IsPlatform(kShieldTV) || IsPlatform(kShieldTVb) ||
487         IsPlatform(kNexusPlayer)) {
488         printf("%s This test seems super-picky on Android platforms\n", kSkipPrefix);
489         return;
490     }
491 
492     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
493                                          "UNASSIGNED-BestPractices-vkCreateFramebuffer-attachment-should-not-be-transient");
494 
495     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkAllocateMemory-small-allocation");
496     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkBindMemory-small-dedicated-allocation");
497     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkBindImageMemory-non-lazy-transient-image");
498 
499     VkAttachmentDescription attachment{};
500     attachment.samples = VK_SAMPLE_COUNT_1_BIT;
501     attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
502     attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
503 
504     VkRenderPassCreateInfo rp_info{};
505     rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
506     rp_info.attachmentCount = 1;
507     rp_info.pAttachments = &attachment;
508 
509     VkRenderPass rp = VK_NULL_HANDLE;
510     vk::CreateRenderPass(m_device->device(), &rp_info, nullptr, &rp);
511 
512     VkImageCreateInfo image_info{};
513     image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
514     image_info.extent = {1920, 1080, 1};
515     image_info.format = VK_FORMAT_R8G8B8A8_UNORM;
516     image_info.imageType = VK_IMAGE_TYPE_2D;
517     image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
518     image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
519     image_info.samples = VK_SAMPLE_COUNT_1_BIT;
520     image_info.arrayLayers = 1;
521     image_info.mipLevels = 1;
522 
523     VkImageObj image(m_device);
524     image.init(&image_info);
525 
526     VkImageViewCreateInfo iv_info{};
527     iv_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
528     iv_info.format = VK_FORMAT_R8G8B8A8_UNORM;
529     iv_info.image = image.handle();
530     iv_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
531     iv_info.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
532     iv_info.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
533 
534     VkImageView image_view = VK_NULL_HANDLE;
535     vk::CreateImageView(m_device->device(), &iv_info, nullptr, &image_view);
536 
537     VkFramebufferCreateInfo fb_info{};
538     fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
539     fb_info.renderPass = rp;
540     fb_info.layers = 1;
541     fb_info.width = 1920;
542     fb_info.height = 1080;
543     fb_info.attachmentCount = 1;
544     fb_info.pAttachments = &image_view;
545 
546     VkFramebuffer fb = VK_NULL_HANDLE;
547     vk::CreateFramebuffer(m_device->device(), &fb_info, nullptr, &fb);
548 
549     m_errorMonitor->VerifyFound();
550 }
551 
TEST_F(VkBestPracticesLayerTest,TooManyInstancedVertexBuffers)552 TEST_F(VkBestPracticesLayerTest, TooManyInstancedVertexBuffers) {
553     TEST_DESCRIPTION("Test for too many instanced vertex buffers");
554 
555     InitBestPracticesFramework();
556     InitState();
557 
558     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
559                                          "UNASSIGNED-BestPractices-vkCreateGraphicsPipelines-too-many-instanced-vertex-buffers");
560 
561     // This test may also trigger the small allocation warnings
562     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkAllocateMemory-small-allocation");
563     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkBindMemory-small-dedicated-allocation");
564 
565     ASSERT_NO_FATAL_FAILURE(InitViewport());
566     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
567 
568     std::vector<VkVertexInputBindingDescription> bindings(2, VkVertexInputBindingDescription{});
569     std::vector<VkVertexInputAttributeDescription> attributes(2, VkVertexInputAttributeDescription{});
570 
571     bindings[0].binding = 0;
572     bindings[0].stride = 4;
573     bindings[0].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
574 
575     attributes[0].binding = 0;
576 
577     bindings[1].binding = 1;
578     bindings[1].stride = 8;
579     bindings[1].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
580 
581     attributes[1].binding = 1;
582 
583     VkPipelineVertexInputStateCreateInfo vi_state_ci{};
584     vi_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
585     vi_state_ci.vertexBindingDescriptionCount = static_cast<uint32_t>(bindings.size());
586     vi_state_ci.pVertexBindingDescriptions = bindings.data();
587     vi_state_ci.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributes.size());
588     vi_state_ci.pVertexAttributeDescriptions = attributes.data();
589 
590     CreatePipelineHelper pipe(*this);
591     pipe.InitInfo();
592     pipe.vi_ci_ = vi_state_ci;
593     pipe.InitState();
594     pipe.CreateGraphicsPipeline();
595 
596     m_errorMonitor->VerifyFound();
597 }
598 
TEST_F(VkBestPracticesLayerTest,ClearAttachmentsAfterLoad)599 TEST_F(VkBestPracticesLayerTest, ClearAttachmentsAfterLoad) {
600     TEST_DESCRIPTION("Test for clearing attachments after load");
601 
602     InitBestPracticesFramework();
603     InitState();
604 
605     m_clear_via_load_op = false;  // Force LOAD_OP_LOAD
606     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
607 
608     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-vkCmdClearAttachments-clear-after-load");
609 
610     // On tiled renderers, this can also trigger a warning about LOAD_OP_LOAD causing a readback
611     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkCmdBeginRenderPass-attachment-needs-readback");
612     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-DrawState-ClearCmdBeforeDraw");
613 
614     m_commandBuffer->begin();
615     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
616 
617     VkClearAttachment color_attachment;
618     color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
619     color_attachment.clearValue.color.float32[0] = 1.0;
620     color_attachment.clearValue.color.float32[1] = 1.0;
621     color_attachment.clearValue.color.float32[2] = 1.0;
622     color_attachment.clearValue.color.float32[3] = 1.0;
623     color_attachment.colorAttachment = 0;
624     VkClearRect clear_rect = {{{0, 0}, {(uint32_t)m_width, (uint32_t)m_height}}, 0, 1};
625 
626     vk::CmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
627 
628     m_errorMonitor->VerifyFound();
629 }
630 
TEST_F(VkBestPracticesLayerTest,TripleBufferingTest)631 TEST_F(VkBestPracticesLayerTest, TripleBufferingTest) {
632     TEST_DESCRIPTION("Test for usage of triple buffering");
633 
634     AddSurfaceInstanceExtension();
635     InitBestPracticesFramework();
636     AddSwapchainDeviceExtension();
637     InitState();
638     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
639                                          "UNASSIGNED-BestPractices-vkCreateSwapchainKHR-suboptimal-swapchain-image-count");
640     InitSurface();
641     VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
642     VkSurfaceTransformFlagBitsKHR preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
643     VkSurfaceCapabilitiesKHR capabilities;
644     vk::GetPhysicalDeviceSurfaceCapabilitiesKHR(m_device->phy().handle(), m_surface, &capabilities);
645 
646     uint32_t format_count;
647     vk::GetPhysicalDeviceSurfaceFormatsKHR(m_device->phy().handle(), m_surface, &format_count, nullptr);
648     vector<VkSurfaceFormatKHR> formats;
649     if (format_count != 0) {
650         formats.resize(format_count);
651         vk::GetPhysicalDeviceSurfaceFormatsKHR(m_device->phy().handle(), m_surface, &format_count, formats.data());
652     }
653 
654     uint32_t present_mode_count;
655     vk::GetPhysicalDeviceSurfacePresentModesKHR(m_device->phy().handle(), m_surface, &present_mode_count, nullptr);
656     vector<VkPresentModeKHR> present_modes;
657     if (present_mode_count != 0) {
658         present_modes.resize(present_mode_count);
659         vk::GetPhysicalDeviceSurfacePresentModesKHR(m_device->phy().handle(), m_surface, &present_mode_count, present_modes.data());
660     }
661 
662     VkSwapchainCreateInfoKHR swapchain_create_info = {};
663     swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
664     swapchain_create_info.pNext = 0;
665     swapchain_create_info.surface = m_surface;
666     swapchain_create_info.minImageCount = 2;
667     swapchain_create_info.imageFormat = formats[0].format;
668     swapchain_create_info.imageColorSpace = formats[0].colorSpace;
669     swapchain_create_info.imageExtent = {capabilities.minImageExtent.width, capabilities.minImageExtent.height};
670     swapchain_create_info.imageArrayLayers = 1;
671     swapchain_create_info.imageUsage = imageUsage;
672     swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
673     swapchain_create_info.preTransform = preTransform;
674 #ifdef VK_USE_PLATFORM_ANDROID_KHR
675     swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
676 #else
677     swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
678 #endif
679     swapchain_create_info.presentMode = present_modes[0];
680     swapchain_create_info.clipped = VK_FALSE;
681     swapchain_create_info.oldSwapchain = 0;
682 
683     VkResult err = vk::CreateSwapchainKHR(device(), &swapchain_create_info, nullptr, &m_swapchain);
684     m_errorMonitor->VerifyFound();
685 
686     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
687                                          "UNASSIGNED-BestPractices-vkCreateSwapchainKHR-suboptimal-swapchain-image-count");
688     swapchain_create_info.minImageCount = 3;
689     err = vk::CreateSwapchainKHR(device(), &swapchain_create_info, nullptr, &m_swapchain);
690     m_errorMonitor->VerifyNotFound();
691     ASSERT_VK_SUCCESS(err)
692     DestroySwapchain();
693 }
694 
TEST_F(VkBestPracticesLayerTest,ExpectedQueryDetails)695 TEST_F(VkBestPracticesLayerTest, ExpectedQueryDetails) {
696     TEST_DESCRIPTION("Check that GetPhysicalDeviceQueueFamilyProperties is working as expected");
697 
698     ASSERT_NO_FATAL_FAILURE(InitBestPracticesFramework());
699     const vk_testing::PhysicalDevice phys_device_obj(gpu_);
700 
701     std::vector<VkQueueFamilyProperties> queue_family_props;
702 
703     m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit);
704 
705     // Ensure we can find a graphics queue family.
706     uint32_t queue_count = 0;
707     vk::GetPhysicalDeviceQueueFamilyProperties(phys_device_obj.handle(), &queue_count, nullptr);
708 
709     queue_family_props.resize(queue_count);
710     vk::GetPhysicalDeviceQueueFamilyProperties(phys_device_obj.handle(), &queue_count, queue_family_props.data());
711 
712     vk_testing::Device device(phys_device_obj.handle());
713     device.init();
714 }
715 
TEST_F(VkBestPracticesLayerTest,MissingQueryDetails)716 TEST_F(VkBestPracticesLayerTest, MissingQueryDetails) {
717     TEST_DESCRIPTION("Check that GetPhysicalDeviceQueueFamilyProperties generates appropriate query warning");
718 
719     ASSERT_NO_FATAL_FAILURE(InitBestPracticesFramework());
720     const vk_testing::PhysicalDevice phys_device_obj(gpu_);
721 
722     std::vector<VkQueueFamilyProperties> queue_family_props(1);
723     uint32_t queue_count = static_cast<uint32_t>(queue_family_props.size());
724 
725     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-CoreValidation-DevLimit-MissingQueryCount");
726     vk::GetPhysicalDeviceQueueFamilyProperties(phys_device_obj.handle(), &queue_count, queue_family_props.data());
727     m_errorMonitor->VerifyFound();
728 
729     // Now get information correctly
730     m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit);
731 
732     vk_testing::QueueCreateInfoArray queue_info(phys_device_obj.queue_properties());
733     // Only request creation with queuefamilies that have at least one queue
734     std::vector<VkDeviceQueueCreateInfo> create_queue_infos;
735     auto qci = queue_info.data();
736     for (uint32_t j = 0; j < queue_info.size(); ++j) {
737         if (qci[j].queueCount) {
738             create_queue_infos.push_back(qci[j]);
739         }
740     }
741     m_errorMonitor->VerifyNotFound();
742 
743     VkPhysicalDeviceFeatures all_features;
744     VkDeviceCreateInfo device_ci = {};
745     device_ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
746     device_ci.pNext = nullptr;
747     device_ci.queueCreateInfoCount = create_queue_infos.size();
748     device_ci.pQueueCreateInfos = create_queue_infos.data();
749     device_ci.enabledLayerCount = 0;
750     device_ci.ppEnabledLayerNames = NULL;
751     device_ci.enabledExtensionCount = 0;
752     device_ci.ppEnabledExtensionNames = nullptr;
753     device_ci.pEnabledFeatures = &all_features;
754 
755     // vkGetPhysicalDeviceFeatures has not been called, so this should produce a warning
756     m_errorMonitor->SetDesiredFailureMsg(kWarningBit,
757                                          "UNASSIGNED-BestPractices-vkCreateDevice-physical-device-features-not-retrieved");
758     VkDevice device;
759     vk::CreateDevice(phys_device_obj.handle(), &device_ci, nullptr, &device);
760     m_errorMonitor->VerifyFound();
761 }