| /* |
| * Copyright (c) 2015-2022 The Khronos Group Inc. |
| * Copyright (c) 2015-2022 Valve Corporation |
| * Copyright (c) 2015-2022 LunarG, Inc. |
| * Copyright (c) 2015-2022 Google, Inc. |
| * |
| * 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: Chia-I Wu <olvaffe@gmail.com> |
| * Author: Chris Forbes <chrisf@ijw.co.nz> |
| * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> |
| * Author: Mark Lobodzinski <mark@lunarg.com> |
| * Author: Mike Stroyan <mike@LunarG.com> |
| * Author: Tobin Ehlis <tobine@google.com> |
| * Author: Tony Barbour <tony@LunarG.com> |
| * Author: Cody Northrop <cnorthrop@google.com> |
| * Author: Dave Houlton <daveh@lunarg.com> |
| * Author: Jeremy Kniager <jeremyk@lunarg.com> |
| * Author: Shannon McPherson <shannon@lunarg.com> |
| * Author: John Zulauf <jzulauf@lunarg.com> |
| */ |
| |
| #include "../layer_validation_tests.h" |
| #include "vk_extension_helper.h" |
| |
| #include <algorithm> |
| #include <array> |
| #include <chrono> |
| #include <memory> |
| #include <mutex> |
| #include <thread> |
| |
| #include "cast_utils.h" |
| |
| TEST_F(VkPositiveLayerTest, DynamicRenderingDraw) { |
| TEST_DESCRIPTION("Draw with Dynamic Rendering."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| |
| ASSERT_NO_FATAL_FAILURE(InitFramework()); |
| |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| |
| if (DeviceValidationVersion() < VK_API_VERSION_1_1) { |
| GTEST_SKIP() << "At least Vulkan version 1.1 is required"; |
| } |
| |
| auto dynamic_rendering_features = LvlInitStruct<VkPhysicalDeviceDynamicRenderingFeaturesKHR>(); |
| auto features2 = GetPhysicalDeviceFeatures2(dynamic_rendering_features); |
| if (!dynamic_rendering_features.dynamicRendering) { |
| printf("%s Test requires (unsupported) dynamicRendering , skipping\n", kSkipPrefix); |
| return; |
| } |
| |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); |
| |
| char const* fsSource = R"glsl( |
| #version 450 |
| layout(location=0) out vec4 color; |
| void main() { |
| color = vec4(1.0f); |
| } |
| )glsl"; |
| |
| VkShaderObj vs(this, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(this, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| VkPipelineObj pipe(m_device); |
| pipe.AddShader(&vs); |
| pipe.AddShader(&fs); |
| pipe.AddDefaultColorAttachment(); |
| |
| VkDescriptorSetLayoutBinding dslb = {0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; |
| const VkDescriptorSetLayoutObj dsl(m_device, {dslb}); |
| const VkPipelineLayoutObj pl(m_device, {&dsl}); |
| |
| VkFormat color_formats = {VK_FORMAT_R8G8B8A8_UNORM}; |
| auto pipeline_rendering_info = LvlInitStruct<VkPipelineRenderingCreateInfoKHR>(); |
| pipeline_rendering_info.colorAttachmentCount = 1; |
| pipeline_rendering_info.pColorAttachmentFormats = &color_formats; |
| |
| auto create_info = LvlInitStruct<VkGraphicsPipelineCreateInfo>(); |
| pipe.InitGraphicsPipelineCreateInfo(&create_info); |
| create_info.pNext = &pipeline_rendering_info; |
| |
| pipe.CreateVKPipeline(pl.handle(), VK_NULL_HANDLE, &create_info); |
| |
| VkViewport viewport = {0, 0, 16, 16, 0, 1}; |
| VkRect2D scissor = {{0, 0}, {16, 16}}; |
| |
| VkRenderingAttachmentInfoKHR color_attachment = LvlInitStruct<VkRenderingAttachmentInfoKHR>(); |
| color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| |
| VkRenderingInfoKHR begin_rendering_info = LvlInitStruct<VkRenderingInfoKHR>(); |
| begin_rendering_info.colorAttachmentCount = 1; |
| begin_rendering_info.pColorAttachments = &color_attachment; |
| begin_rendering_info.layerCount = 1; |
| |
| m_commandBuffer->begin(); |
| m_commandBuffer->BeginRendering(begin_rendering_info); |
| vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); |
| vk::CmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); |
| vk::CmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); |
| vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); |
| m_commandBuffer->EndRendering(); |
| m_commandBuffer->end(); |
| } |
| |
| TEST_F(VkPositiveLayerTest, DynamicRenderingDrawMultiBind) { |
| TEST_DESCRIPTION("Draw with Dynamic Rendering and multiple CmdBindPipeline calls."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| |
| ASSERT_NO_FATAL_FAILURE(InitFramework()); |
| |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| |
| if (DeviceValidationVersion() < VK_API_VERSION_1_1) { |
| GTEST_SKIP() << "At least Vulkan version 1.1 is required"; |
| } |
| |
| auto dynamic_rendering_features = LvlInitStruct<VkPhysicalDeviceDynamicRenderingFeaturesKHR>(); |
| auto features2 = GetPhysicalDeviceFeatures2(dynamic_rendering_features); |
| if (!dynamic_rendering_features.dynamicRendering) { |
| printf("%s Test requires (unsupported) dynamicRendering , skipping\n", kSkipPrefix); |
| return; |
| } |
| |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); |
| |
| char const* fsSource = R"glsl( |
| #version 450 |
| layout(location=0) out vec4 color; |
| void main() { |
| color = vec4(1.0f); |
| } |
| )glsl"; |
| |
| VkShaderObj vs(this, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(this, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| const auto depth_format = FindSupportedDepthOnlyFormat(gpu()); |
| auto ds_ci = LvlInitStruct<VkPipelineDepthStencilStateCreateInfo>(); |
| |
| VkPipelineObj pipe(m_device); |
| pipe.AddShader(&vs); |
| pipe.AddShader(&fs); |
| pipe.SetDepthStencil(&ds_ci); |
| pipe.AddDefaultColorAttachment(); |
| |
| VkPipelineObj pipe2(m_device); |
| pipe2.AddShader(&vs); |
| pipe2.AddShader(&fs); |
| pipe2.AddDefaultColorAttachment(); |
| |
| VkDescriptorSetLayoutBinding dslb = {0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; |
| const VkDescriptorSetLayoutObj dsl(m_device, {dslb}); |
| const VkPipelineLayoutObj pl(m_device, {&dsl}); |
| |
| VkFormat color_formats = {VK_FORMAT_R8G8B8A8_UNORM}; |
| auto pipeline_rendering_info = LvlInitStruct<VkPipelineRenderingCreateInfoKHR>(); |
| pipeline_rendering_info.colorAttachmentCount = 1; |
| pipeline_rendering_info.pColorAttachmentFormats = &color_formats; |
| pipeline_rendering_info.depthAttachmentFormat = depth_format; |
| |
| auto create_info = LvlInitStruct<VkGraphicsPipelineCreateInfo>(); |
| pipe.InitGraphicsPipelineCreateInfo(&create_info); |
| create_info.pNext = &pipeline_rendering_info; |
| pipe.CreateVKPipeline(pl.handle(), VK_NULL_HANDLE, &create_info); |
| |
| pipeline_rendering_info.depthAttachmentFormat = VK_FORMAT_UNDEFINED; |
| pipe2.InitGraphicsPipelineCreateInfo(&create_info); |
| create_info.pNext = &pipeline_rendering_info; |
| pipe2.CreateVKPipeline(pl.handle(), VK_NULL_HANDLE, &create_info); |
| |
| VkViewport viewport = {0, 0, 16, 16, 0, 1}; |
| VkRect2D scissor = {{0, 0}, {16, 16}}; |
| |
| VkRenderingAttachmentInfoKHR color_attachment = LvlInitStruct<VkRenderingAttachmentInfoKHR>(); |
| color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| |
| VkRenderingInfoKHR begin_rendering_info = LvlInitStruct<VkRenderingInfoKHR>(); |
| begin_rendering_info.colorAttachmentCount = 1; |
| begin_rendering_info.pColorAttachments = &color_attachment; |
| begin_rendering_info.layerCount = 1; |
| |
| m_commandBuffer->begin(); |
| m_commandBuffer->BeginRendering(begin_rendering_info); |
| vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); |
| vk::CmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); |
| vk::CmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); |
| vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); |
| m_commandBuffer->EndRendering(); |
| |
| m_commandBuffer->BeginRendering(begin_rendering_info); |
| // NOTE: Setting dynamic state does not count as "using" the currently bound pipeline. |
| vk::CmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); |
| vk::CmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); |
| vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe2.handle()); |
| vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); |
| m_commandBuffer->EndRendering(); |
| m_commandBuffer->end(); |
| } |
| |
| TEST_F(VkPositiveLayerTest, TestBeginQueryInDynamicRendering) { |
| TEST_DESCRIPTION("Test calling vkCmdBeginQuery with a dynamic render pass."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| |
| ASSERT_NO_FATAL_FAILURE(InitFramework()); |
| |
| if (DeviceValidationVersion() < VK_API_VERSION_1_3) { |
| GTEST_SKIP() << "At least Vulkan version 1.3 is required"; |
| } |
| |
| auto vk13features = LvlInitStruct<VkPhysicalDeviceVulkan13Features>(); |
| auto features2 = GetPhysicalDeviceFeatures2(vk13features); |
| if (!vk13features.dynamicRendering) { |
| printf("%s Test requires (unsupported) dynamicRendering, skipping\n", kSkipPrefix); |
| return; |
| } |
| if (!vk13features.synchronization2) { |
| printf("%s Test requires (unsupported) synchronization2, skipping\n", kSkipPrefix); |
| return; |
| } |
| |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| PFN_vkCmdBeginRendering vkCmdBeginRendering = |
| reinterpret_cast<PFN_vkCmdBeginRendering>(vk::GetDeviceProcAddr(m_device->device(), "vkCmdBeginRendering")); |
| assert(vkCmdBeginRendering != nullptr); |
| PFN_vkCmdEndRendering vkCmdEndRendering = |
| reinterpret_cast<PFN_vkCmdEndRendering>(vk::GetDeviceProcAddr(m_device->device(), "vkCmdEndRendering")); |
| assert(vkCmdEndRendering != nullptr); |
| |
| VkRenderingInfoKHR begin_rendering_info = LvlInitStruct<VkRenderingInfoKHR>(); |
| begin_rendering_info.layerCount = 1; |
| |
| VkQueryPoolCreateInfo qpci = LvlInitStruct<VkQueryPoolCreateInfo>(); |
| qpci.queryType = VK_QUERY_TYPE_OCCLUSION; |
| qpci.queryCount = 2; |
| |
| vk_testing::QueryPool query_pool; |
| query_pool.init(*m_device, qpci); |
| |
| m_commandBuffer->begin(); |
| |
| vkCmdBeginRendering(m_commandBuffer->handle(), &begin_rendering_info); |
| vk::CmdBeginQuery(m_commandBuffer->handle(), query_pool.handle(), 0, 0); |
| vk::CmdEndQuery(m_commandBuffer->handle(), query_pool.handle(), 0); |
| vkCmdEndRendering(m_commandBuffer->handle()); |
| |
| m_commandBuffer->end(); |
| } |
| |
| TEST_F(VkPositiveLayerTest, DynamicRenderingPipeWithDiscard) { |
| TEST_DESCRIPTION("Create dynamic rendering pipeline with rasterizer discard."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| |
| ASSERT_NO_FATAL_FAILURE(InitFramework()); |
| |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| |
| if (DeviceValidationVersion() < VK_API_VERSION_1_1) { |
| GTEST_SKIP() << "At least Vulkan version 1.1 is required"; |
| } |
| |
| auto dynamic_rendering_features = LvlInitStruct<VkPhysicalDeviceDynamicRenderingFeaturesKHR>(); |
| auto features2 = GetPhysicalDeviceFeatures2(dynamic_rendering_features); |
| if (!dynamic_rendering_features.dynamicRendering) { |
| printf("%s Test requires (unsupported) dynamicRendering , skipping\n", kSkipPrefix); |
| return; |
| } |
| |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); |
| |
| VkShaderObj vs(this, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(this, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| VkPipelineRasterizationStateCreateInfo rs_ci = LvlInitStruct<VkPipelineRasterizationStateCreateInfo>(); |
| rs_ci.rasterizerDiscardEnable = VK_TRUE; |
| rs_ci.lineWidth = 1.0f; |
| |
| VkPipelineDepthStencilStateCreateInfo ds_ci = LvlInitStruct<VkPipelineDepthStencilStateCreateInfo>(); |
| ds_ci.depthTestEnable = VK_TRUE; |
| ds_ci.depthWriteEnable = VK_TRUE; |
| |
| VkPipelineObj pipe(m_device); |
| pipe.AddShader(&vs); |
| pipe.AddShader(&fs); |
| pipe.AddDefaultColorAttachment(); |
| pipe.SetDepthStencil(&ds_ci); |
| pipe.SetRasterization(&rs_ci); |
| |
| VkDescriptorSetLayoutBinding dslb = {0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; |
| const VkDescriptorSetLayoutObj dsl(m_device, {dslb}); |
| const VkPipelineLayoutObj pl(m_device, {&dsl}); |
| |
| auto create_info = LvlInitStruct<VkGraphicsPipelineCreateInfo>(); |
| pipe.InitGraphicsPipelineCreateInfo(&create_info); |
| create_info.layout = pl.handle(); |
| create_info.renderPass = VK_NULL_HANDLE; |
| |
| VkFormat color_formats = {VK_FORMAT_R8G8B8A8_UNORM}; |
| auto pipeline_rendering_info = LvlInitStruct<VkPipelineRenderingCreateInfoKHR>(); |
| pipeline_rendering_info.colorAttachmentCount = 1; |
| pipeline_rendering_info.pColorAttachmentFormats = &color_formats; |
| pipeline_rendering_info.depthAttachmentFormat = VK_FORMAT_D16_UNORM; // D16_UNORM has guaranteed support |
| pipeline_rendering_info.pNext = create_info.pNext; |
| create_info.pNext = &pipeline_rendering_info; |
| |
| const VkRenderPass render_pass = VK_NULL_HANDLE; |
| pipe.CreateVKPipeline(pl.handle(), render_pass, &create_info); |
| } |
| |
| |
| TEST_F(VkPositiveLayerTest, UseStencilAttachmentWithIntegerFormatAndDepthStencilResolve) { |
| TEST_DESCRIPTION("Use stencil attachment with integer format and depth stencil resolve extension"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME); |
| ASSERT_NO_FATAL_FAILURE(InitFramework()); |
| |
| if (DeviceValidationVersion() < VK_API_VERSION_1_1) { |
| GTEST_SKIP() << "At least Vulkan version 1.1 is required"; |
| } |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| |
| auto dynamic_rendering_features = LvlInitStruct<VkPhysicalDeviceDynamicRenderingFeaturesKHR>(); |
| auto features2 = GetPhysicalDeviceFeatures2(dynamic_rendering_features); |
| if (dynamic_rendering_features.dynamicRendering == VK_FALSE) { |
| printf("%s Test requires (unsupported) dynamicRendering , skipping\n", kSkipPrefix); |
| return; |
| } |
| |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| if (ImageFormatIsSupported(gpu(), VK_FORMAT_S8_UINT, VK_IMAGE_TILING_OPTIMAL)) { |
| printf("%s VK_FORMAT_S8_UINT format not supported, skipping test.\n", kSkipPrefix); |
| return; |
| } |
| |
| auto depth_stencil_resolve_properties = LvlInitStruct<VkPhysicalDeviceDepthStencilResolveProperties>(); |
| auto properties2 = LvlInitStruct<VkPhysicalDeviceProperties2>(&depth_stencil_resolve_properties); |
| GetPhysicalDeviceProperties2(properties2); |
| if (depth_stencil_resolve_properties.supportedStencilResolveModes & VK_RESOLVE_MODE_AVERAGE_BIT) { |
| printf("%s VK_RESOLVE_MODE_AVERAGE_BIT not supported for VK_FORMAT_S8_UINT, skipping test.\n", kSkipPrefix); |
| return; |
| } |
| |
| VkImageCreateInfo image_create_info = LvlInitStruct<VkImageCreateInfo>(); |
| image_create_info.imageType = VK_IMAGE_TYPE_2D; |
| image_create_info.format = VK_FORMAT_S8_UINT; |
| image_create_info.extent = {32, 32, 1}; |
| image_create_info.mipLevels = 1; |
| image_create_info.arrayLayers = 1; |
| image_create_info.samples = VK_SAMPLE_COUNT_2_BIT; |
| image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; |
| image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; |
| VkImageObj image(m_device); |
| image.Init(image_create_info); |
| VkImageView image_view = image.targetView(VK_FORMAT_S8_UINT, VK_IMAGE_ASPECT_STENCIL_BIT); |
| |
| VkRenderingAttachmentInfoKHR stencil_attachment = LvlInitStruct<VkRenderingAttachmentInfoKHR>(); |
| stencil_attachment.imageView = image_view; |
| stencil_attachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
| stencil_attachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT; |
| stencil_attachment.resolveImageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| |
| VkRenderingInfoKHR begin_rendering_info = LvlInitStruct<VkRenderingInfoKHR>(); |
| begin_rendering_info.pStencilAttachment = &stencil_attachment; |
| begin_rendering_info.layerCount = 1; |
| |
| m_commandBuffer->begin(); |
| m_commandBuffer->BeginRendering(begin_rendering_info); |
| m_commandBuffer->EndRendering(); |
| m_commandBuffer->end(); |
| } |
| |
| TEST_F(VkPositiveLayerTest, DynamicRenderingFragmentDensityMapSubsampledBit) { |
| TEST_DESCRIPTION("Test creating an image with subsampled bit."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME); |
| |
| ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor)); |
| |
| if (DeviceValidationVersion() < VK_API_VERSION_1_1) { |
| GTEST_SKIP() << "At least Vulkan version 1.1 is required"; |
| } |
| |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| |
| auto dynamic_rendering_features = LvlInitStruct<VkPhysicalDeviceDynamicRenderingFeaturesKHR>(); |
| auto features2 = GetPhysicalDeviceFeatures2(dynamic_rendering_features); |
| if (!dynamic_rendering_features.dynamicRendering) { |
| printf("%s Test requires (unsupported) dynamicRendering , skipping\n", kSkipPrefix); |
| return; |
| } |
| |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); |
| |
| VkImageCreateInfo image_ci = LvlInitStruct<VkImageCreateInfo>(); |
| image_ci.flags = VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT; |
| image_ci.imageType = VK_IMAGE_TYPE_2D; |
| image_ci.format = VK_FORMAT_R8G8B8A8_UINT; |
| image_ci.extent = {32, 32, 1}; |
| image_ci.mipLevels = 1; |
| image_ci.arrayLayers = 1; |
| image_ci.samples = VK_SAMPLE_COUNT_1_BIT; |
| image_ci.tiling = VK_IMAGE_TILING_OPTIMAL; |
| image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| |
| VkImageObj image(m_device); |
| image.Init(image_ci); |
| VkImageView image_view = image.targetView(VK_FORMAT_R8G8B8A8_UINT, VK_IMAGE_ASPECT_COLOR_BIT); |
| |
| image_ci.flags = 0; |
| image_ci.usage = VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT; |
| |
| VkImageObj fdm_image(m_device); |
| fdm_image.Init(image_ci); |
| VkImageView fdm_image_view = fdm_image.targetView(VK_FORMAT_R8G8B8A8_UINT); |
| |
| VkRenderingAttachmentInfoKHR color_attachment = LvlInitStruct<VkRenderingAttachmentInfoKHR>(); |
| color_attachment.imageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| color_attachment.imageView = image_view; |
| |
| VkRenderingInfoKHR begin_rendering_info = LvlInitStruct<VkRenderingInfoKHR>(); |
| begin_rendering_info.colorAttachmentCount = 1; |
| begin_rendering_info.pColorAttachments = &color_attachment; |
| |
| auto fragment_density_map = LvlInitStruct<VkRenderingFragmentDensityMapAttachmentInfoEXT>(); |
| fragment_density_map.imageView = fdm_image_view; |
| fragment_density_map.imageLayout = VK_IMAGE_LAYOUT_GENERAL; |
| begin_rendering_info.pNext = &fragment_density_map; |
| begin_rendering_info.layerCount = 1; |
| |
| m_commandBuffer->begin(); |
| m_commandBuffer->BeginRendering(begin_rendering_info); |
| } |
| |
| TEST_F(VkPositiveLayerTest, DynamicRenderingSuspendResumeDraw) { |
| TEST_DESCRIPTION("Resume and suspend at vkCmdBeginRendering time"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| |
| ASSERT_NO_FATAL_FAILURE(InitFramework()); |
| |
| if (!AreRequiredExtensionsEnabled()) { |
| GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported"; |
| } |
| |
| if (DeviceValidationVersion() < VK_API_VERSION_1_1) { |
| GTEST_SKIP() << "At least Vulkan version 1.1 is required"; |
| } |
| |
| auto dynamic_rendering_features = LvlInitStruct<VkPhysicalDeviceDynamicRenderingFeaturesKHR>(); |
| auto features2 = GetPhysicalDeviceFeatures2(dynamic_rendering_features); |
| if (!dynamic_rendering_features.dynamicRendering) { |
| GTEST_SKIP() << "Test requires (unsupported) dynamicRendering , skipping"; |
| } |
| |
| ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2)); |
| |
| char const* fsSource = R"glsl( |
| #version 450 |
| layout(location=0) out vec4 color; |
| void main() { |
| color = vec4(1.0f); |
| } |
| )glsl"; |
| |
| VkShaderObj vs(this, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(this, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| VkPipelineObj pipe(m_device); |
| pipe.AddShader(&vs); |
| pipe.AddShader(&fs); |
| pipe.AddDefaultColorAttachment(); |
| |
| VkDescriptorSetLayoutBinding dslb = {0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; |
| const VkDescriptorSetLayoutObj dsl(m_device, {dslb}); |
| const VkPipelineLayoutObj pl(m_device, {&dsl}); |
| |
| VkFormat color_formats = {VK_FORMAT_R8G8B8A8_UNORM}; |
| auto pipeline_rendering_info = LvlInitStruct<VkPipelineRenderingCreateInfoKHR>(); |
| pipeline_rendering_info.colorAttachmentCount = 1; |
| pipeline_rendering_info.pColorAttachmentFormats = &color_formats; |
| |
| auto create_info = LvlInitStruct<VkGraphicsPipelineCreateInfo>(); |
| pipe.InitGraphicsPipelineCreateInfo(&create_info); |
| create_info.pNext = &pipeline_rendering_info; |
| |
| pipe.CreateVKPipeline(pl.handle(), VK_NULL_HANDLE, &create_info); |
| |
| VkViewport viewport = {0, 0, 16, 16, 0, 1}; |
| VkRect2D scissor = {{0, 0}, {16, 16}}; |
| |
| VkRenderingAttachmentInfoKHR color_attachment = LvlInitStruct<VkRenderingAttachmentInfoKHR>(); |
| color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| |
| VkRenderingInfoKHR begin_rendering_info = LvlInitStruct<VkRenderingInfoKHR>(); |
| begin_rendering_info.flags = VK_RENDERING_SUSPENDING_BIT_KHR; |
| begin_rendering_info.colorAttachmentCount = 1; |
| begin_rendering_info.pColorAttachments = &color_attachment; |
| begin_rendering_info.layerCount = 1; |
| |
| VkCommandBufferObj cb1(m_device, m_commandPool); |
| VkCommandBufferObj cb2(m_device, m_commandPool); |
| |
| m_commandBuffer->begin(); |
| m_commandBuffer->BeginRendering(begin_rendering_info); |
| vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); |
| vk::CmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport); |
| vk::CmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor); |
| vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); |
| m_commandBuffer->EndRendering(); |
| m_commandBuffer->end(); |
| |
| begin_rendering_info.flags = VK_RENDERING_RESUMING_BIT_KHR | VK_RENDERING_SUSPENDING_BIT_KHR; |
| cb1.begin(); |
| cb1.BeginRendering(begin_rendering_info); |
| vk::CmdBindPipeline(cb1.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); |
| vk::CmdSetViewport(cb1.handle(), 0, 1, &viewport); |
| vk::CmdSetScissor(cb1.handle(), 0, 1, &scissor); |
| vk::CmdDraw(cb1.handle(), 3, 1, 0, 0); |
| cb1.EndRendering(); |
| cb1.end(); |
| |
| begin_rendering_info.flags = VK_RENDERING_RESUMING_BIT_KHR; |
| cb2.begin(); |
| cb2.BeginRendering(begin_rendering_info); |
| vk::CmdBindPipeline(cb2.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); |
| vk::CmdSetViewport(cb2.handle(), 0, 1, &viewport); |
| vk::CmdSetScissor(cb2.handle(), 0, 1, &scissor); |
| vk::CmdDraw(cb2.handle(), 3, 1, 0, 0); |
| cb2.EndRendering(); |
| cb2.end(); |
| |
| std::array<VkCommandBuffer, 3> cbs = {m_commandBuffer->handle(), cb1.handle(), cb2.handle()}; |
| auto submit = LvlInitStruct<VkSubmitInfo>(); |
| submit.commandBufferCount = static_cast<uint32_t>(cbs.size()); |
| submit.pCommandBuffers = cbs.data(); |
| vk::QueueSubmit(m_device->m_queue, 1, &submit, VK_NULL_HANDLE); |
| |
| vk::QueueWaitIdle(m_device->m_queue); |
| } |