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  * Modifications Copyright (C) 2020-2021 Advanced Micro Devices, Inc. All rights reserved.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Author: Nathaniel Cesario <nathaniel@lunarg.com>
14  * Author: Nadav Geva <nadav.geva@amd.com>
15  */
16 
17 #include "cast_utils.h"
18 #include "layer_validation_tests.h"
19 
20 // Tests for AMD-specific best practices
21 const char *kEnableAMDValidation = "VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_AMD";
22 
23 
24 // this is a very long test (~10 minutes)
25 // disabled for now
26 #ifdef AMD_LONG_RUNNING_TEST
TEST_F(VkAmdBestPracticesLayerTest,TooManyPipelines)27 TEST_F(VkAmdBestPracticesLayerTest, TooManyPipelines) {
28 
29 
30     InitBestPracticesFramework(kEnableAMDValidation);
31     InitState();
32 
33     ASSERT_NO_FATAL_FAILURE(InitViewport());
34     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
35 
36     // create 1 more than the warning limit for pipeline objects
37     const uint32_t warn_limit = 5001;
38     VkPipeline pipeline_Array[warn_limit + 1] = {};
39 
40     for (int i = 0; i <= warn_limit; i++) {
41         // create a new pipeline helper so the cache won't be used
42         // also imitates a "just in time" pipeline creator pattern
43         if (i == 1) {
44             // check that the second pipeline helper cache was detected
45             m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
46                                                  "UNASSIGNED-BestPractices-vkCreatePipelines-multiple-pipelines-caches");
47         }
48         CreatePipelineHelper pipe(*this);
49         pipe.InitInfo();
50         pipe.InitState();
51         pipe.CreateGraphicsPipeline();
52         pipeline_Array[i] = pipe.pipeline_;
53         if (i == 1) {
54             // change check to too many pipelines
55             m_errorMonitor->VerifyFound();
56             m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
57                                                  "UNASSIGNED-BestPractices-CreatePipelines-TooManyPipelines");
58         }
59     }
60 
61     m_errorMonitor->VerifyFound();
62 }
63 #endif
64 
TEST_F(VkAmdBestPracticesLayerTest,UseMutableRT)65 TEST_F(VkAmdBestPracticesLayerTest, UseMutableRT) {
66     InitBestPracticesFramework(kEnableAMDValidation);
67     InitState();
68 
69     ASSERT_NO_FATAL_FAILURE(InitViewport());
70     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
71 
72     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
73                                          "UNASSIGNED-BestPractices-vkImage-DontUseMutableRenderTargets");
74 
75     // create a colot attachment image with mutable bit set
76     VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
77                                  nullptr,
78                                  VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
79                                  VK_IMAGE_TYPE_1D,
80                                  VK_FORMAT_R8G8B8A8_UNORM,
81                                  {1, 1, 1},
82                                  1,
83                                  1,
84                                  VK_SAMPLE_COUNT_1_BIT,
85                                  VK_IMAGE_TILING_OPTIMAL,
86                                  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
87                                  VK_SHARING_MODE_EXCLUSIVE,
88                                  0,
89                                  nullptr,
90                                  VK_IMAGE_LAYOUT_UNDEFINED};
91     VkImage test_image = VK_NULL_HANDLE;
92     vk::CreateImage(m_device->handle(), &img_info, nullptr, &test_image);
93     m_errorMonitor->VerifyFound();
94 
95     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
96                                          "UNASSIGNED-BestPractices-vkImage-DontUseMutableRenderTargets");
97     // create a depth attachment image with mutable bit set
98     img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
99                nullptr,
100                VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
101                VK_IMAGE_TYPE_1D,
102                VK_FORMAT_R8G8B8A8_UNORM,
103                {1, 1, 1},
104                1,
105                1,
106                VK_SAMPLE_COUNT_1_BIT,
107                VK_IMAGE_TILING_OPTIMAL,
108                VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
109                VK_SHARING_MODE_EXCLUSIVE,
110                0,
111                nullptr,
112                VK_IMAGE_LAYOUT_UNDEFINED};
113     test_image = VK_NULL_HANDLE;
114     vk::CreateImage(m_device->handle(), &img_info, nullptr, &test_image);
115     m_errorMonitor->VerifyFound();
116 
117     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
118                                          "UNASSIGNED-BestPractices-vkImage-DontUseMutableRenderTargets");
119     // create a storage image with mutable bit set
120     img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
121                nullptr,
122                VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
123                VK_IMAGE_TYPE_1D,
124                VK_FORMAT_R8G8B8A8_UNORM,
125                {1, 1, 1},
126                1,
127                1,
128                VK_SAMPLE_COUNT_1_BIT,
129                VK_IMAGE_TILING_OPTIMAL,
130                VK_IMAGE_USAGE_STORAGE_BIT,
131                VK_SHARING_MODE_EXCLUSIVE,
132                0,
133                nullptr,
134                VK_IMAGE_LAYOUT_UNDEFINED};
135     test_image = VK_NULL_HANDLE;
136     vk::CreateImage(m_device->handle(), &img_info, nullptr, &test_image);
137     m_errorMonitor->VerifyFound();
138 }
139 
TEST_F(VkAmdBestPracticesLayerTest,UsageConcurentRT)140 TEST_F(VkAmdBestPracticesLayerTest, UsageConcurentRT) {
141     InitBestPracticesFramework(kEnableAMDValidation);
142     InitState();
143 
144     ASSERT_NO_FATAL_FAILURE(InitViewport());
145     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
146 
147     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
148                                          "UNASSIGNED-BestPractices-vkImage-AvoidConcurrentRenderTargets");
149 
150     // create a render target image with mutable bit set
151     VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
152                                  nullptr,
153                                  0,
154                                  VK_IMAGE_TYPE_1D,
155                                  VK_FORMAT_R8G8B8A8_UNORM,
156                                  {1, 1, 1},
157                                  1,
158                                  1,
159                                  VK_SAMPLE_COUNT_1_BIT,
160                                  VK_IMAGE_TILING_OPTIMAL,
161                                  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
162                                  VK_SHARING_MODE_CONCURRENT,
163                                  0,
164                                  nullptr,
165                                  VK_IMAGE_LAYOUT_UNDEFINED};
166     VkImage test_image = VK_NULL_HANDLE;
167     vk::CreateImage(m_device->handle(), &img_info, nullptr, &test_image);
168     m_errorMonitor->VerifyFound();
169 
170     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
171                                          "UNASSIGNED-BestPractices-vkImage-AvoidConcurrentRenderTargets");
172     // create a render target image with mutable bit set
173     img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
174                nullptr,
175                0,
176                VK_IMAGE_TYPE_1D,
177                VK_FORMAT_R8G8B8A8_UNORM,
178                {1, 1, 1},
179                1,
180                1,
181                VK_SAMPLE_COUNT_1_BIT,
182                VK_IMAGE_TILING_OPTIMAL,
183                VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
184                VK_SHARING_MODE_CONCURRENT,
185                0,
186                nullptr,
187                VK_IMAGE_LAYOUT_UNDEFINED};
188     test_image = VK_NULL_HANDLE;
189     vk::CreateImage(m_device->handle(), &img_info, nullptr, &test_image);
190     m_errorMonitor->VerifyFound();
191 }
192 
TEST_F(VkAmdBestPracticesLayerTest,UsageStorageRT)193 TEST_F(VkAmdBestPracticesLayerTest, UsageStorageRT) {
194     InitBestPracticesFramework(kEnableAMDValidation);
195     InitState();
196 
197     ASSERT_NO_FATAL_FAILURE(InitViewport());
198     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
199 
200     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
201                                          "UNASSIGNED-BestPractices-vkImage-DontUseStorageRenderTargets");
202 
203     // create a render target image with mutable bit set
204     VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
205                                  nullptr,
206                                  0,
207                                  VK_IMAGE_TYPE_1D,
208                                  VK_FORMAT_R8G8B8A8_UNORM,
209                                  {1, 1, 1},
210                                  1,
211                                  1,
212                                  VK_SAMPLE_COUNT_1_BIT,
213                                  VK_IMAGE_TILING_OPTIMAL,
214                                  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
215                                  VK_SHARING_MODE_EXCLUSIVE,
216                                  0,
217                                  nullptr,
218                                  VK_IMAGE_LAYOUT_UNDEFINED};
219     VkImage test_image = VK_NULL_HANDLE;
220     vk::CreateImage(m_device->handle(), &img_info, nullptr, &test_image);
221     m_errorMonitor->VerifyFound();
222 }
223 
TEST_F(VkAmdBestPracticesLayerTest,PrimitiveRestart)224 TEST_F(VkAmdBestPracticesLayerTest, PrimitiveRestart) {
225     InitBestPracticesFramework(kEnableAMDValidation);
226     InitState();
227 
228     ASSERT_NO_FATAL_FAILURE(InitViewport());
229     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
230 
231     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
232                                          "UNASSIGNED-BestPractices-CreatePipelines-AvoidPrimitiveRestart");
233 
234     CreatePipelineHelper pipe(*this);
235     pipe.InitInfo();
236     pipe.InitState();
237     pipe.ia_ci_.primitiveRestartEnable = true;
238     pipe.CreateGraphicsPipeline();
239 
240     m_errorMonitor->VerifyFound();
241 }
242 
TEST_F(VkAmdBestPracticesLayerTest,NumDynamicStates)243 TEST_F(VkAmdBestPracticesLayerTest, NumDynamicStates) {
244     InitBestPracticesFramework(kEnableAMDValidation);
245     InitState();
246 
247     ASSERT_NO_FATAL_FAILURE(InitViewport());
248     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
249 
250     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
251                                          "UNASSIGNED-BestPractices-CreatePipelines-MinimizeNumDynamicStates");
252 
253     // fill the dynamic array with the first 8 types in the enum
254     // imitates a case where the user have set most dynamic states unnecessarily
255     VkDynamicState dynamic_states_array[8] = {};
256     for (uint32_t i = 0; i < 8; i++) {
257         dynamic_states_array[i] = (VkDynamicState)i;
258     }
259 
260     VkPipelineDynamicStateCreateInfo dynamic_state_info = {};
261     dynamic_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
262     dynamic_state_info.dynamicStateCount = 8;
263     dynamic_state_info.pDynamicStates = dynamic_states_array;
264 
265     CreatePipelineHelper pipe(*this);
266     pipe.InitInfo();
267     pipe.InitState();
268     pipe.dyn_state_ci_ = dynamic_state_info;
269     pipe.CreateGraphicsPipeline();
270 
271     m_errorMonitor->VerifyFound();
272 }
273 
TEST_F(VkAmdBestPracticesLayerTest,KeepLayoutSmall)274 TEST_F(VkAmdBestPracticesLayerTest, KeepLayoutSmall) {
275     // TODO: add dynamic buffer check as well
276     InitBestPracticesFramework(kEnableAMDValidation);
277     InitState();
278 
279     ASSERT_NO_FATAL_FAILURE(InitViewport());
280     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
281 
282     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
283                                          "UNASSIGNED-BestPractices-CreatePipelinesLayout-KeepLayoutSmall");
284 
285     // create a layout of 15 DWORDS (40 bytes push constants (10 DWORDS), a descriptor set (1 DWORD), and 2 dynamic buffers (4
286     // DWORDS)
287 
288     uint32_t push_size_dwords = 10;
289     VkPushConstantRange push_range = {};
290     push_range.stageFlags = VK_SHADER_STAGE_ALL;
291     push_range.offset = 0;
292     push_range.size = 4 * push_size_dwords;
293 
294     VkDescriptorSetLayoutBinding binding;
295     binding.binding = 0;
296     binding.descriptorCount = 2;
297     binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
298     binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
299 
300     VkDescriptorSetLayout DS_layout;
301 
302     VkDescriptorSetLayoutCreateInfo DS_layout_info = {};
303     DS_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
304     DS_layout_info.bindingCount = 1;
305     DS_layout_info.pBindings = &binding;
306 
307     vk::CreateDescriptorSetLayout(m_device->device(), &DS_layout_info, nullptr, &DS_layout);
308 
309     VkPipelineLayoutCreateInfo pipeline_layout_info = {};
310     pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
311     pipeline_layout_info.setLayoutCount = 1;
312     pipeline_layout_info.pSetLayouts = &DS_layout;
313     pipeline_layout_info.pushConstantRangeCount = 1;
314     pipeline_layout_info.pPushConstantRanges = &push_range;
315 
316     VkPipelineLayout test_pipeline_layout = VK_NULL_HANDLE;
317     vk::CreatePipelineLayout(m_device->handle(), &pipeline_layout_info, nullptr, &test_pipeline_layout);
318 
319     m_errorMonitor->VerifyFound();
320 }
321 
TEST_F(VkAmdBestPracticesLayerTest,CopyingDescriptors)322 TEST_F(VkAmdBestPracticesLayerTest, CopyingDescriptors) {
323     // TODO: add dynamic buffer check as well
324     InitBestPracticesFramework(kEnableAMDValidation);
325     InitState();
326 
327     ASSERT_NO_FATAL_FAILURE(InitViewport());
328     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
329 
330     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
331                                          "UNASSIGNED-BestPractices-UpdateDescriptors-AvoidCopyingDescriptors");
332 
333     VkDescriptorPoolSize ds_type_count = {};
334     ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
335     ds_type_count.descriptorCount = 1;
336 
337     VkDescriptorPoolCreateInfo ds_pool_ci = {};
338     ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
339     ds_pool_ci.pNext = NULL;
340     ds_pool_ci.maxSets = 1;
341     ds_pool_ci.poolSizeCount = 1;
342     ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
343     ds_pool_ci.pPoolSizes = &ds_type_count;
344 
345     VkDescriptorPool ds_pool;
346     vk::CreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
347 
348     VkDescriptorSetLayoutBinding dsl_binding = {};
349     dsl_binding.binding = 2;
350     dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
351     dsl_binding.descriptorCount = 1;
352     dsl_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
353     dsl_binding.pImmutableSamplers = NULL;
354 
355     const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding});
356 
357     VkDescriptorSet descriptor_sets[3] = {};
358     VkDescriptorSetAllocateInfo alloc_info = {};
359     alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
360     alloc_info.descriptorSetCount = 1;
361     alloc_info.descriptorPool = ds_pool;
362     alloc_info.pSetLayouts = &ds_layout.handle();
363     vk::AllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_sets[0]);
364     vk::AllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_sets[1]);
365 
366     VkCopyDescriptorSet copy_info = {};
367     copy_info.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET;
368     copy_info.descriptorCount = 1;
369     copy_info.srcSet = descriptor_sets[1];
370     copy_info.srcBinding = 2;
371     copy_info.srcArrayElement = 0;
372     copy_info.dstSet = descriptor_sets[0];
373     copy_info.dstBinding = 2;
374     copy_info.dstArrayElement = 0;
375 
376     vk::UpdateDescriptorSets(m_device->handle(), 0, nullptr, 1, &copy_info);
377 
378     m_errorMonitor->VerifyFound();
379 }
380 
TEST_F(VkAmdBestPracticesLayerTest,ClearImage)381 TEST_F(VkAmdBestPracticesLayerTest, ClearImage) {
382     TEST_DESCRIPTION("Test for validating usage of vkCmdClearAttachments");
383 
384 InitBestPracticesFramework(kEnableAMDValidation);
385     InitState();
386     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
387 
388     {
389         VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
390                                      nullptr,
391                                      VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
392                                      VK_IMAGE_TYPE_1D,
393                                      VK_FORMAT_R8G8B8A8_UNORM,
394                                      {1, 1, 1},
395                                      1,
396                                      1,
397                                      VK_SAMPLE_COUNT_1_BIT,
398                                      VK_IMAGE_TILING_OPTIMAL,
399                                      VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
400                                      VK_SHARING_MODE_EXCLUSIVE,
401                                      0,
402                                      nullptr,
403                                      VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL};
404         VkImageObj image_1D(m_device);
405         image_1D.init(&img_info);
406         ASSERT_TRUE(image_1D.initialized());
407 
408         m_commandBuffer->begin();
409         m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
410 
411         VkClearColorValue clear_value = {{0.0f, 0.0f, 0.0f, 0.0f}};
412         VkImageSubresourceRange image_range = {};
413         image_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
414         image_range.levelCount = 1;
415         image_range.layerCount = 1;
416 
417         m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
418                                              "UNASSIGNED-BestPractices-ClearAttachment-ClearImage");
419 
420         vk::CmdClearColorImage(m_commandBuffer->handle(), image_1D.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_value, 1,
421                                &image_range);
422         m_errorMonitor->VerifyFound();
423 
424         m_commandBuffer->EndRenderPass();
425         m_commandBuffer->end();
426     }
427 
428     {
429         VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
430                                      nullptr,
431                                      VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
432                                      VK_IMAGE_TYPE_1D,
433                                      VK_FORMAT_D32_SFLOAT_S8_UINT,
434                                      {1, 1, 1},
435                                      1,
436                                      1,
437                                      VK_SAMPLE_COUNT_1_BIT,
438                                      VK_IMAGE_TILING_OPTIMAL,
439                                      VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
440                                      VK_SHARING_MODE_EXCLUSIVE,
441                                      0,
442                                      nullptr,
443                                      VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL};
444         VkImageObj image_1D(m_device);
445         image_1D.init(&img_info);
446         ASSERT_TRUE(image_1D.initialized());
447 
448         m_commandBuffer->begin();
449         m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
450 
451         VkClearDepthStencilValue clear_value = {0.0f, 0};
452         VkImageSubresourceRange image_range = {};
453         image_range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
454         image_range.levelCount = 1;
455         image_range.layerCount = 1;
456 
457         m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
458                                              "UNASSIGNED-BestPractices-ClearAttachment-ClearImage");
459 
460         vk::CmdClearDepthStencilImage(m_commandBuffer->handle(), image_1D.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
461                                       &clear_value, 1, &image_range);
462         m_errorMonitor->VerifyFound();
463 
464         m_commandBuffer->EndRenderPass();
465         m_commandBuffer->end();
466     }
467 }
468 
TEST_F(VkAmdBestPracticesLayerTest,ImageToImageCopy)469 TEST_F(VkAmdBestPracticesLayerTest, ImageToImageCopy) {
470     InitBestPracticesFramework(kEnableAMDValidation);
471     InitState();
472     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
473 
474     VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
475                                  nullptr,
476                                  0,
477                                  VK_IMAGE_TYPE_2D,
478                                  VK_FORMAT_R8G8B8A8_UNORM,
479                                  {1, 1, 1},
480                                  1,
481                                  1,
482                                  VK_SAMPLE_COUNT_1_BIT,
483                                  VK_IMAGE_TILING_OPTIMAL,
484                                  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
485                                  VK_SHARING_MODE_EXCLUSIVE,
486                                  0,
487                                  nullptr,
488                                  VK_IMAGE_LAYOUT_UNDEFINED};
489     VkImageObj image1D_1(m_device);
490     image1D_1.init(&img_info);
491     ASSERT_TRUE(image1D_1.initialized());
492 
493     img_info.tiling = VK_IMAGE_TILING_LINEAR;
494     img_info.usage = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
495 
496     VkImageObj image_1D_2(m_device);
497     image_1D_2.init(&img_info);
498     if (!image_1D_2.initialized()) {
499         printf("%s Could not initilize Linear image, skipping image to image copy test\n", kSkipPrefix);
500         return;
501     }
502 
503     m_commandBuffer->begin();
504     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
505 
506     image1D_1.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
507     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
508                                          "UNASSIGNED-BestPractices-vkImage-AvoidImageToImageCopy");
509 
510     vk::CmdCopyImage(m_commandBuffer->handle(), image1D_1.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image_1D_2.handle(),
511                      VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, nullptr);
512     m_errorMonitor->VerifyFound();
513 }
514 
TEST_F(VkAmdBestPracticesLayerTest,GeneralLayout)515 TEST_F(VkAmdBestPracticesLayerTest, GeneralLayout) {
516     InitBestPracticesFramework(kEnableAMDValidation);
517     InitState();
518     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
519 
520     VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
521                                  nullptr,
522                                  0,
523                                  VK_IMAGE_TYPE_2D,
524                                  VK_FORMAT_R8G8B8A8_UNORM,
525                                  {1024, 1024, 1},
526                                  1,
527                                  1,
528                                  VK_SAMPLE_COUNT_1_BIT,
529                                  VK_IMAGE_TILING_OPTIMAL,
530                                  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
531                                  VK_SHARING_MODE_EXCLUSIVE,
532                                  0,
533                                  nullptr,
534                                  VK_IMAGE_LAYOUT_UNDEFINED};
535     VkImageObj image_1D(m_device);
536 
537     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
538                                          "UNASSIGNED-BestPractices-vkImage-AvoidGeneral");
539     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-VkCommandBuffer-AvoidTinyCmdBuffers");
540 
541     // the init function initializes to general layout
542     image_1D.init(&img_info);
543 
544     m_errorMonitor->VerifyFound();
545 }
546 
TEST_F(VkAmdBestPracticesLayerTest,RobustAccessOn)547 TEST_F(VkAmdBestPracticesLayerTest, RobustAccessOn) {
548     InitBestPracticesFramework(kEnableAMDValidation);
549     InitState();
550     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
551                                          "UNASSIGNED-BestPractices-vkCreateDevice-RobustBufferAccess");
552 
553     VkPhysicalDeviceFeatures features = {};
554     features.robustBufferAccess = true;
555 
556     const float q_priority[] = {1.0f};
557     VkDeviceQueueCreateInfo queue_ci = {};
558     queue_ci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
559     queue_ci.queueFamilyIndex = 0;
560     queue_ci.queueCount = 1;
561     queue_ci.pQueuePriorities = q_priority;
562 
563     VkDeviceCreateInfo device_ci = {};
564     device_ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
565     device_ci.queueCreateInfoCount = 1;
566     device_ci.pQueueCreateInfos = &queue_ci;
567     device_ci.pEnabledFeatures = &features;
568 
569     VkDevice test_device;
570     vk::CreateDevice(gpu(), &device_ci, nullptr, &test_device);
571 
572     m_errorMonitor->VerifyFound();
573 }
574 
TEST_F(VkAmdBestPracticesLayerTest,Barriers)575 TEST_F(VkAmdBestPracticesLayerTest, Barriers) {
576     InitBestPracticesFramework(kEnableAMDValidation);
577     InitState();
578     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
579 
580     VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
581                                  nullptr,
582                                  VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
583                                  VK_IMAGE_TYPE_1D,
584                                  VK_FORMAT_R8G8B8A8_UNORM,
585                                  {1, 1, 1},
586                                  1,
587                                  1,
588                                  VK_SAMPLE_COUNT_1_BIT,
589                                  VK_IMAGE_TILING_OPTIMAL,
590                                  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
591                                  VK_SHARING_MODE_EXCLUSIVE,
592                                  0,
593                                  nullptr,
594                                  VK_IMAGE_LAYOUT_UNDEFINED};
595     VkImageObj image_1D(m_device);
596     image_1D.init(&img_info);
597     ASSERT_TRUE(image_1D.initialized());
598 
599     m_commandBuffer->begin();
600     // check for read-to-read barrier
601     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
602                                          "UNASSIGNED-BestPractices-PipelineBarrier-readToReadBarrier");
603     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-CmdBuffer-backToBackBarrier");  // we already test for this above
604     image_1D.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
605     image_1D.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
606 
607     m_errorMonitor->VerifyFound();
608 
609     // check total number of barriers warning
610     uint32_t warn_Limit = 250;
611     for (uint32_t i = 0; i < warn_Limit; i++) {
612         image_1D.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
613         image_1D.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
614     }
615 
616     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
617                                          "UNASSIGNED-BestPractices-CmdBuffer-highBarrierCount");
618     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-CmdBuffer-backToBackBarrier");  // we already test for this above
619     image_1D.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
620     m_errorMonitor->VerifyFound();
621 }
622 
TEST_F(VkAmdBestPracticesLayerTest,NumberOfSubmissions)623 TEST_F(VkAmdBestPracticesLayerTest, NumberOfSubmissions) {
624     AddSurfaceInstanceExtension();
625 
626     InitBestPracticesFramework(kEnableAMDValidation);
627     AddSwapchainDeviceExtension();
628 
629     InitState();
630     ASSERT_NO_FATAL_FAILURE(InitViewport());
631     InitSwapchain();
632     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
633 
634     VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
635                                  nullptr,
636                                  VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
637                                  VK_IMAGE_TYPE_1D,
638                                  VK_FORMAT_R8G8B8A8_UNORM,
639                                  {1, 1, 1},
640                                  1,
641                                  1,
642                                  VK_SAMPLE_COUNT_1_BIT,
643                                  VK_IMAGE_TILING_OPTIMAL,
644                                  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
645                                  VK_SHARING_MODE_EXCLUSIVE,
646                                  0,
647                                  nullptr,
648                                  VK_IMAGE_LAYOUT_UNDEFINED};
649     VkImageObj image_1D(m_device);
650     image_1D.init(&img_info);
651     ASSERT_TRUE(image_1D.initialized());
652 
653     uint32_t warn_limit = 11;
654 
655     for (uint32_t i = 0; i < warn_limit; i++) {
656         image_1D.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
657         image_1D.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL);
658     }
659 
660     VkPresentInfoKHR present_info = {};
661     present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
662     present_info.waitSemaphoreCount = 0;
663     // presentInfo.pWaitSemaphores = &(m_RenderFinishedSemaphores[m_imageIndex]);
664     present_info.swapchainCount = 1;
665     present_info.pSwapchains = &m_swapchain;
666     present_info.pImageIndices = 0;
667     present_info.pResults = NULL;
668 
669     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
670                                          "UNASSIGNED-BestPractices-Submission-ReduceNumberOfSubmissions");
671 
672     vk::QueuePresentKHR(m_device->GetDefaultQueue()->handle(), &present_info);
673 
674     m_errorMonitor->VerifyFound();
675 }
676 
TEST_F(VkAmdBestPracticesLayerTest,NumSyncPrimitives)677 TEST_F(VkAmdBestPracticesLayerTest, NumSyncPrimitives) {
678     InitBestPracticesFramework(kEnableAMDValidation);
679     InitState();
680     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
681 
682     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
683                                          "UNASSIGNED-BestPractices-SyncObjects-HighNumberOfFences");
684     uint32_t fence_warn_limit = 5;
685     for (uint32_t i = 0; i < fence_warn_limit; i++) {
686         VkFence testFence;
687         VkFenceCreateInfo fenceInfo = VkFenceObj::create_info();
688         vk::CreateFence(m_device->device(), &fenceInfo, nullptr, &testFence);
689     }
690     m_errorMonitor->VerifyFound();
691 
692     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
693                                          "UNASSIGNED-BestPractices-SyncObjects-HighNumberOfSemaphores");
694     uint32_t semaphore_warn_limit = 12;
695     for (uint32_t i = 0; i < semaphore_warn_limit; i++) {
696         VkSemaphore test_semaphore;
697         VkSemaphoreCreateInfo semaphore_create_info = {};
698         semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
699         vk::CreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &test_semaphore);
700     }
701 
702     m_errorMonitor->VerifyFound();
703 }
704 
TEST_F(VkAmdBestPracticesLayerTest,SecondaryCmdBuffer)705 TEST_F(VkAmdBestPracticesLayerTest, SecondaryCmdBuffer) {
706     InitBestPracticesFramework(kEnableAMDValidation);
707     InitState();
708 
709     ASSERT_NO_FATAL_FAILURE(InitViewport());
710     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
711 
712     VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {};
713     pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
714     pipe_ms_state_ci.pNext = NULL;
715     pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
716     pipe_ms_state_ci.sampleShadingEnable = 0;
717     pipe_ms_state_ci.minSampleShading = 1.0;
718     pipe_ms_state_ci.pSampleMask = NULL;
719 
720     const float vbo_data[3] = {1.f, 0.f, 1.f};
721     VkVerticesObj vertex_buffer(m_device, 1, 1, sizeof(vbo_data), 1, vbo_data);
722 
723     CreatePipelineHelper pipe(*this);
724     pipe.InitInfo();
725     pipe.pipe_ms_state_ci_ = pipe_ms_state_ci;
726     pipe.InitState();
727 
728     vertex_buffer.AddVertexInputToPipeHelpr(&pipe);
729 
730     pipe.CreateGraphicsPipeline();
731 
732     VkCommandPoolObj pool(m_device, m_device->graphics_queue_node_index_);
733     VkCommandBufferObj secondary_cmd_buf(m_device, &pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
734 
735     // record a secondary command buffer
736     secondary_cmd_buf.begin();
737     secondary_cmd_buf.BeginRenderPass(m_renderPassBeginInfo);
738 
739     vk::CmdBindPipeline(secondary_cmd_buf.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
740     vertex_buffer.BindVertexBuffers(secondary_cmd_buf.handle());
741     secondary_cmd_buf.Draw(1, 0, 0, 0);
742     secondary_cmd_buf.Draw(1, 0, 0, 0);
743     secondary_cmd_buf.Draw(1, 0, 0, 0);
744     secondary_cmd_buf.Draw(1, 0, 0, 0);
745 
746     VkClearAttachment color_attachment;
747     color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
748     color_attachment.clearValue.color.float32[0] = 1.0;
749     color_attachment.clearValue.color.float32[1] = 1.0;
750     color_attachment.clearValue.color.float32[2] = 1.0;
751     color_attachment.clearValue.color.float32[3] = 1.0;
752     color_attachment.colorAttachment = 0;
753     VkClearRect clear_rect = {{{0, 0}, {(uint32_t)m_width, (uint32_t)m_height}}, 0, 1};
754 
755     m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-DrawState-ClearCmdBeforeDraw");
756 
757     vk::CmdClearAttachments(secondary_cmd_buf.handle(), 1, &color_attachment, 1, &clear_rect);
758 
759     secondary_cmd_buf.EndRenderPass();
760     secondary_cmd_buf.end();
761 
762     m_commandBuffer->begin();
763     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
764     m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit,
765                                          "UNASSIGNED-BestPractices-VkCommandBuffer-AvoidSecondaryCmdBuffers");
766 
767     vk::CmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary_cmd_buf.handle());
768 
769     m_errorMonitor->VerifyFound();
770 }