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