blob: cca4c3be2ea6596118bceecf3ff1af944c8a9593 [file] [log] [blame]
/*
* Copyright (c) 2023 Valve Corporation
* Copyright (c) 2023 LunarG, 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../framework/layer_validation_tests.h"
TEST_F(PositiveSubpass, SubpassImageBarrier) {
TEST_DESCRIPTION("Subpass with image barrier (self-dependency)");
SetTargetApiVersion(VK_API_VERSION_1_3);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceSynchronization2Features sync2_features = vku::InitStructHelper();
GetPhysicalDeviceFeatures2(sync2_features);
RETURN_IF_SKIP(InitState(nullptr, &sync2_features, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
const VkAttachmentDescription attachment = {0,
VK_FORMAT_R8G8B8A8_UNORM,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL};
const VkSubpassDependency dependency = {0,
0,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_DEPENDENCY_BY_REGION_BIT};
const VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_GENERAL};
const VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 1, &ref, nullptr, nullptr, 0, nullptr};
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.attachmentCount = 1;
rpci.pAttachments = &attachment;
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.dependencyCount = 1;
rpci.pDependencies = &dependency;
vkt::RenderPass render_pass(*m_device, rpci);
VkImageObj image(m_device);
image.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL);
VkImageView image_view = image.targetView(VK_FORMAT_R8G8B8A8_UNORM);
VkFramebufferCreateInfo fbci = vku::InitStructHelper();
fbci.renderPass = render_pass;
fbci.attachmentCount = 1;
fbci.pAttachments = &image_view;
fbci.width = 32;
fbci.height = 32;
fbci.layers = 1;
vkt::Framebuffer framebuffer(*m_device, fbci);
VkRenderPassBeginInfo render_pass_begin = vku::InitStructHelper();
render_pass_begin.renderPass = render_pass;
render_pass_begin.framebuffer = framebuffer;
render_pass_begin.renderArea = VkRect2D{{0, 0}, {32, 32}};
// VkImageMemoryBarrier
VkImageMemoryBarrier barrier = vku::InitStructHelper();
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.image = image;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.layerCount = 1;
barrier.subresourceRange.levelCount = 1;
// VkDependencyInfo with VkImageMemoryBarrier2
const safe_VkImageMemoryBarrier2 safe_barrier2 = ConvertVkImageMemoryBarrierToV2(
barrier, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependency_info.imageMemoryBarrierCount = 1;
dependency_info.pImageMemoryBarriers = safe_barrier2.ptr();
// Test vkCmdPipelineBarrier subpass barrier
m_commandBuffer->begin();
vk::CmdBeginRenderPass(*m_commandBuffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
vk::CmdPipelineBarrier(*m_commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1,
&barrier);
vk::CmdEndRenderPass(*m_commandBuffer);
m_commandBuffer->end();
// Test vkCmdPipelineBarrier2 subpass barrier
m_commandBuffer->begin();
vk::CmdBeginRenderPass(*m_commandBuffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
vk::CmdPipelineBarrier2(*m_commandBuffer, &dependency_info);
vk::CmdEndRenderPass(*m_commandBuffer);
m_commandBuffer->end();
}
TEST_F(PositiveSubpass, SubpassWithEventWait) {
TEST_DESCRIPTION("Subpass waits for the event set outside of this subpass");
SetTargetApiVersion(VK_API_VERSION_1_3);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceSynchronization2Features sync2_features = vku::InitStructHelper();
GetPhysicalDeviceFeatures2(sync2_features);
RETURN_IF_SKIP(InitState(nullptr, &sync2_features, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
const VkAttachmentDescription attachment = {0,
VK_FORMAT_R8G8B8A8_UNORM,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL};
const VkSubpassDependency dependency = {VK_SUBPASS_EXTERNAL,
0,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
0};
const VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_GENERAL};
const VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 1, &ref, nullptr, nullptr, 0, nullptr};
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.attachmentCount = 1;
rpci.pAttachments = &attachment;
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.dependencyCount = 1;
rpci.pDependencies = &dependency;
vkt::RenderPass render_pass(*m_device, rpci);
VkImageObj image(m_device);
image.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL);
VkImageView image_view = image.targetView(VK_FORMAT_R8G8B8A8_UNORM);
VkFramebufferCreateInfo fbci = vku::InitStructHelper();
fbci.renderPass = render_pass;
fbci.attachmentCount = 1;
fbci.pAttachments = &image_view;
fbci.width = 32;
fbci.height = 32;
fbci.layers = 1;
vkt::Framebuffer framebuffer(*m_device, fbci);
VkRenderPassBeginInfo render_pass_begin = vku::InitStructHelper();
render_pass_begin.renderPass = render_pass;
render_pass_begin.framebuffer = framebuffer;
render_pass_begin.renderArea = VkRect2D{{0, 0}, {32, 32}};
// VkImageMemoryBarrier
VkImageMemoryBarrier barrier = vku::InitStructHelper();
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.image = image;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.layerCount = 1;
barrier.subresourceRange.levelCount = 1;
// VkDependencyInfo with VkImageMemoryBarrier2
const safe_VkImageMemoryBarrier2 safe_barrier2 = ConvertVkImageMemoryBarrierToV2(
barrier, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.dependencyFlags = 0;
dependency_info.imageMemoryBarrierCount = 1;
dependency_info.pImageMemoryBarriers = safe_barrier2.ptr();
// vkCmdWaitEvents inside render pass
{
vkt::Event event(*m_device);
m_commandBuffer->begin();
vk::CmdSetEvent(*m_commandBuffer, event, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
vk::CmdBeginRenderPass(*m_commandBuffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
vk::CmdWaitEvents(*m_commandBuffer, 1, &event.handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, nullptr, 0, nullptr, 1, &barrier);
vk::CmdEndRenderPass(*m_commandBuffer);
m_commandBuffer->end();
}
// vkCmdWaitEvents2 inside render pass.
// It's also a regression test for https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/4258
{
vkt::Event event2(*m_device);
m_commandBuffer->begin();
vk::CmdSetEvent2(*m_commandBuffer, event2, &dependency_info);
vk::CmdBeginRenderPass(*m_commandBuffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
vk::CmdWaitEvents2(*m_commandBuffer, 1, &event2.handle(), &dependency_info);
vk::CmdEndRenderPass(*m_commandBuffer);
m_commandBuffer->end();
}
}