| /* |
| * Copyright (c) 2015-2021 The Khronos Group Inc. |
| * Copyright (c) 2015-2021 Valve Corporation |
| * Copyright (c) 2015-2021 LunarG, Inc. |
| * Modifications Copyright (C) 2020-2021 Advanced Micro Devices, Inc. All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Author: Nathaniel Cesario <nathaniel@lunarg.com> |
| * Author: Nadav Geva <nadav.geva@amd.com> |
| */ |
| |
| #include "cast_utils.h" |
| #include "layer_validation_tests.h" |
| |
| // Tests for AMD-specific best practices |
| const char *kEnableAMDValidation = "VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_AMD"; |
| |
| |
| // this is a very long test (~10 minutes) |
| // disabled for now |
| #ifdef AMD_LONG_RUNNING_TEST |
| TEST_F(VkAmdBestPracticesLayerTest, TooManyPipelines) { |
| |
| |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| |
| ASSERT_NO_FATAL_FAILURE(InitViewport()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| // create 1 more than the warning limit for pipeline objects |
| const uint32_t warn_limit = 5001; |
| VkPipeline pipeline_Array[warn_limit + 1] = {}; |
| |
| for (int i = 0; i <= warn_limit; i++) { |
| // create a new pipeline helper so the cache won't be used |
| // also imitates a "just in time" pipeline creator pattern |
| if (i == 1) { |
| // check that the second pipeline helper cache was detected |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-vkCreatePipelines-multiple-pipelines-caches"); |
| } |
| CreatePipelineHelper pipe(*this); |
| pipe.InitInfo(); |
| pipe.InitState(); |
| pipe.CreateGraphicsPipeline(); |
| pipeline_Array[i] = pipe.pipeline_; |
| if (i == 1) { |
| // change check to too many pipelines |
| m_errorMonitor->VerifyFound(); |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-CreatePipelines-TooManyPipelines"); |
| } |
| } |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| #endif |
| |
| TEST_F(VkAmdBestPracticesLayerTest, UseMutableRT) { |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| |
| ASSERT_NO_FATAL_FAILURE(InitViewport()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-vkImage-DontUseMutableRenderTargets"); |
| |
| // create a colot attachment image with mutable bit set |
| VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| nullptr, |
| VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, |
| VK_IMAGE_TYPE_1D, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| {1, 1, 1}, |
| 1, |
| 1, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, |
| VK_SHARING_MODE_EXCLUSIVE, |
| 0, |
| nullptr, |
| VK_IMAGE_LAYOUT_UNDEFINED}; |
| VkImage test_image = VK_NULL_HANDLE; |
| vk::CreateImage(m_device->handle(), &img_info, nullptr, &test_image); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-vkImage-DontUseMutableRenderTargets"); |
| // create a depth attachment image with mutable bit set |
| img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| nullptr, |
| VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, |
| VK_IMAGE_TYPE_1D, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| {1, 1, 1}, |
| 1, |
| 1, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, |
| VK_SHARING_MODE_EXCLUSIVE, |
| 0, |
| nullptr, |
| VK_IMAGE_LAYOUT_UNDEFINED}; |
| test_image = VK_NULL_HANDLE; |
| vk::CreateImage(m_device->handle(), &img_info, nullptr, &test_image); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-vkImage-DontUseMutableRenderTargets"); |
| // create a storage image with mutable bit set |
| img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| nullptr, |
| VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, |
| VK_IMAGE_TYPE_1D, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| {1, 1, 1}, |
| 1, |
| 1, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_STORAGE_BIT, |
| VK_SHARING_MODE_EXCLUSIVE, |
| 0, |
| nullptr, |
| VK_IMAGE_LAYOUT_UNDEFINED}; |
| test_image = VK_NULL_HANDLE; |
| vk::CreateImage(m_device->handle(), &img_info, nullptr, &test_image); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, UsageConcurentRT) { |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| |
| ASSERT_NO_FATAL_FAILURE(InitViewport()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-vkImage-AvoidConcurrentRenderTargets"); |
| |
| // create a render target image with mutable bit set |
| VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| nullptr, |
| 0, |
| VK_IMAGE_TYPE_1D, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| {1, 1, 1}, |
| 1, |
| 1, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, |
| VK_SHARING_MODE_CONCURRENT, |
| 0, |
| nullptr, |
| VK_IMAGE_LAYOUT_UNDEFINED}; |
| VkImage test_image = VK_NULL_HANDLE; |
| vk::CreateImage(m_device->handle(), &img_info, nullptr, &test_image); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-vkImage-AvoidConcurrentRenderTargets"); |
| // create a render target image with mutable bit set |
| img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| nullptr, |
| 0, |
| VK_IMAGE_TYPE_1D, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| {1, 1, 1}, |
| 1, |
| 1, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, |
| VK_SHARING_MODE_CONCURRENT, |
| 0, |
| nullptr, |
| VK_IMAGE_LAYOUT_UNDEFINED}; |
| test_image = VK_NULL_HANDLE; |
| vk::CreateImage(m_device->handle(), &img_info, nullptr, &test_image); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, UsageStorageRT) { |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| |
| ASSERT_NO_FATAL_FAILURE(InitViewport()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-vkImage-DontUseStorageRenderTargets"); |
| |
| // create a render target image with mutable bit set |
| VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| nullptr, |
| 0, |
| VK_IMAGE_TYPE_1D, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| {1, 1, 1}, |
| 1, |
| 1, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT, |
| VK_SHARING_MODE_EXCLUSIVE, |
| 0, |
| nullptr, |
| VK_IMAGE_LAYOUT_UNDEFINED}; |
| VkImage test_image = VK_NULL_HANDLE; |
| vk::CreateImage(m_device->handle(), &img_info, nullptr, &test_image); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, PrimitiveRestart) { |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| |
| ASSERT_NO_FATAL_FAILURE(InitViewport()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-CreatePipelines-AvoidPrimitiveRestart"); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.InitInfo(); |
| pipe.InitState(); |
| pipe.ia_ci_.primitiveRestartEnable = true; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, NumDynamicStates) { |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| |
| ASSERT_NO_FATAL_FAILURE(InitViewport()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-CreatePipelines-MinimizeNumDynamicStates"); |
| |
| // fill the dynamic array with the first 8 types in the enum |
| // imitates a case where the user have set most dynamic states unnecessarily |
| VkDynamicState dynamic_states_array[8] = {}; |
| for (uint32_t i = 0; i < 8; i++) { |
| dynamic_states_array[i] = (VkDynamicState)i; |
| } |
| |
| VkPipelineDynamicStateCreateInfo dynamic_state_info = {}; |
| dynamic_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; |
| dynamic_state_info.dynamicStateCount = 8; |
| dynamic_state_info.pDynamicStates = dynamic_states_array; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.InitInfo(); |
| pipe.InitState(); |
| pipe.dyn_state_ci_ = dynamic_state_info; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, KeepLayoutSmall) { |
| // TODO: add dynamic buffer check as well |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| |
| ASSERT_NO_FATAL_FAILURE(InitViewport()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-CreatePipelinesLayout-KeepLayoutSmall"); |
| |
| // create a layout of 15 DWORDS (40 bytes push constants (10 DWORDS), a descriptor set (1 DWORD), and 2 dynamic buffers (4 |
| // DWORDS) |
| |
| uint32_t push_size_dwords = 10; |
| VkPushConstantRange push_range = {}; |
| push_range.stageFlags = VK_SHADER_STAGE_ALL; |
| push_range.offset = 0; |
| push_range.size = 4 * push_size_dwords; |
| |
| VkDescriptorSetLayoutBinding binding; |
| binding.binding = 0; |
| binding.descriptorCount = 2; |
| binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; |
| binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; |
| |
| VkDescriptorSetLayout DS_layout; |
| |
| VkDescriptorSetLayoutCreateInfo DS_layout_info = {}; |
| DS_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; |
| DS_layout_info.bindingCount = 1; |
| DS_layout_info.pBindings = &binding; |
| |
| vk::CreateDescriptorSetLayout(m_device->device(), &DS_layout_info, nullptr, &DS_layout); |
| |
| VkPipelineLayoutCreateInfo pipeline_layout_info = {}; |
| pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; |
| pipeline_layout_info.setLayoutCount = 1; |
| pipeline_layout_info.pSetLayouts = &DS_layout; |
| pipeline_layout_info.pushConstantRangeCount = 1; |
| pipeline_layout_info.pPushConstantRanges = &push_range; |
| |
| VkPipelineLayout test_pipeline_layout = VK_NULL_HANDLE; |
| vk::CreatePipelineLayout(m_device->handle(), &pipeline_layout_info, nullptr, &test_pipeline_layout); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, CopyingDescriptors) { |
| // TODO: add dynamic buffer check as well |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| |
| ASSERT_NO_FATAL_FAILURE(InitViewport()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-UpdateDescriptors-AvoidCopyingDescriptors"); |
| |
| VkDescriptorPoolSize ds_type_count = {}; |
| ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; |
| ds_type_count.descriptorCount = 1; |
| |
| VkDescriptorPoolCreateInfo ds_pool_ci = {}; |
| ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; |
| ds_pool_ci.pNext = NULL; |
| ds_pool_ci.maxSets = 1; |
| ds_pool_ci.poolSizeCount = 1; |
| ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; |
| ds_pool_ci.pPoolSizes = &ds_type_count; |
| |
| VkDescriptorPool ds_pool; |
| vk::CreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); |
| |
| VkDescriptorSetLayoutBinding dsl_binding = {}; |
| dsl_binding.binding = 2; |
| dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; |
| dsl_binding.descriptorCount = 1; |
| dsl_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; |
| dsl_binding.pImmutableSamplers = NULL; |
| |
| const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding}); |
| |
| VkDescriptorSet descriptor_sets[3] = {}; |
| VkDescriptorSetAllocateInfo alloc_info = {}; |
| alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; |
| alloc_info.descriptorSetCount = 1; |
| alloc_info.descriptorPool = ds_pool; |
| alloc_info.pSetLayouts = &ds_layout.handle(); |
| vk::AllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_sets[0]); |
| vk::AllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_sets[1]); |
| |
| VkCopyDescriptorSet copy_info = {}; |
| copy_info.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; |
| copy_info.descriptorCount = 1; |
| copy_info.srcSet = descriptor_sets[1]; |
| copy_info.srcBinding = 2; |
| copy_info.srcArrayElement = 0; |
| copy_info.dstSet = descriptor_sets[0]; |
| copy_info.dstBinding = 2; |
| copy_info.dstArrayElement = 0; |
| |
| vk::UpdateDescriptorSets(m_device->handle(), 0, nullptr, 1, ©_info); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, ClearImage) { |
| TEST_DESCRIPTION("Test for validating usage of vkCmdClearAttachments"); |
| |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| { |
| VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| nullptr, |
| VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, |
| VK_IMAGE_TYPE_1D, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| {1, 1, 1}, |
| 1, |
| 1, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, |
| VK_SHARING_MODE_EXCLUSIVE, |
| 0, |
| nullptr, |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL}; |
| VkImageObj image_1D(m_device); |
| image_1D.init(&img_info); |
| ASSERT_TRUE(image_1D.initialized()); |
| |
| m_commandBuffer->begin(); |
| m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); |
| |
| VkClearColorValue clear_value = {{0.0f, 0.0f, 0.0f, 0.0f}}; |
| VkImageSubresourceRange image_range = {}; |
| image_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| image_range.levelCount = 1; |
| image_range.layerCount = 1; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-ClearAttachment-ClearImage"); |
| |
| vk::CmdClearColorImage(m_commandBuffer->handle(), image_1D.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_value, 1, |
| &image_range); |
| m_errorMonitor->VerifyFound(); |
| |
| m_commandBuffer->EndRenderPass(); |
| m_commandBuffer->end(); |
| } |
| |
| { |
| VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| nullptr, |
| VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, |
| VK_IMAGE_TYPE_1D, |
| VK_FORMAT_D32_SFLOAT_S8_UINT, |
| {1, 1, 1}, |
| 1, |
| 1, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, |
| VK_SHARING_MODE_EXCLUSIVE, |
| 0, |
| nullptr, |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL}; |
| VkImageObj image_1D(m_device); |
| image_1D.init(&img_info); |
| ASSERT_TRUE(image_1D.initialized()); |
| |
| m_commandBuffer->begin(); |
| m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); |
| |
| VkClearDepthStencilValue clear_value = {0.0f, 0}; |
| VkImageSubresourceRange image_range = {}; |
| image_range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; |
| image_range.levelCount = 1; |
| image_range.layerCount = 1; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-ClearAttachment-ClearImage"); |
| |
| vk::CmdClearDepthStencilImage(m_commandBuffer->handle(), image_1D.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| &clear_value, 1, &image_range); |
| m_errorMonitor->VerifyFound(); |
| |
| m_commandBuffer->EndRenderPass(); |
| m_commandBuffer->end(); |
| } |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, ImageToImageCopy) { |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| nullptr, |
| 0, |
| VK_IMAGE_TYPE_2D, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| {1, 1, 1}, |
| 1, |
| 1, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, |
| VK_SHARING_MODE_EXCLUSIVE, |
| 0, |
| nullptr, |
| VK_IMAGE_LAYOUT_UNDEFINED}; |
| VkImageObj image1D_1(m_device); |
| image1D_1.init(&img_info); |
| ASSERT_TRUE(image1D_1.initialized()); |
| |
| img_info.tiling = VK_IMAGE_TILING_LINEAR; |
| img_info.usage = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| |
| VkImageObj image_1D_2(m_device); |
| image_1D_2.init(&img_info); |
| if (!image_1D_2.initialized()) { |
| printf("%s Could not initilize Linear image, skipping image to image copy test\n", kSkipPrefix); |
| return; |
| } |
| |
| m_commandBuffer->begin(); |
| m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); |
| |
| image1D_1.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-vkImage-AvoidImageToImageCopy"); |
| |
| vk::CmdCopyImage(m_commandBuffer->handle(), image1D_1.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image_1D_2.handle(), |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, nullptr); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, GeneralLayout) { |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| nullptr, |
| 0, |
| VK_IMAGE_TYPE_2D, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| {1024, 1024, 1}, |
| 1, |
| 1, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, |
| VK_SHARING_MODE_EXCLUSIVE, |
| 0, |
| nullptr, |
| VK_IMAGE_LAYOUT_UNDEFINED}; |
| VkImageObj image_1D(m_device); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-vkImage-AvoidGeneral"); |
| m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-VkCommandBuffer-AvoidTinyCmdBuffers"); |
| |
| // the init function initializes to general layout |
| image_1D.init(&img_info); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, RobustAccessOn) { |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-vkCreateDevice-RobustBufferAccess"); |
| |
| VkPhysicalDeviceFeatures features = {}; |
| features.robustBufferAccess = true; |
| |
| const float q_priority[] = {1.0f}; |
| VkDeviceQueueCreateInfo queue_ci = {}; |
| queue_ci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; |
| queue_ci.queueFamilyIndex = 0; |
| queue_ci.queueCount = 1; |
| queue_ci.pQueuePriorities = q_priority; |
| |
| VkDeviceCreateInfo device_ci = {}; |
| device_ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; |
| device_ci.queueCreateInfoCount = 1; |
| device_ci.pQueueCreateInfos = &queue_ci; |
| device_ci.pEnabledFeatures = &features; |
| |
| VkDevice test_device; |
| vk::CreateDevice(gpu(), &device_ci, nullptr, &test_device); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, Barriers) { |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| nullptr, |
| VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, |
| VK_IMAGE_TYPE_1D, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| {1, 1, 1}, |
| 1, |
| 1, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, |
| VK_SHARING_MODE_EXCLUSIVE, |
| 0, |
| nullptr, |
| VK_IMAGE_LAYOUT_UNDEFINED}; |
| VkImageObj image_1D(m_device); |
| image_1D.init(&img_info); |
| ASSERT_TRUE(image_1D.initialized()); |
| |
| m_commandBuffer->begin(); |
| // check for read-to-read barrier |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-PipelineBarrier-readToReadBarrier"); |
| m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-CmdBuffer-backToBackBarrier"); // we already test for this above |
| image_1D.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); |
| image_1D.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); |
| |
| m_errorMonitor->VerifyFound(); |
| |
| // check total number of barriers warning |
| uint32_t warn_Limit = 250; |
| for (uint32_t i = 0; i < warn_Limit; i++) { |
| image_1D.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); |
| image_1D.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); |
| } |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-CmdBuffer-highBarrierCount"); |
| m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-CmdBuffer-backToBackBarrier"); // we already test for this above |
| image_1D.SetLayout(m_commandBuffer, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, NumberOfSubmissions) { |
| AddSurfaceInstanceExtension(); |
| |
| InitBestPracticesFramework(kEnableAMDValidation); |
| AddSwapchainDeviceExtension(); |
| |
| InitState(); |
| ASSERT_NO_FATAL_FAILURE(InitViewport()); |
| InitSwapchain(); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| VkImageCreateInfo img_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| nullptr, |
| VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, |
| VK_IMAGE_TYPE_1D, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| {1, 1, 1}, |
| 1, |
| 1, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, |
| VK_SHARING_MODE_EXCLUSIVE, |
| 0, |
| nullptr, |
| VK_IMAGE_LAYOUT_UNDEFINED}; |
| VkImageObj image_1D(m_device); |
| image_1D.init(&img_info); |
| ASSERT_TRUE(image_1D.initialized()); |
| |
| uint32_t warn_limit = 11; |
| |
| for (uint32_t i = 0; i < warn_limit; i++) { |
| image_1D.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); |
| image_1D.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL); |
| } |
| |
| VkPresentInfoKHR present_info = {}; |
| present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; |
| present_info.waitSemaphoreCount = 0; |
| // presentInfo.pWaitSemaphores = &(m_RenderFinishedSemaphores[m_imageIndex]); |
| present_info.swapchainCount = 1; |
| present_info.pSwapchains = &m_swapchain; |
| present_info.pImageIndices = 0; |
| present_info.pResults = NULL; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-Submission-ReduceNumberOfSubmissions"); |
| |
| vk::QueuePresentKHR(m_device->GetDefaultQueue()->handle(), &present_info); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, NumSyncPrimitives) { |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-SyncObjects-HighNumberOfFences"); |
| uint32_t fence_warn_limit = 5; |
| for (uint32_t i = 0; i < fence_warn_limit; i++) { |
| VkFence testFence; |
| VkFenceCreateInfo fenceInfo = VkFenceObj::create_info(); |
| vk::CreateFence(m_device->device(), &fenceInfo, nullptr, &testFence); |
| } |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-SyncObjects-HighNumberOfSemaphores"); |
| uint32_t semaphore_warn_limit = 12; |
| for (uint32_t i = 0; i < semaphore_warn_limit; i++) { |
| VkSemaphore test_semaphore; |
| VkSemaphoreCreateInfo semaphore_create_info = {}; |
| semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; |
| vk::CreateSemaphore(m_device->device(), &semaphore_create_info, nullptr, &test_semaphore); |
| } |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkAmdBestPracticesLayerTest, SecondaryCmdBuffer) { |
| InitBestPracticesFramework(kEnableAMDValidation); |
| InitState(); |
| |
| ASSERT_NO_FATAL_FAILURE(InitViewport()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {}; |
| pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; |
| pipe_ms_state_ci.pNext = NULL; |
| pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; |
| pipe_ms_state_ci.sampleShadingEnable = 0; |
| pipe_ms_state_ci.minSampleShading = 1.0; |
| pipe_ms_state_ci.pSampleMask = NULL; |
| |
| const float vbo_data[3] = {1.f, 0.f, 1.f}; |
| VkVerticesObj vertex_buffer(m_device, 1, 1, sizeof(vbo_data), 1, vbo_data); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.InitInfo(); |
| pipe.pipe_ms_state_ci_ = pipe_ms_state_ci; |
| pipe.InitState(); |
| |
| vertex_buffer.AddVertexInputToPipeHelpr(&pipe); |
| |
| pipe.CreateGraphicsPipeline(); |
| |
| VkCommandPoolObj pool(m_device, m_device->graphics_queue_node_index_); |
| VkCommandBufferObj secondary_cmd_buf(m_device, &pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); |
| |
| // record a secondary command buffer |
| secondary_cmd_buf.begin(); |
| secondary_cmd_buf.BeginRenderPass(m_renderPassBeginInfo); |
| |
| vk::CmdBindPipeline(secondary_cmd_buf.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_); |
| vertex_buffer.BindVertexBuffers(secondary_cmd_buf.handle()); |
| secondary_cmd_buf.Draw(1, 0, 0, 0); |
| secondary_cmd_buf.Draw(1, 0, 0, 0); |
| secondary_cmd_buf.Draw(1, 0, 0, 0); |
| secondary_cmd_buf.Draw(1, 0, 0, 0); |
| |
| VkClearAttachment color_attachment; |
| color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| color_attachment.clearValue.color.float32[0] = 1.0; |
| color_attachment.clearValue.color.float32[1] = 1.0; |
| color_attachment.clearValue.color.float32[2] = 1.0; |
| color_attachment.clearValue.color.float32[3] = 1.0; |
| color_attachment.colorAttachment = 0; |
| VkClearRect clear_rect = {{{0, 0}, {(uint32_t)m_width, (uint32_t)m_height}}, 0, 1}; |
| |
| m_errorMonitor->SetAllowedFailureMsg("UNASSIGNED-BestPractices-DrawState-ClearCmdBeforeDraw"); |
| |
| vk::CmdClearAttachments(secondary_cmd_buf.handle(), 1, &color_attachment, 1, &clear_rect); |
| |
| secondary_cmd_buf.EndRenderPass(); |
| secondary_cmd_buf.end(); |
| |
| m_commandBuffer->begin(); |
| m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); |
| m_errorMonitor->SetDesiredFailureMsg(kPerformanceWarningBit, |
| "UNASSIGNED-BestPractices-VkCommandBuffer-AvoidSecondaryCmdBuffers"); |
| |
| vk::CmdExecuteCommands(m_commandBuffer->handle(), 1, &secondary_cmd_buf.handle()); |
| |
| m_errorMonitor->VerifyFound(); |
| } |