1 /*
2  * Copyright (c) 2015-2021 The Khronos Group Inc.
3  * Copyright (c) 2015-2021 Valve Corporation
4  * Copyright (c) 2015-2021 LunarG, Inc.
5  * Copyright (c) 2015-2021 Google, Inc.
6  * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Author: Camden Stocker <camden@lunarg.com>
15  * Author: Nadav Geva <nadav.geva@amd.com>
16  */
17 
18 #include "cast_utils.h"
19 #include "layer_validation_tests.h"
20 #include "best_practices_error_enums.h"
21 
InitBestPracticesFramework()22 void VkBestPracticesLayerTest::InitBestPracticesFramework() {
23     // Enable all vendor-specific checks
24     InitBestPracticesFramework("");
25 }
26 
InitBestPracticesFramework(const char * vendor_checks_to_enable)27 void VkBestPracticesLayerTest::InitBestPracticesFramework(const char* vendor_checks_to_enable) {
28     // Enable the vendor-specific checks spcified by vendor_checks_to_enable
29     VkLayerSettingValueDataEXT bp_setting_string_value{};
30     bp_setting_string_value.arrayString.pCharArray = vendor_checks_to_enable;
31     bp_setting_string_value.arrayString.count = sizeof(bp_setting_string_value.arrayString.pCharArray);
32     VkLayerSettingValueEXT bp_vendor_all_setting_val = {"enables", VK_LAYER_SETTING_VALUE_TYPE_STRING_ARRAY_EXT,
33                                                         bp_setting_string_value};
34     VkLayerSettingsEXT bp_settings{static_cast<VkStructureType>(VK_STRUCTURE_TYPE_INSTANCE_LAYER_SETTINGS_EXT), nullptr, 1,
35                                    &bp_vendor_all_setting_val};
36     features_.pNext = &bp_settings;
37     InitFramework(m_errorMonitor, &features_);
38 }
39 
TEST_F(VkBestPracticesLayerTest,ValidateReturnCodes)40 TEST_F(VkBestPracticesLayerTest, ValidateReturnCodes) {
41     uint32_t version = SetTargetApiVersion(VK_API_VERSION_1_2);
42     if (version < VK_API_VERSION_1_1) {
43         printf("%s At least Vulkan version 1.2 is required, skipping test.\n", kSkipPrefix);
44         return;
45     }
46 
47     if (!AddSurfaceInstanceExtension()) {
48         printf("%s surface extensions not supported, skipping test\n", kSkipPrefix);
49         return;
50     }
51 
52     ASSERT_NO_FATAL_FAILURE(InitBestPracticesFramework());
53 
54     if (!AddSwapchainDeviceExtension()) {
55         printf("%s swapchain extensions not supported, skipping CmdCopySwapchainImage test\n", kSkipPrefix);
56         return;
57     }
58 
59     ASSERT_NO_FATAL_FAILURE(InitState());
60 
61     if (!InitSwapchain()) {
62         printf("%s Cannot create surface or swapchain, skipping CmdCopySwapchainImage test\n", kSkipPrefix);
63         return;
64     }
65 
66     // Attempt to force an invalid return code for an unsupported format
67     VkImageFormatProperties2 image_format_prop = {};
68     image_format_prop.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
69     VkPhysicalDeviceImageFormatInfo2 image_format_info = {};
70     image_format_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
71     image_format_info.format = VK_FORMAT_R32G32B32_SFLOAT;
72     image_format_info.tiling = VK_IMAGE_TILING_LINEAR;
73     image_format_info.type = VK_IMAGE_TYPE_3D;
74     image_format_info.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
75 
76     VkResult result = vk::GetPhysicalDeviceImageFormatProperties2(m_device->phy().handle(), &image_format_info, &image_format_prop);
77     // Only run this test if this super-wierd format is not supported
78     if (VK_SUCCESS != result) {
79         m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-BestPractices-Error-Result");
80         vk::GetPhysicalDeviceImageFormatProperties2(m_device->phy().handle(), &image_format_info, &image_format_prop);
81         m_errorMonitor->VerifyFound();
82     }
83 
84     if (IsPlatform(kMockICD) || DeviceSimulation()) {
85         printf("%s Test not supported by MockICD, skipping test case.\n", kSkipPrefix);
86         return;
87     }
88 
89     // Force a non-success success code by only asking for a subset of query results
90     uint32_t format_count;
91     std::vector<VkSurfaceFormatKHR> formats;
92     result = vk::GetPhysicalDeviceSurfaceFormatsKHR(gpu(), m_surface, &format_count, NULL);
93     if (result != VK_SUCCESS || format_count <= 1) {
94         printf("%s test requires 2 or more extensions available, skipping test.\n", kSkipPrefix);
95         return;
96     }
97     format_count -= 1;
98     formats.resize(format_count);
99 
100     m_errorMonitor->SetDesiredFailureMsg(kInformationBit, "UNASSIGNED-BestPractices-NonSuccess-Result");
101     result = vk::GetPhysicalDeviceSurfaceFormatsKHR(gpu(), m_surface, &format_count, formats.data());
102     m_errorMonitor->VerifyFound();
103 }
104 
TEST_F(VkBestPracticesLayerTest,UseDeprecatedInstanceExtensions)105 TEST_F(VkBestPracticesLayerTest, UseDeprecatedInstanceExtensions) {
106     TEST_DESCRIPTION("Create an instance with a deprecated extension.");
107 
108     uint32_t version = SetTargetApiVersion(VK_API_VERSION_1_1);
109     if (version < VK_API_VERSION_1_1) {
110         printf("%s At least Vulkan version 1.1 is required, skipping test.\n", kSkipPrefix);
111         return;
112     }
113 
114     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
115         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
116     } else {
117         printf("%s Did not find %s extension, skipped.\n", kSkipPrefix, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
118         return;
119     }
120     ASSERT_NO_FATAL_FAILURE(InitBestPracticesFramework());
121 
122     // Create a 1.1 vulkan instance and request an extension promoted to core in 1.1
123     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-BestPractices-vkCreateInstance-deprecated-extension");
124     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-BestPractices-vkCreateInstance-specialuse-extension-debugging");
125     VkInstance dummy;
126     auto features = features_;
127     auto ici = GetInstanceCreateInfo();
128     features.pNext = ici.pNext;
129     ici.pNext = &features;
130     vk::CreateInstance(&ici, nullptr, &dummy);
131     m_errorMonitor->VerifyFound();
132 
133     // Create a 1.0 vulkan instance and request an extension promoted to core in 1.1
134     m_errorMonitor->ExpectSuccess(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT);
135     m_errorMonitor->SetUnexpectedError("UNASSIGNED-khronos-Validation-debug-build-warning-message");
136     VkApplicationInfo new_info{};
137     new_info.apiVersion = VK_API_VERSION_1_0;
138     new_info.pApplicationName = ici.pApplicationInfo->pApplicationName;
139     new_info.applicationVersion = ici.pApplicationInfo->applicationVersion;
140     new_info.pEngineName = ici.pApplicationInfo->pEngineName;
141     new_info.engineVersion = ici.pApplicationInfo->engineVersion;
142     ici.pApplicationInfo = &new_info;
143     vk::CreateInstance(&ici, nullptr, &dummy);
144     vk::DestroyInstance(dummy, nullptr);
145     m_errorMonitor->VerifyNotFound();
146 }
147 
TEST_F(VkBestPracticesLayerTest,UseDeprecatedDeviceExtensions)148 TEST_F(VkBestPracticesLayerTest, UseDeprecatedDeviceExtensions) {
149     TEST_DESCRIPTION("Create a device with a deprecated extension.");
150 
151     uint32_t version = SetTargetApiVersion(VK_API_VERSION_1_2);
152     if (version < VK_API_VERSION_1_2) {
153         printf("%s At least Vulkan version 1.2 is required, skipping test.\n", kSkipPrefix);
154         return;
155     }
156 
157     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
158         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
159     } else {
160         printf("%s Did not find %s extension, skipped.\n", kSkipPrefix, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
161         return;
162     }
163 
164     ASSERT_NO_FATAL_FAILURE(InitBestPracticesFramework());
165 
166     if (DeviceValidationVersion() < VK_API_VERSION_1_2) {
167         printf("%s At least Vulkan version 1.2 is required for device, skipping test\n", kSkipPrefix);
168         return;
169     }
170 
171     if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {
172         m_device_extension_names.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
173     } else {
174         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
175         return;
176     }
177 
178     VkDevice local_device;
179     VkDeviceCreateInfo dev_info = {};
180     VkDeviceQueueCreateInfo queue_info = {};
181     queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
182     queue_info.pNext = NULL;
183     queue_info.queueFamilyIndex = 0;
184     queue_info.queueCount = 1;
185     queue_info.pQueuePriorities = nullptr;
186     dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
187     dev_info.pNext = nullptr;
188     dev_info.queueCreateInfoCount = 1;
189     dev_info.pQueueCreateInfos = &queue_info;
190     dev_info.enabledLayerCount = 0;
191     dev_info.ppEnabledLayerNames = NULL;
192     dev_info.enabledExtensionCount = m_device_extension_names.size();
193     dev_info.ppEnabledExtensionNames = m_device_extension_names.data();
194 
195     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-BestPractices-vkCreateDevice-deprecated-extension");
196     vk::CreateDevice(this->gpu(), &dev_info, NULL, &local_device);
197     m_errorMonitor->VerifyFound();
198 }
199 
TEST_F(VkBestPracticesLayerTest,SpecialUseExtensions)200 TEST_F(VkBestPracticesLayerTest, SpecialUseExtensions) {
201     TEST_DESCRIPTION("Create a device with a 'specialuse' extension.");
202 
203     ASSERT_NO_FATAL_FAILURE(InitBestPracticesFramework());
204 
205     if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME)) {
206         m_device_extension_names.push_back(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME);
207     } else {
208         printf("%s %s Extension not supported, skipping test\n", kSkipPrefix, VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME);
209         return;
210     }
211 
212     VkDevice local_device;
213     VkDeviceCreateInfo dev_info = {};
214     VkDeviceQueueCreateInfo queue_info = {};
215     queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
216     queue_info.pNext = NULL;
217     queue_info.queueFamilyIndex = 0;
218     queue_info.queueCount = 1;
219     queue_info.pQueuePriorities = nullptr;
220     dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
221     dev_info.pNext = nullptr;
222     dev_info.queueCreateInfoCount = 1;
223     dev_info.pQueueCreateInfos = &queue_info;
224     dev_info.enabledLayerCount = 0;
225     dev_info.ppEnabledLayerNames = NULL;
226     dev_info.enabledExtensionCount = m_device_extension_names.size();
227     dev_info.ppEnabledExtensionNames = m_device_extension_names.data();
228 
229     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-BestPractices-vkCreateDevice-specialuse-extension-d3demulation");
230     vk::CreateDevice(this->gpu(), &dev_info, NULL, &local_device);
231     m_errorMonitor->VerifyFound();
232 }
233 
TEST_F(VkBestPracticesLayerTest,CmdClearAttachmentTest)234 TEST_F(VkBestPracticesLayerTest, CmdClearAttachmentTest) {
235     TEST_DESCRIPTION("Test for validating usage of vkCmdClearAttachments");
236 
237     InitBestPracticesFramework();
238     InitState();
239     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
240 
241     m_commandBuffer->begin();
242     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
243 
244     // Main thing we care about for this test is that the VkImage obj we're
245     // clearing matches Color Attachment of FB
246     //  Also pass down other dummy params to keep driver and paramchecker happy
247     VkClearAttachment color_attachment;
248     color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
249     color_attachment.clearValue.color.float32[0] = 1.0;
250     color_attachment.clearValue.color.float32[1] = 1.0;
251     color_attachment.clearValue.color.float32[2] = 1.0;
252     color_attachment.clearValue.color.float32[3] = 1.0;
253     color_attachment.colorAttachment = 0;
254     VkClearRect clear_rect = {{{0, 0}, {(uint32_t)m_width, (uint32_t)m_height}}, 0, 1};
255 
256     // Call for full-sized FB Color attachment prior to issuing a Draw
257     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-DrawState-ClearCmdBeforeDraw");
258 
259     vk::CmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
260     m_errorMonitor->VerifyFound();
261 }
262 
TEST_F(VkBestPracticesLayerTest,CmdClearAttachmentTestSecondary)263 TEST_F(VkBestPracticesLayerTest, CmdClearAttachmentTestSecondary) {
264     TEST_DESCRIPTION("Test for validating usage of vkCmdClearAttachments with secondary command buffers");
265 
266     InitBestPracticesFramework();
267     InitState();
268 
269     if (IsPlatform(PlatformType::kShieldTV) || IsPlatform(PlatformType::kShieldTVb)) {
270         printf("%s Test CmdClearAttachmentTestSecondary is unstable on ShieldTV, skipping test.\n", kSkipPrefix);
271         return;
272     }
273 
274     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
275 
276     m_commandBuffer->begin();
277 
278     VkCommandBufferObj secondary_full_clear(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
279     VkCommandBufferObj secondary_small_clear(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
280     VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
281     begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT |
282                        VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
283     VkCommandBufferInheritanceInfo inherit_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO };
284     begin_info.pInheritanceInfo = &inherit_info;
285     inherit_info.subpass = 0;
286     inherit_info.renderPass = m_renderPassBeginInfo.renderPass;
287 
288     // Main thing we care about for this test is that the VkImage obj we're
289     // clearing matches Color Attachment of FB
290     //  Also pass down other dummy params to keep driver and paramchecker happy
291     VkClearAttachment color_attachment;
292     color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
293     color_attachment.clearValue.color.float32[0] = 1.0;
294     color_attachment.clearValue.color.float32[1] = 1.0;
295     color_attachment.clearValue.color.float32[2] = 1.0;
296     color_attachment.clearValue.color.float32[3] = 1.0;
297     color_attachment.colorAttachment = 0;
298     VkClearRect clear_rect_small = {{{0, 0}, {(uint32_t)m_width - 1u, (uint32_t)m_height - 1u}}, 0, 1};
299     VkClearRect clear_rect = {{{0, 0}, {(uint32_t)m_width, (uint32_t)m_height}}, 0, 1};
300 
301     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
302     {
303         // Small clears which don't cover the render area should not trigger the warning.
304         vk::CmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect_small);
305         m_errorMonitor->VerifyNotFound();
306         // Call for full-sized FB Color attachment prior to issuing a Draw
307         m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-DrawState-ClearCmdBeforeDraw");
308         // This test may also trigger other warnings
309         m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-VkCommandBuffer-AvoidSecondaryCmdBuffers");
310         m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-VkCommandBuffer-AvoidSmallSecondaryCmdBuffers");
311 
312         vk::CmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
313         m_errorMonitor->VerifyFound();
314     }
315     m_commandBuffer->EndRenderPass();
316 
317     secondary_small_clear.begin(&begin_info);
318     secondary_full_clear.begin(&begin_info);
319     vk::CmdClearAttachments(secondary_small_clear.handle(), 1, &color_attachment, 1, &clear_rect_small);
320     vk::CmdClearAttachments(secondary_full_clear.handle(), 1, &color_attachment, 1, &clear_rect);
321     secondary_small_clear.end();
322     secondary_full_clear.end();
323 
324     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
325     {
326         // Small clears which don't cover the render area should not trigger the warning.
327         vk::CmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary_small_clear.handle());
328         m_errorMonitor->VerifyNotFound();
329         // Call for full-sized FB Color attachment prior to issuing a Draw
330         m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-DrawState-ClearCmdBeforeDraw");
331         // This test may also trigger other warnings
332         m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-VkCommandBuffer-AvoidSecondaryCmdBuffers");
333         m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-VkCommandBuffer-AvoidSmallSecondaryCmdBuffers");
334         m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-CmdPool-DisparateSizedCmdBuffers");
335 
336         vk::CmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary_full_clear.handle());
337         m_errorMonitor->VerifyFound();
338     }
339     m_commandBuffer->EndRenderPass();
340 }
341 
TEST_F(VkBestPracticesLayerTest,CmdBeginRenderPassZeroSizeRenderArea)342 TEST_F(VkBestPracticesLayerTest, CmdBeginRenderPassZeroSizeRenderArea) {
343     TEST_DESCRIPTION("Test for getting warned when render area is 0 in VkRenderPassBeginInfo during vkCmdBeginRenderPass");
344 
345     InitBestPracticesFramework();
346     InitState();
347     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
348 
349     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-BestPractices-vkCmdBeginRenderPass-zero-size-render-area");
350 
351     m_commandBuffer->begin();
352     m_renderPassBeginInfo.renderArea.extent.width = 0;
353     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
354 
355     m_errorMonitor->VerifyFound();
356 }
357 
TEST_F(VkBestPracticesLayerTest,VtxBufferBadIndex)358 TEST_F(VkBestPracticesLayerTest, VtxBufferBadIndex) {
359     InitBestPracticesFramework();
360     InitState();
361 
362     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-DrawState-VtxIndexOutOfBounds");
363 
364     // This test may also trigger other warnings
365     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkAllocateMemory-small-allocation");
366     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkBindMemory-small-dedicated-allocation");
367     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-VkCommandBuffer-AvoidTinyCmdBuffers");
368 
369     ASSERT_NO_FATAL_FAILURE(InitViewport());
370     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
371 
372     VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {};
373     pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
374     pipe_ms_state_ci.pNext = NULL;
375     pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
376     pipe_ms_state_ci.sampleShadingEnable = 0;
377     pipe_ms_state_ci.minSampleShading = 1.0;
378     pipe_ms_state_ci.pSampleMask = NULL;
379 
380     CreatePipelineHelper pipe(*this);
381     pipe.InitInfo();
382     pipe.pipe_ms_state_ci_ = pipe_ms_state_ci;
383     pipe.InitState();
384     pipe.CreateGraphicsPipeline();
385 
386     m_commandBuffer->begin();
387     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
388     vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
389     // Don't care about actual data, just need to get to draw to flag error
390     const float vbo_data[3] = {1.f, 0.f, 1.f};
391     VkConstantBufferObj vbo(m_device, sizeof(vbo_data), (const void*)&vbo_data, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
392     m_commandBuffer->BindVertexBuffer(&vbo, (VkDeviceSize)0, 1);  // VBO idx 1, but no VBO in PSO
393     m_commandBuffer->Draw(1, 0, 0, 0);
394 
395     m_errorMonitor->VerifyFound();
396 
397     m_commandBuffer->EndRenderPass();
398     m_commandBuffer->end();
399 }
400 
401 // This is a positive test. No failures are expected.
TEST_F(VkBestPracticesLayerTest,TestDestroyFreeNullHandles)402 TEST_F(VkBestPracticesLayerTest, TestDestroyFreeNullHandles) {
403     VkResult err;
404 
405     TEST_DESCRIPTION("Call all applicable destroy and free routines with NULL handles, expecting no validation errors");
406 
407     InitBestPracticesFramework();
408     InitState();
409 
410     ASSERT_NO_FATAL_FAILURE(InitViewport());
411     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
412 
413     m_errorMonitor->ExpectSuccess();
414 
415     vk::DestroyBuffer(m_device->device(), VK_NULL_HANDLE, NULL);
416     vk::DestroyBufferView(m_device->device(), VK_NULL_HANDLE, NULL);
417     vk::DestroyCommandPool(m_device->device(), VK_NULL_HANDLE, NULL);
418     vk::DestroyDescriptorPool(m_device->device(), VK_NULL_HANDLE, NULL);
419     vk::DestroyDescriptorSetLayout(m_device->device(), VK_NULL_HANDLE, NULL);
420     vk::DestroyDevice(VK_NULL_HANDLE, NULL);
421     vk::DestroyEvent(m_device->device(), VK_NULL_HANDLE, NULL);
422     vk::DestroyFence(m_device->device(), VK_NULL_HANDLE, NULL);
423     vk::DestroyFramebuffer(m_device->device(), VK_NULL_HANDLE, NULL);
424     vk::DestroyImage(m_device->device(), VK_NULL_HANDLE, NULL);
425     vk::DestroyImageView(m_device->device(), VK_NULL_HANDLE, NULL);
426     vk::DestroyInstance(VK_NULL_HANDLE, NULL);
427     vk::DestroyPipeline(m_device->device(), VK_NULL_HANDLE, NULL);
428     vk::DestroyPipelineCache(m_device->device(), VK_NULL_HANDLE, NULL);
429     vk::DestroyPipelineLayout(m_device->device(), VK_NULL_HANDLE, NULL);
430     vk::DestroyQueryPool(m_device->device(), VK_NULL_HANDLE, NULL);
431     vk::DestroyRenderPass(m_device->device(), VK_NULL_HANDLE, NULL);
432     vk::DestroySampler(m_device->device(), VK_NULL_HANDLE, NULL);
433     vk::DestroySemaphore(m_device->device(), VK_NULL_HANDLE, NULL);
434     vk::DestroyShaderModule(m_device->device(), VK_NULL_HANDLE, NULL);
435 
436     VkCommandPool command_pool;
437     VkCommandPoolCreateInfo pool_create_info{};
438     pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
439     pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
440     pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
441     vk::CreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool);
442     VkCommandBuffer command_buffers[3] = {};
443     VkCommandBufferAllocateInfo command_buffer_allocate_info{};
444     command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
445     command_buffer_allocate_info.commandPool = command_pool;
446     command_buffer_allocate_info.commandBufferCount = 1;
447     command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
448     vk::AllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &command_buffers[1]);
449     vk::FreeCommandBuffers(m_device->device(), command_pool, 3, command_buffers);
450     vk::DestroyCommandPool(m_device->device(), command_pool, NULL);
451 
452     VkDescriptorPoolSize ds_type_count = {};
453     ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
454     ds_type_count.descriptorCount = 1;
455 
456     VkDescriptorPoolCreateInfo ds_pool_ci = {};
457     ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
458     ds_pool_ci.pNext = NULL;
459     ds_pool_ci.maxSets = 1;
460     ds_pool_ci.poolSizeCount = 1;
461     ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
462     ds_pool_ci.pPoolSizes = &ds_type_count;
463 
464     VkDescriptorPool ds_pool;
465     err = vk::CreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
466     ASSERT_VK_SUCCESS(err);
467 
468     VkDescriptorSetLayoutBinding dsl_binding = {};
469     dsl_binding.binding = 2;
470     dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
471     dsl_binding.descriptorCount = 1;
472     dsl_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
473     dsl_binding.pImmutableSamplers = NULL;
474 
475     const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding});
476 
477     VkDescriptorSet descriptor_sets[3] = {};
478     VkDescriptorSetAllocateInfo alloc_info = {};
479     alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
480     alloc_info.descriptorSetCount = 1;
481     alloc_info.descriptorPool = ds_pool;
482     alloc_info.pSetLayouts = &ds_layout.handle();
483     err = vk::AllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_sets[1]);
484     ASSERT_VK_SUCCESS(err);
485     vk::FreeDescriptorSets(m_device->device(), ds_pool, 3, descriptor_sets);
486     vk::DestroyDescriptorPool(m_device->device(), ds_pool, NULL);
487 
488     vk::FreeMemory(m_device->device(), VK_NULL_HANDLE, NULL);
489 
490     m_errorMonitor->VerifyNotFound();
491 }
492 
TEST_F(VkBestPracticesLayerTest,CommandBufferReset)493 TEST_F(VkBestPracticesLayerTest, CommandBufferReset) {
494     TEST_DESCRIPTION("Test for validating usage of vkCreateCommandPool with COMMAND_BUFFER_RESET_BIT");
495 
496     InitBestPracticesFramework();
497     InitState();
498 
499     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
500                                          "UNASSIGNED-BestPractices-vkCreateCommandPool-command-buffer-reset");
501 
502     VkCommandPool command_pool;
503     VkCommandPoolCreateInfo pool_create_info{};
504     pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
505     pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
506     pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
507     vk::CreateCommandPool(m_device->device(), &pool_create_info, nullptr, &command_pool);
508 
509     m_errorMonitor->VerifyFound();
510 }
511 
TEST_F(VkBestPracticesLayerTest,SimultaneousUse)512 TEST_F(VkBestPracticesLayerTest, SimultaneousUse) {
513     TEST_DESCRIPTION("Test for validating usage of vkBeginCommandBuffer with SIMULTANEOUS_USE");
514 
515     InitBestPracticesFramework();
516     InitState();
517 
518     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-vkBeginCommandBuffer-simultaneous-use");
519 
520     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkBeginCommandBuffer-one-time-submit");
521 
522     VkCommandBufferBeginInfo cmd_begin_info{};
523     cmd_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
524     cmd_begin_info.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
525     vk::BeginCommandBuffer(m_commandBuffer->handle(), &cmd_begin_info);
526 
527     m_errorMonitor->VerifyFound();
528 }
529 
TEST_F(VkBestPracticesLayerTest,SmallAllocation)530 TEST_F(VkBestPracticesLayerTest, SmallAllocation) {
531     TEST_DESCRIPTION("Test for small memory allocations");
532 
533     InitBestPracticesFramework();
534     InitState();
535 
536     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-vkAllocateMemory-small-allocation");
537 
538     // Find appropriate memory type for given reqs
539     VkMemoryPropertyFlags mem_props = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
540     VkPhysicalDeviceMemoryProperties dev_mem_props = m_device->phy().memory_properties();
541 
542     uint32_t mem_type_index = 0;
543     for (mem_type_index = 0; mem_type_index < dev_mem_props.memoryTypeCount; ++mem_type_index) {
544         if (mem_props == (mem_props & dev_mem_props.memoryTypes[mem_type_index].propertyFlags)) break;
545     }
546     EXPECT_LT(mem_type_index, dev_mem_props.memoryTypeCount) << "Could not find a suitable memory type.";
547 
548     const uint32_t kSmallAllocationSize = 1024;
549 
550     VkMemoryAllocateInfo alloc_info{};
551     alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
552     alloc_info.allocationSize = kSmallAllocationSize;
553     alloc_info.memoryTypeIndex = mem_type_index;
554 
555     VkDeviceMemory memory;
556     vk::AllocateMemory(m_device->device(), &alloc_info, nullptr, &memory);
557 
558     m_errorMonitor->VerifyFound();
559 }
560 
TEST_F(VkBestPracticesLayerTest,SmallDedicatedAllocation)561 TEST_F(VkBestPracticesLayerTest, SmallDedicatedAllocation) {
562     TEST_DESCRIPTION("Test for small dedicated memory allocations");
563 
564     InitBestPracticesFramework();
565     InitState();
566 
567     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
568                                          "UNASSIGNED-BestPractices-vkBindMemory-small-dedicated-allocation");
569 
570     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkAllocateMemory-small-allocation");
571 
572     VkImageCreateInfo image_info{};
573     image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
574     image_info.extent = {64, 64, 1};
575     image_info.format = VK_FORMAT_R8G8B8A8_UNORM;
576     image_info.imageType = VK_IMAGE_TYPE_2D;
577     image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
578     image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
579     image_info.samples = VK_SAMPLE_COUNT_1_BIT;
580     image_info.arrayLayers = 1;
581     image_info.mipLevels = 1;
582 
583     // Create a small image with a dedicated allocation
584     VkImageObj image(m_device);
585     image.init_no_mem(*m_device, image_info);
586 
587     vk_testing::DeviceMemory mem;
588     mem.init(*m_device, vk_testing::DeviceMemory::get_resource_alloc_info(*m_device, image.memory_requirements(),
589                                                                           VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
590     vk::BindImageMemory(device(), image.handle(), mem.handle(), 0);
591 
592     m_errorMonitor->VerifyFound();
593 }
594 
TEST_F(VkBestPracticesLayerTest,MSImageRequiresMemory)595 TEST_F(VkBestPracticesLayerTest, MSImageRequiresMemory) {
596     TEST_DESCRIPTION("Test for MS image that requires memory");
597 
598     InitBestPracticesFramework();
599     InitState();
600 
601     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
602                                          "UNASSIGNED-BestPractices-vkCreateRenderPass-image-requires-memory");
603 
604     VkAttachmentDescription attachment{};
605     attachment.samples = VK_SAMPLE_COUNT_4_BIT;
606     attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
607     attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
608 
609     VkRenderPassCreateInfo rp_info{};
610     rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
611     rp_info.attachmentCount = 1;
612     rp_info.pAttachments = &attachment;
613 
614     VkRenderPass rp;
615     vk::CreateRenderPass(m_device->device(), &rp_info, nullptr, &rp);
616 
617     m_errorMonitor->VerifyFound();
618 }
619 
TEST_F(VkBestPracticesLayerTest,AttachmentShouldNotBeTransient)620 TEST_F(VkBestPracticesLayerTest, AttachmentShouldNotBeTransient) {
621     TEST_DESCRIPTION("Test for non-lazy multisampled images");
622 
623     InitBestPracticesFramework();
624     InitState();
625 
626     if (IsPlatform(kPixel2XL) || IsPlatform(kPixel3) || IsPlatform(kPixel3aXL) || IsPlatform(kShieldTV) || IsPlatform(kShieldTVb) ||
627         IsPlatform(kNexusPlayer)) {
628         printf("%s This test seems super-picky on Android platforms\n", kSkipPrefix);
629         return;
630     }
631 
632     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
633                                          "UNASSIGNED-BestPractices-vkCreateFramebuffer-attachment-should-not-be-transient");
634 
635     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkAllocateMemory-small-allocation");
636     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkBindMemory-small-dedicated-allocation");
637     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkBindImageMemory-non-lazy-transient-image");
638     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-VkCommandBuffer-AvoidTinyCmdBuffers");
639     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkImage-AvoidGeneral");
640 
641     VkAttachmentDescription attachment{};
642     attachment.samples = VK_SAMPLE_COUNT_1_BIT;
643     attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
644     attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
645 
646     VkRenderPassCreateInfo rp_info{};
647     rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
648     rp_info.attachmentCount = 1;
649     rp_info.pAttachments = &attachment;
650 
651     VkRenderPass rp = VK_NULL_HANDLE;
652     vk::CreateRenderPass(m_device->device(), &rp_info, nullptr, &rp);
653 
654     VkImageCreateInfo image_info{};
655     image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
656     image_info.extent = {1920, 1080, 1};
657     image_info.format = VK_FORMAT_R8G8B8A8_UNORM;
658     image_info.imageType = VK_IMAGE_TYPE_2D;
659     image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
660     image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
661     image_info.samples = VK_SAMPLE_COUNT_1_BIT;
662     image_info.arrayLayers = 1;
663     image_info.mipLevels = 1;
664 
665     VkImageObj image(m_device);
666     image.init(&image_info);
667 
668     VkImageViewCreateInfo iv_info{};
669     iv_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
670     iv_info.format = VK_FORMAT_R8G8B8A8_UNORM;
671     iv_info.image = image.handle();
672     iv_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
673     iv_info.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
674     iv_info.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
675 
676     VkImageView image_view = VK_NULL_HANDLE;
677     vk::CreateImageView(m_device->device(), &iv_info, nullptr, &image_view);
678 
679     VkFramebufferCreateInfo fb_info{};
680     fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
681     fb_info.renderPass = rp;
682     fb_info.layers = 1;
683     fb_info.width = 1920;
684     fb_info.height = 1080;
685     fb_info.attachmentCount = 1;
686     fb_info.pAttachments = &image_view;
687 
688     VkFramebuffer fb = VK_NULL_HANDLE;
689     vk::CreateFramebuffer(m_device->device(), &fb_info, nullptr, &fb);
690 
691     m_errorMonitor->VerifyFound();
692     vk::DestroyImageView(m_device->device(), image_view, nullptr);
693     vk::DestroyFramebuffer(m_device->device(), fb, nullptr);
694     vk::DestroyRenderPass(m_device->device(), rp, nullptr);
695 }
696 
TEST_F(VkBestPracticesLayerTest,TooManyInstancedVertexBuffers)697 TEST_F(VkBestPracticesLayerTest, TooManyInstancedVertexBuffers) {
698     TEST_DESCRIPTION("Test for too many instanced vertex buffers");
699 
700     InitBestPracticesFramework();
701     InitState();
702 
703     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
704                                          "UNASSIGNED-BestPractices-vkCreateGraphicsPipelines-too-many-instanced-vertex-buffers");
705 
706     // This test may also trigger the small allocation warnings
707     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkAllocateMemory-small-allocation");
708     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkBindMemory-small-dedicated-allocation");
709     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-VkCommandBuffer-AvoidTinyCmdBuffers");
710 
711     ASSERT_NO_FATAL_FAILURE(InitViewport());
712     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
713 
714     std::vector<VkVertexInputBindingDescription> bindings(2, VkVertexInputBindingDescription{});
715     std::vector<VkVertexInputAttributeDescription> attributes(2, VkVertexInputAttributeDescription{});
716 
717     bindings[0].binding = 0;
718     bindings[0].stride = 4;
719     bindings[0].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
720 
721     attributes[0].binding = 0;
722 
723     bindings[1].binding = 1;
724     bindings[1].stride = 8;
725     bindings[1].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
726 
727     attributes[1].binding = 1;
728 
729     VkPipelineVertexInputStateCreateInfo vi_state_ci{};
730     vi_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
731     vi_state_ci.vertexBindingDescriptionCount = static_cast<uint32_t>(bindings.size());
732     vi_state_ci.pVertexBindingDescriptions = bindings.data();
733     vi_state_ci.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributes.size());
734     vi_state_ci.pVertexAttributeDescriptions = attributes.data();
735 
736     CreatePipelineHelper pipe(*this);
737     pipe.InitInfo();
738     pipe.vi_ci_ = vi_state_ci;
739     pipe.InitState();
740     pipe.CreateGraphicsPipeline();
741 
742     m_errorMonitor->VerifyFound();
743 }
744 
TEST_F(VkBestPracticesLayerTest,ClearAttachmentsAfterLoad)745 TEST_F(VkBestPracticesLayerTest, ClearAttachmentsAfterLoad) {
746     TEST_DESCRIPTION("Test for clearing attachments after load");
747 
748     InitBestPracticesFramework();
749     InitState();
750 
751     m_clear_via_load_op = false;  // Force LOAD_OP_LOAD
752     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
753 
754     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-vkCmdClearAttachments-clear-after-load");
755 
756     // On tiled renderers, this can also trigger a warning about LOAD_OP_LOAD causing a readback
757     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkCmdBeginRenderPass-attachment-needs-readback");
758     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-DrawState-ClearCmdBeforeDraw");
759     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-RenderPass-redundant-store");
760     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-RenderPass-redundant-clear");
761     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-RenderPass-inefficient-clear");
762 
763     m_commandBuffer->begin();
764     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
765 
766     VkClearAttachment color_attachment;
767     color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
768     color_attachment.clearValue.color.float32[0] = 1.0;
769     color_attachment.clearValue.color.float32[1] = 1.0;
770     color_attachment.clearValue.color.float32[2] = 1.0;
771     color_attachment.clearValue.color.float32[3] = 1.0;
772     color_attachment.colorAttachment = 0;
773     VkClearRect clear_rect = {{{0, 0}, {(uint32_t)m_width, (uint32_t)m_height}}, 0, 1};
774 
775     vk::CmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
776 
777     m_errorMonitor->VerifyFound();
778 }
779 
TEST_F(VkBestPracticesLayerTest,ClearAttachmentsAfterLoadSecondary)780 TEST_F(VkBestPracticesLayerTest, ClearAttachmentsAfterLoadSecondary) {
781     TEST_DESCRIPTION("Test for clearing attachments after load with secondary command buffers");
782 
783     InitBestPracticesFramework();
784     InitState();
785 
786     if (IsPlatform(PlatformType::kShieldTV) || IsPlatform(PlatformType::kShieldTVb)) {
787         printf("%s Test CmdClearAttachmentAfterLoadSecondary is unstable on ShieldTV, skipping test.\n", kSkipPrefix);
788         return;
789     }
790 
791     m_clear_via_load_op = false;  // Force LOAD_OP_LOAD
792     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
793 
794     // On tiled renderers, this can also trigger a warning about LOAD_OP_LOAD causing a readback
795     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-vkCmdBeginRenderPass-attachment-needs-readback");
796     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-RenderPass-redundant-store");
797     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-RenderPass-redundant-clear");
798     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-RenderPass-inefficient-clear");
799 
800     CreatePipelineHelper pipe_masked(*this);
801     pipe_masked.InitInfo();
802     pipe_masked.InitState();
803     pipe_masked.cb_attachments_.colorWriteMask = 0;
804     pipe_masked.CreateGraphicsPipeline();
805 
806     CreatePipelineHelper pipe_writes(*this);
807     pipe_writes.InitInfo();
808     pipe_writes.InitState();
809     pipe_writes.cb_attachments_.colorWriteMask = 0xf;
810     pipe_writes.CreateGraphicsPipeline();
811 
812     m_commandBuffer->begin();
813 
814     VkClearAttachment color_attachment;
815     color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
816     color_attachment.clearValue.color.float32[0] = 1.0;
817     color_attachment.clearValue.color.float32[1] = 1.0;
818     color_attachment.clearValue.color.float32[2] = 1.0;
819     color_attachment.clearValue.color.float32[3] = 1.0;
820     color_attachment.colorAttachment = 0;
821     VkClearRect clear_rect = {{{0, 0}, {(uint32_t)m_width, (uint32_t)m_height}}, 0, 1};
822 
823     // Plain clear after load.
824     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
825     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-vkCmdClearAttachments-clear-after-load");
826     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-DrawState-ClearCmdBeforeDraw");
827     {
828         vk::CmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
829         m_errorMonitor->VerifyFound();
830     }
831     m_commandBuffer->EndRenderPass();
832 
833     // Test that a masked write is ignored before clear
834     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
835     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-vkCmdClearAttachments-clear-after-load");
836     {
837         vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_masked.pipeline_);
838         m_commandBuffer->Draw(1, 0, 0, 0);
839         vk::CmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
840         m_errorMonitor->VerifyFound();
841     }
842     m_commandBuffer->EndRenderPass();
843 
844     // Test that an actual write will not trigger the clear warning
845     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
846     {
847         vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_writes.pipeline_);
848         m_commandBuffer->Draw(1, 0, 0, 0);
849         vk::CmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
850         m_errorMonitor->VerifyNotFound();
851     }
852     m_commandBuffer->EndRenderPass();
853 
854     // Try the same thing, but now with secondary command buffers.
855     VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
856     begin_info.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT |
857                        VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
858     VkCommandBufferInheritanceInfo inherit_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO };
859     begin_info.pInheritanceInfo = &inherit_info;
860     inherit_info.subpass = 0;
861     inherit_info.renderPass = m_renderPassBeginInfo.renderPass;
862 
863     VkCommandBufferObj secondary_clear(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
864     VkCommandBufferObj secondary_draw_masked(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
865     VkCommandBufferObj secondary_draw_write(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
866 
867     secondary_clear.begin(&begin_info);
868     secondary_draw_masked.begin(&begin_info);
869     secondary_draw_write.begin(&begin_info);
870 
871     vk::CmdClearAttachments(secondary_clear.handle(), 1, &color_attachment, 1, &clear_rect);
872 
873     vk::CmdBindPipeline(secondary_draw_masked.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_masked.pipeline_);
874     secondary_draw_masked.Draw(1, 0, 0, 0);
875 
876     vk::CmdBindPipeline(secondary_draw_write.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_writes.pipeline_);
877     secondary_draw_write.Draw(1, 0, 0, 0);
878 
879     secondary_clear.end();
880     secondary_draw_masked.end();
881     secondary_draw_write.end();
882 
883     // Plain clear after load.
884     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
885     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-vkCmdClearAttachments-clear-after-load");
886     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-DrawState-ClearCmdBeforeDraw");
887     {
888         vk::CmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary_clear.handle());
889         m_errorMonitor->VerifyFound();
890     }
891     m_commandBuffer->EndRenderPass();
892 
893     // Test that a masked write is ignored before clear
894     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
895     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, "UNASSIGNED-BestPractices-vkCmdClearAttachments-clear-after-load");
896     {
897         vk::CmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary_draw_masked.handle());
898         vk::CmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary_clear.handle());
899         m_errorMonitor->VerifyFound();
900     }
901     m_commandBuffer->EndRenderPass();
902 
903     // Test that an actual write will not trigger the clear warning
904     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
905     {
906         vk::CmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary_draw_write.handle());
907         vk::CmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary_clear.handle());
908         m_errorMonitor->VerifyNotFound();
909     }
910     m_commandBuffer->EndRenderPass();
911 }
912 
TEST_F(VkBestPracticesLayerTest,TripleBufferingTest)913 TEST_F(VkBestPracticesLayerTest, TripleBufferingTest) {
914     TEST_DESCRIPTION("Test for usage of triple buffering");
915 
916     AddSurfaceInstanceExtension();
917     InitBestPracticesFramework();
918     AddSwapchainDeviceExtension();
919     InitState();
920     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
921                                          "UNASSIGNED-BestPractices-vkCreateSwapchainKHR-suboptimal-swapchain-image-count");
922     if (!InitSurface()) {
923         printf("%s Cannot create surface, skipping test\n", kSkipPrefix);
924         return;
925     }
926     InitSwapchainInfo();
927 
928     VkBool32 supported;
929     vk::GetPhysicalDeviceSurfaceSupportKHR(gpu(), m_device->graphics_queue_node_index_, m_surface, &supported);
930     if (!supported) {
931         printf("%s Graphics queue does not support present, skipping test\n", kSkipPrefix);
932         return;
933     }
934 
935     VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
936     VkSurfaceTransformFlagBitsKHR preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
937 
938     VkSwapchainCreateInfoKHR swapchain_create_info = {};
939     swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
940     swapchain_create_info.pNext = 0;
941     swapchain_create_info.surface = m_surface;
942     swapchain_create_info.minImageCount = 2;
943     swapchain_create_info.imageFormat = m_surface_formats[0].format;
944     swapchain_create_info.imageColorSpace = m_surface_formats[0].colorSpace;
945     swapchain_create_info.imageExtent = {m_surface_capabilities.minImageExtent.width, m_surface_capabilities.minImageExtent.height};
946     swapchain_create_info.imageArrayLayers = 1;
947     swapchain_create_info.imageUsage = imageUsage;
948     swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
949     swapchain_create_info.preTransform = preTransform;
950     swapchain_create_info.compositeAlpha = m_surface_composite_alpha;
951     swapchain_create_info.presentMode = m_surface_non_shared_present_mode;
952     swapchain_create_info.clipped = VK_FALSE;
953     swapchain_create_info.oldSwapchain = 0;
954 
955     VkResult err = vk::CreateSwapchainKHR(device(), &swapchain_create_info, nullptr, &m_swapchain);
956     m_errorMonitor->VerifyFound();
957 
958     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
959                                          "UNASSIGNED-BestPractices-vkCreateSwapchainKHR-suboptimal-swapchain-image-count");
960     swapchain_create_info.minImageCount = 3;
961     err = vk::CreateSwapchainKHR(device(), &swapchain_create_info, nullptr, &m_swapchain);
962     m_errorMonitor->VerifyNotFound();
963     ASSERT_VK_SUCCESS(err)
964     DestroySwapchain();
965 }
966 
TEST_F(VkBestPracticesLayerTest,SwapchainCreationTest)967 TEST_F(VkBestPracticesLayerTest, SwapchainCreationTest) {
968     TEST_DESCRIPTION("Test for correct swapchain creation");
969 
970     AddSurfaceInstanceExtension();
971     InitBestPracticesFramework();
972     AddSwapchainDeviceExtension();
973     InitState();
974     if (!InitSurface()) {
975         printf("%s Cannot create surface, skipping test\n", kSkipPrefix);
976         return;
977     }
978 
979     // GetPhysicalDeviceSurfaceCapabilitiesKHR() not called before trying to create a swapchain
980     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-BestPractices-vkCreateSwapchainKHR-surface-not-retrieved");
981 
982     // GetPhysicalDeviceSurfaceFormatsKHR() not called before trying to create a swapchain
983     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-BestPractices-vkCreateSwapchainKHR-surface-not-retrieved");
984 
985     // GetPhysicalDeviceSurfacePresentModesKHR() not called before trying to create a swapchain
986     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-BestPractices-vkCreateSwapchainKHR-surface-not-retrieved");
987 
988 #ifdef VK_USE_PLATFORM_ANDROID_KHR
989     m_surface_composite_alpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
990 #else
991     m_surface_composite_alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
992 #endif
993 
994     VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
995     VkSurfaceTransformFlagBitsKHR preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
996 
997     VkSwapchainCreateInfoKHR swapchain_create_info = {};
998     swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
999     swapchain_create_info.pNext = 0;
1000     swapchain_create_info.surface = m_surface;
1001     swapchain_create_info.minImageCount = 3;
1002     swapchain_create_info.imageArrayLayers = 1;
1003     swapchain_create_info.imageUsage = imageUsage;
1004     swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
1005     swapchain_create_info.preTransform = preTransform;
1006     swapchain_create_info.compositeAlpha = m_surface_composite_alpha;
1007     swapchain_create_info.presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
1008     swapchain_create_info.clipped = VK_FALSE;
1009     swapchain_create_info.oldSwapchain = 0;
1010 
1011     // Set unexpected error because warning is thrown any time the present mode is not VK_PRESENT_MODE_FIFO_KHR
1012     m_errorMonitor->SetUnexpectedError("UNASSIGNED-BestPractices-vkCreateSwapchainKHR-swapchain-presentmode-not-fifo");
1013 
1014     VkResult err = vk::CreateSwapchainKHR(device(), &swapchain_create_info, nullptr, &m_swapchain);
1015     ASSERT_TRUE(err == VK_ERROR_VALIDATION_FAILED_EXT);
1016     m_errorMonitor->VerifyFound();
1017 
1018     // Test for successful swapchain creation when GetPhysicalDeviceSurfaceCapabilitiesKHR() and
1019     // GetPhysicalDeviceSurfaceFormatsKHR() are queried as expected and GetPhysicalDeviceSurfacePresentModesKHR() is not called but
1020     // the present mode is VK_PRESENT_MODE_FIFO_KHR
1021     vk::GetPhysicalDeviceSurfaceCapabilitiesKHR(gpu(), m_surface, &m_surface_capabilities);
1022 
1023     uint32_t format_count;
1024     vk::GetPhysicalDeviceSurfaceFormatsKHR(gpu(), m_surface, &format_count, nullptr);
1025     if (format_count != 0) {
1026         m_surface_formats.resize(format_count);
1027         vk::GetPhysicalDeviceSurfaceFormatsKHR(gpu(), m_surface, &format_count, m_surface_formats.data());
1028     }
1029 
1030     swapchain_create_info.imageFormat = m_surface_formats[0].format;
1031     swapchain_create_info.imageColorSpace = m_surface_formats[0].colorSpace;
1032     swapchain_create_info.imageExtent = {m_surface_capabilities.minImageExtent.width, m_surface_capabilities.minImageExtent.height};
1033     swapchain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
1034 
1035     m_errorMonitor->ExpectSuccess(kWarningBit);
1036     err = vk::CreateSwapchainKHR(device(), &swapchain_create_info, nullptr, &m_swapchain);
1037     m_errorMonitor->VerifyNotFound();
1038 
1039     DestroySwapchain();
1040 }
1041 
TEST_F(VkBestPracticesLayerTest,ExpectedQueryDetails)1042 TEST_F(VkBestPracticesLayerTest, ExpectedQueryDetails) {
1043     TEST_DESCRIPTION("Check that GetPhysicalDeviceQueueFamilyProperties is working as expected");
1044 
1045     // Vulkan 1.1 required to test vkGetPhysicalDeviceQueueFamilyProperties2
1046     app_info_.apiVersion = VK_API_VERSION_1_1;
1047     // VK_KHR_get_physical_device_properties2 required to test vkGetPhysicalDeviceQueueFamilyProperties2KHR
1048     instance_extensions_.emplace_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1049     ASSERT_NO_FATAL_FAILURE(InitBestPracticesFramework());
1050     const vk_testing::PhysicalDevice phys_device_obj(gpu_);
1051 
1052     std::vector<VkQueueFamilyProperties> queue_family_props;
1053 
1054     m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit);
1055 
1056     // Ensure we can find a graphics queue family.
1057     uint32_t queue_count = 0;
1058     vk::GetPhysicalDeviceQueueFamilyProperties(phys_device_obj.handle(), &queue_count, nullptr);
1059 
1060     queue_family_props.resize(queue_count);
1061     vk::GetPhysicalDeviceQueueFamilyProperties(phys_device_obj.handle(), &queue_count, queue_family_props.data());
1062 
1063     // Now  for GetPhysicalDeviceQueueFamilyProperties2
1064     std::vector<VkQueueFamilyProperties2> queue_family_props2;
1065     vk::GetPhysicalDeviceQueueFamilyProperties2(phys_device_obj.handle(), &queue_count, nullptr);
1066 
1067     queue_family_props2.resize(queue_count);
1068     vk::GetPhysicalDeviceQueueFamilyProperties2(phys_device_obj.handle(), &queue_count, queue_family_props2.data());
1069 
1070     // And for GetPhysicalDeviceQueueFamilyProperties2KHR
1071     PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR =
1072         reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR>(
1073             vk::GetInstanceProcAddr(instance(), "vkGetPhysicalDeviceQueueFamilyProperties2KHR"));
1074     if (vkGetPhysicalDeviceQueueFamilyProperties2KHR) {
1075         vkGetPhysicalDeviceQueueFamilyProperties2KHR(phys_device_obj.handle(), &queue_count, nullptr);
1076 
1077         queue_family_props2.resize(queue_count);
1078         vkGetPhysicalDeviceQueueFamilyProperties2KHR(phys_device_obj.handle(), &queue_count, queue_family_props2.data());
1079     }
1080 
1081     vk_testing::Device device(phys_device_obj.handle());
1082     device.init();
1083 }
1084 
TEST_F(VkBestPracticesLayerTest,MissingQueryDetails)1085 TEST_F(VkBestPracticesLayerTest, MissingQueryDetails) {
1086     TEST_DESCRIPTION("Check that GetPhysicalDeviceQueueFamilyProperties generates appropriate query warning");
1087 
1088     ASSERT_NO_FATAL_FAILURE(InitBestPracticesFramework());
1089     const vk_testing::PhysicalDevice phys_device_obj(gpu_);
1090 
1091     std::vector<VkQueueFamilyProperties> queue_family_props(1);
1092     uint32_t queue_count = static_cast<uint32_t>(queue_family_props.size());
1093 
1094     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, "UNASSIGNED-CoreValidation-DevLimit-MissingQueryCount");
1095     vk::GetPhysicalDeviceQueueFamilyProperties(phys_device_obj.handle(), &queue_count, queue_family_props.data());
1096     m_errorMonitor->VerifyFound();
1097 
1098     // Now get information correctly
1099     m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit);
1100     vk_testing::QueueCreateInfoArray queue_info(phys_device_obj.queue_properties());
1101     // Only request creation with queuefamilies that have at least one queue
1102     std::vector<VkDeviceQueueCreateInfo> create_queue_infos;
1103     auto qci = queue_info.data();
1104     for (uint32_t j = 0; j < queue_info.size(); ++j) {
1105         if (qci[j].queueCount) {
1106             create_queue_infos.push_back(qci[j]);
1107         }
1108     }
1109     m_errorMonitor->VerifyNotFound();
1110 
1111     VkPhysicalDeviceFeatures all_features;
1112     VkDeviceCreateInfo device_ci = {};
1113     device_ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
1114     device_ci.pNext = nullptr;
1115     device_ci.queueCreateInfoCount = create_queue_infos.size();
1116     device_ci.pQueueCreateInfos = create_queue_infos.data();
1117     device_ci.enabledLayerCount = 0;
1118     device_ci.ppEnabledLayerNames = NULL;
1119     device_ci.enabledExtensionCount = 0;
1120     device_ci.ppEnabledExtensionNames = nullptr;
1121     device_ci.pEnabledFeatures = &all_features;
1122 
1123     // vkGetPhysicalDeviceFeatures has not been called, so this should produce a warning
1124     m_errorMonitor->SetDesiredFailureMsg(kWarningBit,
1125                                          "UNASSIGNED-BestPractices-vkCreateDevice-physical-device-features-not-retrieved");
1126     VkDevice device;
1127     vk::CreateDevice(phys_device_obj.handle(), &device_ci, nullptr, &device);
1128     m_errorMonitor->VerifyFound();
1129 }
1130 
TEST_F(VkBestPracticesLayerTest,GetSwapchainImagesInvalidCount)1131 TEST_F(VkBestPracticesLayerTest, GetSwapchainImagesInvalidCount) {
1132     TEST_DESCRIPTION("Pass an 'incorrect' count to the second GetSwapchainImagesKHR call");
1133 
1134     if (!AddSurfaceInstanceExtension()) {
1135         printf("%s surface extensions not supported, skipping test\n", kSkipPrefix);
1136         return;
1137     }
1138 
1139     ASSERT_NO_FATAL_FAILURE(InitBestPracticesFramework());
1140 
1141     if (!AddSwapchainDeviceExtension()) {
1142         printf("%s swapchain extensions not supported, skipping test\n", kSkipPrefix);
1143         return;
1144     }
1145     ASSERT_NO_FATAL_FAILURE(InitState());
1146     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1147     if (!InitSwapchain()) {
1148         printf("%s Cannot create surface or swapchain, skipping test\n", kSkipPrefix);
1149         return;
1150     }
1151 
1152     uint32_t swapchain_images_count = 0;
1153     vk::GetSwapchainImagesKHR(device(), m_swapchain, &swapchain_images_count, nullptr);
1154 
1155     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, kVUID_BestPractices_Swapchain_InvalidCount);
1156     ++swapchain_images_count;  // Set the image count to something greater (i.e., "invalid") than what was returned
1157     std::vector<VkImage> swapchain_images(swapchain_images_count, VK_NULL_HANDLE);
1158     vk::GetSwapchainImagesKHR(device(), m_swapchain, &swapchain_images_count, swapchain_images.data());
1159     m_errorMonitor->VerifyFound();
1160 }
1161 
TEST_F(VkBestPracticesLayerTest,DepthBiasNoAttachment)1162 TEST_F(VkBestPracticesLayerTest, DepthBiasNoAttachment) {
1163     TEST_DESCRIPTION("Enable depthBias without a depth attachment");
1164 
1165     InitBestPracticesFramework();
1166     InitState();
1167     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1168 
1169     CreatePipelineHelper pipe(*this);
1170     pipe.InitInfo();
1171     pipe.rs_state_ci_.depthBiasEnable = VK_TRUE;
1172     pipe.rs_state_ci_.depthBiasConstantFactor = 1.0f;
1173     pipe.InitState();
1174     pipe.CreateGraphicsPipeline();
1175 
1176     m_commandBuffer->begin();
1177     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
1178     vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
1179 
1180     m_errorMonitor->SetDesiredFailureMsg(kWarningBit, kVUID_BestPractices_DepthBiasNoAttachment);
1181     vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
1182     m_errorMonitor->VerifyFound();
1183 
1184     m_commandBuffer->end();
1185 }
1186 
TEST_F(VkBestPracticesLayerTest,CreatePipelineVsFsTypeMismatchArraySize)1187 TEST_F(VkBestPracticesLayerTest, CreatePipelineVsFsTypeMismatchArraySize) {
1188     TEST_DESCRIPTION("Test that an error is produced for mismatched array sizes across the vertex->fragment shader interface");
1189 
1190     ASSERT_NO_FATAL_FAILURE(Init());
1191     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1192 
1193     char const *vsSource = R"glsl(
1194         #version 450
1195         layout(location=0) out float x[2];
1196         void main(){
1197            x[0] = 0; x[1] = 0;
1198            gl_Position = vec4(1);
1199         }
1200     )glsl";
1201     char const *fsSource = R"glsl(
1202         #version 450
1203         layout(location=0) in float x[1];
1204         layout(location=0) out vec4 color;
1205         void main(){
1206            color = vec4(x[0]);
1207         }
1208     )glsl";
1209 
1210     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
1211     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
1212 
1213     const auto set_info = [&](CreatePipelineHelper &helper) {
1214         helper.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
1215     };
1216     CreatePipelineHelper::OneshotTest(*this, set_info, kPerformanceWarningBit | kErrorBit,
1217                                       "UNASSIGNED-CoreValidation-Shader-OutputNotConsumed");
1218 }
1219