blob: 1d5aa8690a573702cbc28dcbd475fc40def6b996 [file] [log] [blame]
/*
* Copyright (c) 2015-2025 The Khronos Group Inc.
* Copyright (c) 2015-2025 Valve Corporation
* Copyright (c) 2015-2025 LunarG, Inc.
* Copyright (c) 2015-2025 Google, Inc.
* Modifications Copyright (C) 2020-2024 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
*/
#include <gtest/gtest.h>
#include <thread>
#include "utils/cast_utils.h"
#include "../framework/external_memory_sync.h"
#include "../framework/layer_validation_tests.h"
#include "../framework/render_pass_helper.h"
#include "../framework/sync_helper.h"
class NegativeSyncObject : public SyncObjectTest {};
TEST_F(NegativeSyncObject, ImageBarrierSubpassConflicts) {
TEST_DESCRIPTION("Add a pipeline barrier within a subpass that has conflicting state");
RETURN_IF_SKIP(Init());
// A renderpass with a single subpass that declared a self-dependency
VkAttachmentDescription attach[] = {
{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_COLOR_ATTACHMENT_OPTIMAL},
};
VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
VkSubpassDescription subpasses[] = {
{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr},
};
VkSubpassDependency dep = {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};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, attach, 1, subpasses, 1, &dep};
vkt::RenderPass rp(*m_device, rpci);
rpci.dependencyCount = 0;
rpci.pDependencies = nullptr;
vkt::RenderPass rp_noselfdep(*m_device, rpci);
vkt::Image image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView imageView = image.CreateView();
vkt::Framebuffer fb(*m_device, rp, 1, &imageView.handle());
vkt::Framebuffer fb_noselfdep(*m_device, rp_noselfdep, 1, &imageView.handle());
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp_noselfdep, fb_noselfdep, 32, 32);
VkMemoryBarrier mem_barrier = vku::InitStructHelper();
mem_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
mem_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-None-07889");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 1,
&mem_barrier, 0, nullptr, 0, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.FullMemoryBarrier();
m_command_buffer.BeginRenderPass(rp, fb, 32, 32);
VkImageMemoryBarrier img_barrier = vku::InitStructHelper();
img_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
img_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
img_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
img_barrier.image = image;
img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
img_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
// Mis-match src stage mask
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-None-07889");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier);
m_errorMonitor->VerifyFound();
// // Now mis-match dst stage mask
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-None-07889");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier);
m_errorMonitor->VerifyFound();
// Set srcQueueFamilyIndex to a different value than dstQueueFamilyIndex
img_barrier.srcQueueFamilyIndex = 0;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-srcQueueFamilyIndex-01182");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1,
&img_barrier);
m_errorMonitor->VerifyFound();
img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
// Mis-match mem barrier src access mask
mem_barrier = vku::InitStructHelper();
mem_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
mem_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-None-07889");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 1, &mem_barrier, 0, nullptr,
0, nullptr);
m_errorMonitor->VerifyFound();
// Mis-match mem barrier dst access mask. Also set srcAccessMask to 0 which should not cause an error
mem_barrier.srcAccessMask = 0;
mem_barrier.dstAccessMask = VK_ACCESS_HOST_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-None-07889");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 1, &mem_barrier, 0, nullptr,
0, nullptr);
m_errorMonitor->VerifyFound();
// Mis-match image barrier src access mask
img_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-None-07889");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1,
&img_barrier);
m_errorMonitor->VerifyFound();
// Mis-match image barrier dst access mask
img_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
img_barrier.dstAccessMask = VK_ACCESS_HOST_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-None-07889");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1,
&img_barrier);
m_errorMonitor->VerifyFound();
// Mis-match dependencyFlags
img_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-None-07889");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0 /* wrong */, 0, nullptr, 0, nullptr, 1, &img_barrier);
m_errorMonitor->VerifyFound();
// Send non-zero bufferMemoryBarrierCount
// Construct a valid BufferMemoryBarrier to avoid any parameter errors
// First we need a valid buffer to reference
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VkBufferMemoryBarrier bmb = vku::InitStructHelper();
bmb.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
bmb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
bmb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bmb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bmb.buffer = buffer;
bmb.offset = 0;
bmb.size = VK_WHOLE_SIZE;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-bufferMemoryBarrierCount-01178");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1, &bmb, 0,
nullptr);
m_errorMonitor->VerifyFound();
// Add image barrier w/ image handle that's not in framebuffer
vkt::Image lone_image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
img_barrier.image = lone_image;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-image-04073");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1,
&img_barrier);
m_errorMonitor->VerifyFound();
// Have image barrier with layout that does not match layout specified in attachment reference
img_barrier.image = image;
img_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-oldLayout-10758");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1,
&img_barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
}
TEST_F(NegativeSyncObject, BufferMemoryBarrierNoBuffer) {
// Try to add a buffer memory barrier with no buffer.
m_errorMonitor->SetDesiredError("UNASSIGNED-GeneralParameterError-RequiredHandle");
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
VkBufferMemoryBarrier buf_barrier = vku::InitStructHelper();
buf_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
buf_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
buf_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
buf_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
buf_barrier.buffer = VK_NULL_HANDLE;
buf_barrier.offset = 0;
buf_barrier.size = VK_WHOLE_SIZE;
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 1,
&buf_barrier, 0, nullptr);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, Barriers) {
TEST_DESCRIPTION("A variety of ways to get VK_INVALID_BARRIER ");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::separateDepthStencilLayouts);
// Make sure extensions for multi-planar and separate depth stencil images are enabled if possible
AddOptionalExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
AddOptionalExtensions(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_VIDEO_ENCODE_QUANTIZATION_MAP_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework(&kDisableMessageLimit));
RETURN_IF_SKIP(InitState());
const bool mp_extensions = IsExtensionsEnabled(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME);
const bool external_memory = IsExtensionsEnabled(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
const bool maintenance2 = IsExtensionsEnabled(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
const bool feedback_loop_layout = IsExtensionsEnabled(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME);
const bool video_decode_queue = IsExtensionsEnabled(VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
const bool video_encode_queue = IsExtensionsEnabled(VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME);
const bool video_encode_quantization_map = IsExtensionsEnabled(VK_KHR_VIDEO_ENCODE_QUANTIZATION_MAP_EXTENSION_NAME);
vkt::Image color_image(*m_device, m_width, m_height, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
auto color_view = color_image.CreateView();
// Just using all framebuffer-space pipeline stages in order to get a reasonably large
// set of bits that can be used for both src & dst
VkPipelineStageFlags stage_flags = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
// Add all of the gfx mem access bits that correlate to the fb-space pipeline stages
VkAccessFlags access_flags = VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT |
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL});
rp.AddColorAttachment(0);
// Add a token self-dependency for this test to avoid unexpected errors
rp.AddSubpassDependency(stage_flags, stage_flags, access_flags, access_flags);
rp.CreateRenderPass();
vkt::Framebuffer fb(*m_device, rp, 1, &color_view.handle());
auto depth_format = FindSupportedDepthStencilFormat(Gpu());
const uint32_t submit_family = m_device->graphics_queue_node_index_;
const uint32_t invalid = static_cast<uint32_t>(m_device->Physical().queue_properties_.size());
const uint32_t other_family = submit_family != 0 ? 0 : 1;
const bool only_one_family = (invalid == 1) || (m_device->Physical().queue_properties_[other_family].queueCount == 0) ||
((m_device->Physical().queue_properties_[other_family].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0);
std::vector<uint32_t> qf_indices{{submit_family, other_family}};
if (only_one_family) {
qf_indices.resize(1);
}
BarrierQueueFamilyTestHelper::Context test_context(this, qf_indices);
// Use image unbound to memory in barrier
// Use buffer unbound to memory in barrier
BarrierQueueFamilyTestHelper conc_test(&test_context);
conc_test.Init(nullptr, false, false);
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
conc_test(" used with no memory bound. Memory should be bound by calling vkBindImageMemory()",
" used with no memory bound. Memory should be bound by calling vkBindBufferMemory()");
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
conc_test.buffer_barrier_.buffer = buffer;
vkt::Image image(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
image.SetLayout(VK_IMAGE_LAYOUT_GENERAL);
conc_test.image_barrier_.image = image;
// New layout can't be UNDEFINED
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_UNDEFINED;
conc_test("VUID-VkImageMemoryBarrier-newLayout-01198", "");
// Transition image to color attachment optimal
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
conc_test("");
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp, fb);
// Can't send buffer memory barrier during a render pass
m_command_buffer.EndRenderPass();
// Duplicate barriers that change layout
VkImageMemoryBarrier img_barrier = vku::InitStructHelper();
img_barrier.image = image;
img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
img_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
img_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
img_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
VkImageMemoryBarrier img_barriers[2] = {img_barrier, img_barrier};
// Transitions from UNDEFINED are valid, even if duplicated
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 2, img_barriers);
// Duplication of layout transitions (not from undefined) are not valid
img_barriers[0].oldLayout = VK_IMAGE_LAYOUT_GENERAL;
img_barriers[0].newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
img_barriers[1].oldLayout = img_barriers[0].oldLayout;
img_barriers[1].newLayout = img_barriers[0].newLayout;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-oldLayout-01197");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 2, img_barriers);
m_errorMonitor->VerifyFound();
if (!external_memory) {
printf("External memory extension not supported, skipping external queue family subcase\n");
} else {
// Transitions to and from EXTERNAL within the same command buffer are valid, if pointless.
img_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
img_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
img_barrier.srcQueueFamilyIndex = submit_family;
img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
img_barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
img_barrier.dstAccessMask = 0;
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0,
nullptr, 0, nullptr, 1, &img_barrier);
img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
img_barrier.dstQueueFamilyIndex = submit_family;
img_barrier.srcAccessMask = 0;
img_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0,
nullptr, 0, nullptr, 1, &img_barrier);
}
// Exceed the buffer size
conc_test.buffer_barrier_.offset = conc_test.buffer_.CreateInfo().size + 1;
conc_test("", "VUID-VkBufferMemoryBarrier-offset-01187");
conc_test.buffer_barrier_.offset = 0;
conc_test.buffer_barrier_.size = conc_test.buffer_.CreateInfo().size + 1;
// Size greater than total size
conc_test("", "VUID-VkBufferMemoryBarrier-size-01189");
conc_test.buffer_barrier_.size = 0;
// Size is zero
conc_test("", "VUID-VkBufferMemoryBarrier-size-01188");
conc_test.buffer_barrier_.size = VK_WHOLE_SIZE;
// Now exercise barrier aspect bit errors, first DS
vkt::Image ds_image(*m_device, 128, 128, depth_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = ds_image;
// Not having DEPTH or STENCIL set is an error
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-09601");
conc_test("VUID-VkImageMemoryBarrier-image-03319");
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
conc_test("VUID-VkImageMemoryBarrier-aspectMask-08702");
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
conc_test("VUID-VkImageMemoryBarrier-aspectMask-08703");
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
// Having anything other than DEPTH and STENCIL is an error
conc_test.image_barrier_.subresourceRange.aspectMask =
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_COLOR_BIT;
conc_test("VUID-VkImageMemoryBarrier-subresourceRange-09601");
// Now test depth-only
VkFormatProperties format_props;
vk::GetPhysicalDeviceFormatProperties(m_device->Physical(), VK_FORMAT_D16_UNORM, &format_props);
if (format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
vkt::Image d_image(*m_device, 128, 128, VK_FORMAT_D16_UNORM, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = d_image;
// DEPTH bit must be set
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT;
conc_test("VUID-VkImageMemoryBarrier-subresourceRange-09601");
// No bits other than DEPTH may be set
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_COLOR_BIT;
conc_test("VUID-VkImageMemoryBarrier-subresourceRange-09601");
}
// Now test stencil-only
vk::GetPhysicalDeviceFormatProperties(m_device->Physical(), VK_FORMAT_S8_UINT, &format_props);
if (format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
vkt::Image s_image(*m_device, 128, 128, VK_FORMAT_S8_UINT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = s_image;
// Use of COLOR aspect on depth image is error
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
// must have the VK_IMAGE_ASPECT_STENCIL_BIT set
conc_test("VUID-VkImageMemoryBarrier-subresourceRange-09601");
}
// Finally test color
vkt::Image c_image(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = c_image;
// COLOR bit must be set
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-09601");
conc_test("VUID-VkImageMemoryBarrier-image-09241");
// No bits other than COLOR may be set
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-09601");
conc_test("VUID-VkImageMemoryBarrier-image-09241");
// Test multip-planar image
if (mp_extensions) {
VkFormatProperties format_properties;
VkFormat mp_format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
vk::GetPhysicalDeviceFormatProperties(m_device->Physical(), mp_format, &format_properties);
constexpr VkImageAspectFlags disjoint_sampled = VK_FORMAT_FEATURE_DISJOINT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
if (disjoint_sampled == (format_properties.optimalTilingFeatures & disjoint_sampled)) {
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
image_create_info.extent = {64, 64, 1};
image_create_info.mipLevels = 1;
image_create_info.arrayLayers = 1;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
image_create_info.flags = VK_IMAGE_CREATE_DISJOINT_BIT;
VkImage mp_image;
VkDeviceMemory plane_0_memory;
VkDeviceMemory plane_1_memory;
ASSERT_EQ(VK_SUCCESS, vk::CreateImage(device(), &image_create_info, NULL, &mp_image));
VkImagePlaneMemoryRequirementsInfo image_plane_req = vku::InitStructHelper();
image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT;
VkImageMemoryRequirementsInfo2 mem_req_info2 = vku::InitStructHelper(&image_plane_req);
mem_req_info2.image = mp_image;
VkMemoryRequirements2 mem_req2 = vku::InitStructHelper();
vk::GetImageMemoryRequirements2KHR(device(), &mem_req_info2, &mem_req2);
// Find a valid memory type index to memory to be allocated from
VkMemoryAllocateInfo alloc_info = vku::InitStructHelper();
alloc_info.allocationSize = mem_req2.memoryRequirements.size;
ASSERT_TRUE(m_device->Physical().SetMemoryType(mem_req2.memoryRequirements.memoryTypeBits, &alloc_info, 0));
ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &alloc_info, NULL, &plane_0_memory));
image_plane_req.planeAspect = VK_IMAGE_ASPECT_PLANE_1_BIT;
vk::GetImageMemoryRequirements2KHR(device(), &mem_req_info2, &mem_req2);
alloc_info.allocationSize = mem_req2.memoryRequirements.size;
ASSERT_TRUE(m_device->Physical().SetMemoryType(mem_req2.memoryRequirements.memoryTypeBits, &alloc_info, 0));
ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &alloc_info, NULL, &plane_1_memory));
VkBindImagePlaneMemoryInfo plane_0_memory_info = vku::InitStructHelper();
plane_0_memory_info.planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT;
VkBindImagePlaneMemoryInfo plane_1_memory_info = vku::InitStructHelper();
plane_1_memory_info.planeAspect = VK_IMAGE_ASPECT_PLANE_1_BIT;
VkBindImageMemoryInfo bind_image_info[2];
bind_image_info[0] = vku::InitStructHelper(&plane_0_memory_info);
bind_image_info[0].image = mp_image;
bind_image_info[0].memory = plane_0_memory;
bind_image_info[0].memoryOffset = 0;
bind_image_info[1] = bind_image_info[0];
bind_image_info[1].pNext = &plane_1_memory_info;
bind_image_info[1].memory = plane_1_memory;
vk::BindImageMemory2KHR(device(), 2, bind_image_info);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = mp_image;
// Test valid usage first
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT;
conc_test("", "", VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, true);
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-09601");
conc_test("VUID-VkImageMemoryBarrier-image-01672");
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_PLANE_2_BIT;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-09601");
conc_test("VUID-VkImageMemoryBarrier-image-01672");
vk::FreeMemory(device(), plane_0_memory, NULL);
vk::FreeMemory(device(), plane_1_memory, NULL);
vk::DestroyImage(device(), mp_image, nullptr);
}
}
// A barrier's new and old VkImageLayout must be compatible with an image's VkImageUsageFlags.
{
vkt::Image img_color(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::Image img_ds(*m_device, 128, 128, depth_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
vkt::Image img_xfer_src(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
vkt::Image img_xfer_dst(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT);
vkt::Image img_sampled(*m_device, 32, 32, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
vkt::Image img_input(*m_device, 128, 128, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
struct BadBufferTest {
vkt::Image &image_obj;
VkImageLayout bad_layout;
std::string msg_code;
};
// clang-format off
std::vector<BadBufferTest> bad_buffer_layouts = {
// images _without_ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
{img_ds, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01208"},
{img_xfer_src, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01208"},
{img_xfer_dst, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01208"},
{img_sampled, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01208"},
{img_input, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01208"},
// images _without_ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
{img_color, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01209"},
{img_xfer_src, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01209"},
{img_xfer_dst, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01209"},
{img_sampled, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01209"},
{img_input, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01209"},
{img_color, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01210"},
{img_xfer_src, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01210"},
{img_xfer_dst, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01210"},
{img_sampled, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01210"},
{img_input, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01210"},
// images _without_ VK_IMAGE_USAGE_SAMPLED_BIT or VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
{img_color, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01211"},
{img_ds, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01211"},
{img_xfer_src, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01211"},
{img_xfer_dst, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01211"},
// images _without_ VK_IMAGE_USAGE_TRANSFER_SRC_BIT
{img_color, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01212"},
{img_ds, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01212"},
{img_xfer_dst, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01212"},
{img_sampled, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01212"},
{img_input, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01212"},
// images _without_ VK_IMAGE_USAGE_TRANSFER_DST_BIT
{img_color, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01213"},
{img_ds, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01213"},
{img_xfer_src, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01213"},
{img_sampled, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01213"},
{img_input, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01213"},
// images _without_ VK_KHR_maintenance2 added layouts
{img_color, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01658"},
{img_xfer_src, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01658"},
{img_sampled, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01658"},
{img_input, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01658"},
{img_color, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01659"},
{img_xfer_src, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01659"},
{img_sampled, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01659"},
{img_input, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier-oldLayout-01659"},
};
if (video_decode_queue) {
// images _without_ VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07120"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07120"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07120"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07120"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07120"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07120"});
// // images _without_ VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07121"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07121"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07121"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07121"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07121"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07121"});
// // images _without_ VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07122"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07122"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07122"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07122"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07122"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07122"});
}
if (video_encode_queue) {
// images _without_ VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07123"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07123"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07123"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07123"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07123"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07123"});
// images _without_ VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07124"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07124"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07124"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07124"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07124"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07124"});
// images _without_ VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07125"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07125"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07125"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07125"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07125"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, "VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07125"});
}
if (video_encode_quantization_map) {
// images _without_ VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR,"VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-10287"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR,"VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-10287"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR,"VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-10287"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR,"VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-10287"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR,"VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-10287"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR,"VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-10287"});
}
// clang-format on
for (const auto &test : bad_buffer_layouts) {
const VkImageLayout bad_layout = test.bad_layout;
// Skip layouts that require maintenance2 support
if ((maintenance2 == false) && ((bad_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) ||
(bad_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL))) {
continue;
}
conc_test.image_barrier_.image = test.image_obj;
const VkImageUsageFlags usage = test.image_obj.Usage();
conc_test.image_barrier_.subresourceRange.aspectMask = (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
? (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)
: VK_IMAGE_ASPECT_COLOR_BIT;
conc_test.image_barrier_.oldLayout = bad_layout;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test(test.msg_code);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.newLayout = bad_layout;
conc_test(test.msg_code);
}
if (feedback_loop_layout) {
conc_test.image_barrier_.image = img_color;
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test("VUID-VkImageMemoryBarrier-srcQueueFamilyIndex-07006");
}
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = image;
}
// Attempt barrier where srcAccessMask is not supported by srcStageMask
// Have bit that's supported (transfer write), and another that isn't to verify multi-bit validation
conc_test.buffer_barrier_.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
conc_test.buffer_barrier_.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
conc_test.buffer_barrier_.offset = 0;
conc_test.buffer_barrier_.size = VK_WHOLE_SIZE;
conc_test("", "VUID-vkCmdPipelineBarrier-pBufferMemoryBarriers-02817");
// Attempt barrier where dstAccessMask is not supported by dstStageMask
conc_test.buffer_barrier_.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
conc_test.buffer_barrier_.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
conc_test("", "VUID-vkCmdPipelineBarrier-pBufferMemoryBarriers-02818");
// Attempt to mismatch barriers/waitEvents calls with incompatible queues
// Create command pool with incompatible queueflags
const std::vector<VkQueueFamilyProperties> queue_props = m_device->Physical().queue_properties_;
const std::optional<uint32_t> queue_family_index = m_device->ComputeOnlyQueueFamily();
if (!queue_family_index) {
GTEST_SKIP() << "No compute-only queue found; skipped";
}
VkBufferMemoryBarrier buf_barrier = vku::InitStructHelper();
buf_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
buf_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
buf_barrier.buffer = buffer;
buf_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
buf_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
buf_barrier.offset = 0;
buf_barrier.size = VK_WHOLE_SIZE;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-srcStageMask-06461");
vkt::CommandPool command_pool(*m_device, queue_family_index.value(), VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
vkt::CommandBuffer bad_command_buffer(*m_device, command_pool);
bad_command_buffer.Begin();
// Set two bits that should both be supported as a bonus positive check
buf_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
buf_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
vk::CmdPipelineBarrier(bad_command_buffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1, &buf_barrier, 0, nullptr);
m_errorMonitor->VerifyFound();
// Check for error for trying to wait on pipeline stage not supported by this queue. Specifically since our queue is not a
// compute queue, vk::CmdWaitEvents cannot have it's source stage mask be VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents-srcStageMask-06459");
vkt::Event event(*m_device);
vk::CmdWaitEvents(bad_command_buffer, 1, &event.handle(), /*source stage mask*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, nullptr, 0, nullptr, 0, nullptr);
m_errorMonitor->VerifyFound();
bad_command_buffer.End();
}
TEST_F(NegativeSyncObject, Sync2Barriers) {
TEST_DESCRIPTION("Synchronization2 test for invalid Memory Barriers");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddOptionalExtensions(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
AddOptionalExtensions(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_VIDEO_ENCODE_QUANTIZATION_MAP_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework(&kDisableMessageLimit));
RETURN_IF_SKIP(InitState());
const bool maintenance2 = IsExtensionsEnabled(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
const bool feedback_loop_layout = IsExtensionsEnabled(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME);
const bool video_decode_queue = IsExtensionsEnabled(VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
const bool video_encode_queue = IsExtensionsEnabled(VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME);
const bool video_encode_quantization_map = IsExtensionsEnabled(VK_KHR_VIDEO_ENCODE_QUANTIZATION_MAP_EXTENSION_NAME);
auto depth_format = FindSupportedDepthStencilFormat(Gpu());
vkt::Image color_image(*m_device, m_width, m_height, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
auto color_view = color_image.CreateView();
// Just using all framebuffer-space pipeline stages in order to get a reasonably large
// set of bits that can be used for both src & dst
VkPipelineStageFlags stage_flags = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
// Add all of the gfx mem access bits that correlate to the fb-space pipeline stages
VkAccessFlags access_flags = VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT |
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL});
rp.AddColorAttachment(0);
// Add a token self-dependency for this test to avoid unexpected errors
rp.AddSubpassDependency(stage_flags, stage_flags, access_flags, access_flags);
rp.CreateRenderPass();
vkt::Framebuffer fb(*m_device, rp, 1, &color_view.handle());
const uint32_t submit_family = m_device->graphics_queue_node_index_;
const uint32_t invalid = static_cast<uint32_t>(m_device->Physical().queue_properties_.size());
const uint32_t other_family = submit_family != 0 ? 0 : 1;
const bool only_one_family = (invalid == 1) || (m_device->Physical().queue_properties_[other_family].queueCount == 0);
std::vector<uint32_t> qf_indices{{submit_family, other_family}};
if (only_one_family) {
qf_indices.resize(1);
}
Barrier2QueueFamilyTestHelper::Context test_context(this, qf_indices);
// Use image unbound to memory in barrier
// Use buffer unbound to memory in barrier
Barrier2QueueFamilyTestHelper conc_test(&test_context);
conc_test.Init(false, false);
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
conc_test(" used with no memory bound. Memory should be bound by calling vkBindImageMemory()",
" used with no memory bound. Memory should be bound by calling vkBindBufferMemory()");
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
conc_test.buffer_barrier_.buffer = buffer;
vkt::Image image(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
image.SetLayout(VK_IMAGE_LAYOUT_GENERAL);
conc_test.image_barrier_.image = image;
// New layout can't be PREINITIALIZED
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
conc_test("VUID-VkImageMemoryBarrier2-newLayout-01198", "");
// Transition image to color attachment optimal
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
conc_test("");
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp, fb);
// Can't send buffer memory barrier during a render pass
m_command_buffer.EndRenderPass();
// Duplicate barriers that change layout
VkImageMemoryBarrier2 img_barrier = vku::InitStructHelper();
img_barrier.image = image;
img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
img_barrier.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
img_barrier.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
img_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
img_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
img_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
VkImageMemoryBarrier2 img_barriers[2] = {img_barrier, img_barrier};
VkDependencyInfo dep_info = vku::InitStructHelper();
dep_info.imageMemoryBarrierCount = 2;
dep_info.pImageMemoryBarriers = img_barriers;
dep_info.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
// Transitions from UNDEFINED are valid, even if duplicated
m_command_buffer.BarrierKHR(dep_info);
// Duplication of layout transitions (not from undefined) are not valid
img_barriers[0].oldLayout = VK_IMAGE_LAYOUT_GENERAL;
img_barriers[0].newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
img_barriers[1].oldLayout = img_barriers[0].oldLayout;
img_barriers[1].newLayout = img_barriers[0].newLayout;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-oldLayout-01197");
vk::CmdPipelineBarrier2KHR(m_command_buffer, &dep_info);
m_errorMonitor->VerifyFound();
{
// Transitions to and from EXTERNAL within the same command buffer are valid, if pointless.
dep_info.imageMemoryBarrierCount = 1;
dep_info.pImageMemoryBarriers = &img_barrier;
img_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
img_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
img_barrier.srcQueueFamilyIndex = submit_family;
img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
img_barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
img_barrier.dstAccessMask = 0;
img_barrier.srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
img_barrier.dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
vk::CmdPipelineBarrier2KHR(m_command_buffer, &dep_info);
img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
img_barrier.dstQueueFamilyIndex = submit_family;
img_barrier.srcAccessMask = 0;
img_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
vk::CmdPipelineBarrier2KHR(m_command_buffer, &dep_info);
}
// Exceed the buffer size
conc_test.buffer_barrier_.offset = conc_test.buffer_.CreateInfo().size + 1;
conc_test("", "VUID-VkBufferMemoryBarrier2-offset-01187");
conc_test.buffer_barrier_.offset = 0;
conc_test.buffer_barrier_.size = conc_test.buffer_.CreateInfo().size + 1;
// Size greater than total size
conc_test("", "VUID-VkBufferMemoryBarrier2-size-01189");
conc_test.buffer_barrier_.size = 0;
// Size is zero
conc_test("", "VUID-VkBufferMemoryBarrier2-size-01188");
conc_test.buffer_barrier_.size = VK_WHOLE_SIZE;
// Now exercise barrier aspect bit errors, first DS
vkt::Image ds_image(*m_device, 128, 128, depth_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = ds_image;
// Not having DEPTH or STENCIL set is an error
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-subresourceRange-09601");
{
conc_test("VUID-VkImageMemoryBarrier2-image-03320");
// Having only one of depth or stencil set for DS image is an error
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
conc_test("VUID-VkImageMemoryBarrier2-image-03320");
}
// Having anything other than DEPTH and STENCIL is an error
conc_test.image_barrier_.subresourceRange.aspectMask =
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_COLOR_BIT;
conc_test("VUID-VkImageMemoryBarrier2-subresourceRange-09601");
// Now test depth-only
VkFormatProperties format_props;
vk::GetPhysicalDeviceFormatProperties(m_device->Physical(), VK_FORMAT_D16_UNORM, &format_props);
if (format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
vkt::Image d_image(*m_device, 128, 128, VK_FORMAT_D16_UNORM, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = d_image;
// DEPTH bit must be set
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT;
conc_test("depth-only image formats must have the VK_IMAGE_ASPECT_DEPTH_BIT set.");
// No bits other than DEPTH may be set
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_COLOR_BIT;
conc_test("depth-only image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT set.");
}
// Now test stencil-only
vk::GetPhysicalDeviceFormatProperties(m_device->Physical(), VK_FORMAT_S8_UINT, &format_props);
if (format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
vkt::Image s_image(*m_device, 128, 128, VK_FORMAT_S8_UINT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = s_image;
// Use of COLOR aspect on depth image is error
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
conc_test("stencil-only image formats must have the VK_IMAGE_ASPECT_STENCIL_BIT set.");
}
// Finally test color
vkt::Image c_image(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = c_image;
// COLOR bit must be set
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-subresourceRange-09601");
conc_test("VUID-VkImageMemoryBarrier2-image-09241");
// No bits other than COLOR may be set
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-subresourceRange-09601");
conc_test("VUID-VkImageMemoryBarrier2-image-09241");
// A barrier's new and old VkImageLayout must be compatible with an image's VkImageUsageFlags.
{
vkt::Image img_color(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::Image img_ds(*m_device, 128, 128, depth_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
vkt::Image img_xfer_src(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
vkt::Image img_xfer_dst(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT);
vkt::Image img_sampled(*m_device, 32, 32, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
vkt::Image img_input(*m_device, 128, 128, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
struct BadBufferTest {
vkt::Image &image_obj;
VkImageLayout bad_layout;
std::string msg_code;
};
// clang-format off
std::vector<BadBufferTest> bad_buffer_layouts = {
// images _without_ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
{img_ds, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01208"},
{img_xfer_src, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01208"},
{img_xfer_dst, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01208"},
{img_sampled, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01208"},
{img_input, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01208"},
// images _without_ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
{img_color, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01209"},
{img_xfer_src, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01209"},
{img_xfer_dst, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01209"},
{img_sampled, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01209"},
{img_input, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01209"},
{img_color, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01210"},
{img_xfer_src, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01210"},
{img_xfer_dst, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01210"},
{img_sampled, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01210"},
{img_input, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01210"},
// images _without_ VK_IMAGE_USAGE_SAMPLED_BIT or VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
{img_color, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01211"},
{img_ds, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01211"},
{img_xfer_src, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01211"},
{img_xfer_dst, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01211"},
// images _without_ VK_IMAGE_USAGE_TRANSFER_SRC_BIT
{img_color, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01212"},
{img_ds, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01212"},
{img_xfer_dst, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01212"},
{img_sampled, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01212"},
{img_input, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01212"},
// images _without_ VK_IMAGE_USAGE_TRANSFER_DST_BIT
{img_color, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01213"},
{img_ds, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01213"},
{img_xfer_src, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01213"},
{img_sampled, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01213"},
{img_input, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01213"},
// images _without_ VK_KHR_maintenance2 added layouts
{img_color, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01658"},
{img_xfer_src, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01658"},
{img_sampled, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01658"},
{img_input, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01658"},
{img_color, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01659"},
{img_xfer_src, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01659"},
{img_sampled, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01659"},
{img_input, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, "VUID-VkImageMemoryBarrier2-oldLayout-01659"},
};
if (video_decode_queue) {
// images _without_ VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07120"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07120"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07120"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07120"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07120"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07120"});
// images _without_ VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07121"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07121"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07121"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07121"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07121"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07121"});
// images _without_ VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07122"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07122"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07122"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07122"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07122"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07122"});
}
if (video_encode_queue) {
// images _without_ VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07123"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07123"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07123"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07123"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07123"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07123"});
// images _without_ VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07124"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07124"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07124"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07124"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07124"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07124"});
// images _without_ VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07125"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07125"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07125"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07125"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07125"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07125"});
}
if (video_encode_quantization_map) {
// images _without_ VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR
bad_buffer_layouts.push_back({img_color, VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-10287"});
bad_buffer_layouts.push_back({img_ds, VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-10287"});
bad_buffer_layouts.push_back({img_xfer_src, VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-10287"});
bad_buffer_layouts.push_back({img_xfer_dst, VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-10287"});
bad_buffer_layouts.push_back({img_sampled, VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-10287"});
bad_buffer_layouts.push_back({img_input, VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR, "VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-10287"});
}
// clang-format on
for (const auto &test : bad_buffer_layouts) {
const VkImageLayout bad_layout = test.bad_layout;
// Skip layouts that require maintenance2 support
if ((maintenance2 == false) && ((bad_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) ||
(bad_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL))) {
continue;
}
conc_test.image_barrier_.image = test.image_obj;
const VkImageUsageFlags usage = test.image_obj.Usage();
conc_test.image_barrier_.subresourceRange.aspectMask = (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
? (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)
: VK_IMAGE_ASPECT_COLOR_BIT;
conc_test.image_barrier_.oldLayout = bad_layout;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test(test.msg_code);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.newLayout = bad_layout;
conc_test(test.msg_code);
}
if (feedback_loop_layout) {
conc_test.image_barrier_.image = img_color;
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test("VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07006");
}
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = image;
}
// Attempt barrier where srcAccessMask is not supported by srcStageMask
// Have lower-order bit that's supported (shader write), but higher-order bit not supported to verify multi-bit validation
// TODO: synchronization2 has a separate VUID for every access flag. Gotta test them all..
conc_test.buffer_barrier_.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
conc_test.buffer_barrier_.offset = 0;
conc_test.buffer_barrier_.size = VK_WHOLE_SIZE;
conc_test("", "VUID-VkBufferMemoryBarrier2-srcAccessMask-03909");
// Attempt barrier where dstAccessMask is not supported by dstStageMask
conc_test.buffer_barrier_.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
conc_test.buffer_barrier_.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
conc_test("", "VUID-VkBufferMemoryBarrier2-dstAccessMask-03911");
}
TEST_F(NegativeSyncObject, DepthStencilImageNonSeparate) {
TEST_DESCRIPTION("test barrier with depth/stencil image, with wrong aspect mask with not separateDepthStencilLayouts");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
InitRenderTarget();
const uint32_t submit_family = m_device->graphics_queue_node_index_;
const uint32_t invalid = static_cast<uint32_t>(m_device->Physical().queue_properties_.size());
const uint32_t other_family = submit_family != 0 ? 0 : 1;
const bool only_one_family = (invalid == 1) || (m_device->Physical().queue_properties_[other_family].queueCount == 0);
std::vector<uint32_t> qf_indices{{submit_family, other_family}};
if (only_one_family) {
qf_indices.resize(1);
}
BarrierQueueFamilyTestHelper::Context test_context(this, qf_indices);
BarrierQueueFamilyTestHelper conc_test(&test_context);
conc_test.Init(nullptr, false, true);
m_command_buffer.Begin();
const VkFormat depth_format = FindSupportedDepthStencilFormat(Gpu());
vkt::Image ds_image(*m_device, 128, 128, depth_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = ds_image;
// Not having DEPTH or STENCIL set is an error
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-09601");
conc_test("VUID-VkImageMemoryBarrier-image-03320");
// Having only one of depth or stencil set for DS image is an error
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
conc_test("VUID-VkImageMemoryBarrier-image-03320");
}
TEST_F(NegativeSyncObject, DepthStencilImageNonSeparateSync2) {
TEST_DESCRIPTION("test barrier with depth/stencil image, with wrong aspect mask with not separateDepthStencilLayouts");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
InitRenderTarget();
const uint32_t submit_family = m_device->graphics_queue_node_index_;
const uint32_t invalid = static_cast<uint32_t>(m_device->Physical().queue_properties_.size());
const uint32_t other_family = submit_family != 0 ? 0 : 1;
const bool only_one_family = (invalid == 1) || (m_device->Physical().queue_properties_[other_family].queueCount == 0);
std::vector<uint32_t> qf_indices{{submit_family, other_family}};
if (only_one_family) {
qf_indices.resize(1);
}
Barrier2QueueFamilyTestHelper::Context test_context(this, qf_indices);
Barrier2QueueFamilyTestHelper conc_test(&test_context);
conc_test.Init(false, true);
m_command_buffer.Begin();
const VkFormat depth_format = FindSupportedDepthStencilFormat(Gpu());
vkt::Image ds_image(*m_device, 128, 128, depth_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
conc_test.image_barrier_.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
conc_test.image_barrier_.newLayout = VK_IMAGE_LAYOUT_GENERAL;
conc_test.image_barrier_.image = ds_image;
// Not having DEPTH or STENCIL set is an error
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-subresourceRange-09601");
conc_test("VUID-VkImageMemoryBarrier2-image-03320");
// Having only one of depth or stencil set for DS image is an error
conc_test.image_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
conc_test("VUID-VkImageMemoryBarrier2-image-03320");
}
TEST_F(NegativeSyncObject, BarrierQueueFamily) {
TEST_DESCRIPTION("Create and submit barriers with invalid queue families");
SetTargetApiVersion(VK_API_VERSION_1_0);
RETURN_IF_SKIP(Init());
if (DeviceValidationVersion() >= VK_API_VERSION_1_1) {
GTEST_SKIP()
<< "Device has apiVersion greater than 1.0 -- skipping test cases that require external memory to be disabled.";
}
// Find queues of two families
const uint32_t submit_family = m_device->graphics_queue_node_index_;
const uint32_t queue_family_count = static_cast<uint32_t>(m_device->Physical().queue_properties_.size());
const uint32_t other_family = submit_family != 0 ? 0 : 1;
const bool only_one_family = (queue_family_count == 1) ||
(m_device->Physical().queue_properties_[other_family].queueCount == 0) ||
((m_device->Physical().queue_properties_[other_family].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0);
std::vector<uint32_t> qf_indices{{submit_family, other_family}};
if (only_one_family) {
qf_indices.resize(1);
}
BarrierQueueFamilyTestHelper::Context test_context(this, qf_indices);
BarrierQueueFamilyTestHelper excl_test(&test_context);
excl_test.Init(nullptr); // no queue families means *exclusive* sharing mode.
excl_test("VUID-VkImageMemoryBarrier-image-09117", "VUID-VkBufferMemoryBarrier-buffer-09095", VK_QUEUE_FAMILY_IGNORED,
submit_family);
excl_test("VUID-VkImageMemoryBarrier-image-09118", "VUID-VkBufferMemoryBarrier-buffer-09096", submit_family,
VK_QUEUE_FAMILY_IGNORED);
excl_test(submit_family, submit_family);
excl_test(VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED);
}
TEST_F(NegativeSyncObject, BarrierQueueFamilyOneFamily) {
TEST_DESCRIPTION("Create and submit barriers with invalid queue families");
SetTargetApiVersion(VK_API_VERSION_1_0);
RETURN_IF_SKIP(Init());
if (DeviceValidationVersion() >= VK_API_VERSION_1_1) {
GTEST_SKIP()
<< "Device has apiVersion greater than 1.0 -- skipping test cases that require external memory to be disabled.";
}
// Find queues of two families
const uint32_t submit_family = m_device->graphics_queue_node_index_;
const uint32_t queue_family_count = static_cast<uint32_t>(m_device->Physical().queue_properties_.size());
const uint32_t other_family = submit_family != 0 ? 0 : 1;
const bool only_one_family = (queue_family_count == 1) ||
(m_device->Physical().queue_properties_[other_family].queueCount == 0) ||
((m_device->Physical().queue_properties_[other_family].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0);
if (only_one_family) {
GTEST_SKIP() << "Single queue family found";
}
std::vector<uint32_t> qf_indices{{submit_family, other_family}};
BarrierQueueFamilyTestHelper::Context test_context(this, qf_indices);
std::vector<uint32_t> families = {submit_family, other_family};
BarrierQueueFamilyTestHelper conc_test(&test_context);
conc_test.Init(&families);
{
// src
const char *img_vuid = "VUID-VkImageMemoryBarrier-None-09053";
const char *buf_vuid = "VUID-VkBufferMemoryBarrier-None-09050";
conc_test(img_vuid, buf_vuid, submit_family, VK_QUEUE_FAMILY_IGNORED);
}
{
// dst
const char *img_vuid = "VUID-VkImageMemoryBarrier-None-09054";
const char *buf_vuid = "VUID-VkBufferMemoryBarrier-None-09051";
conc_test(img_vuid, buf_vuid, VK_QUEUE_FAMILY_IGNORED, submit_family);
}
{
// neither
const char *img_vuid = "VUID-VkImageMemoryBarrier-None-09053";
const char *buf_vuid = "VUID-VkBufferMemoryBarrier-None-09050";
conc_test(img_vuid, buf_vuid, submit_family, submit_family);
}
conc_test(VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED);
}
TEST_F(NegativeSyncObject, ImageOwnershipTransferQueueMismatch) {
TEST_DESCRIPTION("Neither src nor dst barrier queue family matches submit queue family");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
std::optional<uint32_t> transfer_only_family = m_device->TransferOnlyQueueFamily();
std::optional<uint32_t> compute_only_family = m_device->ComputeOnlyQueueFamily();
if (!transfer_only_family.has_value() || !compute_only_family.has_value()) {
GTEST_SKIP() << "Transfer-only and compute-only queue family is required";
}
vkt::CommandPool release_pool(*m_device, transfer_only_family.value());
vkt::CommandBuffer release_cb(*m_device, release_pool);
vkt::CommandBuffer acquire_cb(*m_device, m_command_pool);
const VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
vkt::Image image(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, usage);
// Release image
VkImageMemoryBarrier2 release_barrier = vku::InitStructHelper();
release_barrier.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT;
release_barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
release_barrier.dstStageMask = VK_PIPELINE_STAGE_2_NONE;
release_barrier.dstAccessMask = VK_ACCESS_2_NONE;
release_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
release_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
release_barrier.srcQueueFamilyIndex = compute_only_family.value(); // specify compute family instead of expected transfer
release_barrier.dstQueueFamilyIndex = m_default_queue->family_index;
release_barrier.image = image;
release_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
release_cb.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-srcQueueFamilyIndex-10387");
release_cb.Barrier(release_barrier);
m_errorMonitor->VerifyFound();
release_cb.End();
// Acquire image
VkImageMemoryBarrier2 acquire_barrier = vku::InitStructHelper();
acquire_barrier.srcStageMask = VK_PIPELINE_STAGE_2_NONE;
acquire_barrier.srcAccessMask = VK_ACCESS_2_NONE;
acquire_barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
acquire_barrier.dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT;
acquire_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
acquire_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
acquire_barrier.srcQueueFamilyIndex = transfer_only_family.value();
acquire_barrier.dstQueueFamilyIndex = compute_only_family.value(); // specify compute family instead of expected graphics
acquire_barrier.image = image;
acquire_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
acquire_cb.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-srcQueueFamilyIndex-10387");
acquire_cb.Barrier(acquire_barrier);
m_errorMonitor->VerifyFound();
acquire_cb.End();
}
TEST_F(NegativeSyncObject, BufferOwnershipTransferQueueMismatch) {
TEST_DESCRIPTION("Neither src nor dst barrier queue family matches submit queue family");
RETURN_IF_SKIP(Init());
std::optional<uint32_t> transfer_only_family = m_device->TransferOnlyQueueFamily();
std::optional<uint32_t> compute_only_family = m_device->ComputeOnlyQueueFamily();
if (!transfer_only_family.has_value() || !compute_only_family.has_value()) {
GTEST_SKIP() << "Transfer-only and compute-only queue family is required";
}
vkt::CommandPool release_pool(*m_device, transfer_only_family.value());
vkt::CommandBuffer release_cb(*m_device, release_pool);
vkt::CommandBuffer acquire_cb(*m_device, m_command_pool);
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
// Release buffer
VkBufferMemoryBarrier release_barrier = vku::InitStructHelper();
release_barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
release_barrier.dstAccessMask = VK_ACCESS_2_NONE;
release_barrier.srcQueueFamilyIndex = compute_only_family.value(); // specify compute family instead of expected transfer
release_barrier.dstQueueFamilyIndex = m_default_queue->family_index;
release_barrier.buffer = buffer;
release_barrier.size = 256;
release_cb.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-srcQueueFamilyIndex-10388");
vk::CmdPipelineBarrier(release_cb, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1,
&release_barrier, 0, nullptr);
m_errorMonitor->VerifyFound();
release_cb.End();
// Acquire image
VkBufferMemoryBarrier acquire_barrier = vku::InitStructHelper();
acquire_barrier.srcAccessMask = 0;
acquire_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
acquire_barrier.srcQueueFamilyIndex = transfer_only_family.value();
acquire_barrier.dstQueueFamilyIndex = compute_only_family.value(); // specify compute family instead of expected graphics
acquire_barrier.buffer = buffer;
acquire_barrier.size = 256;
acquire_cb.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-srcQueueFamilyIndex-10388");
vk::CmdPipelineBarrier(acquire_cb, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 1,
&acquire_barrier, 0, nullptr);
m_errorMonitor->VerifyFound();
acquire_cb.End();
}
TEST_F(NegativeSyncObject, ConcurrentBufferBarrierNeedsIgnoredQueue) {
TEST_DESCRIPTION("Barrier for concurrent buffer resource must have VK_QUEUE_FAMILY_IGNORED at least for src or dst");
AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
std::optional<uint32_t> transfer_only_family = m_device->TransferOnlyQueueFamily();
if (!transfer_only_family.has_value()) {
GTEST_SKIP() << "Transfer-only queue family is required";
}
// Create VK_SHARING_MODE_CONCURRENT buffer by specifying queue families
uint32_t queue_families[2] = {m_default_queue->family_index, transfer_only_family.value()};
vkt::Buffer buffer;
buffer.Init(*m_device, 256, VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0, nullptr, vvl::make_span(queue_families, 2));
VkBufferMemoryBarrier barrier = vku::InitStructHelper();
barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
// Specify EXTERNAL for both queue families to trigger VU
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
barrier.buffer = buffer;
barrier.offset = 0;
barrier.size = 256;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkBufferMemoryBarrier-None-09049");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr,
1, &barrier, 0, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, ConcurrentImageBarrierNeedsIgnoredQueue) {
TEST_DESCRIPTION("Barrier for concurrent image resource must have VK_QUEUE_FAMILY_IGNORED at least for src or dst");
AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
std::optional<uint32_t> transfer_only_family = m_device->TransferOnlyQueueFamily();
if (!transfer_only_family.has_value()) {
GTEST_SKIP() << "Transfer-only queue family is required";
}
// Create VK_SHARING_MODE_CONCURRENT image by specifying queue families
uint32_t queue_families[2] = {m_default_queue->family_index, transfer_only_family.value()};
const VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
VkImageCreateInfo image_ci = vkt::Image::ImageCreateInfo2D(128, 128, 1, 1, VK_FORMAT_B8G8R8A8_UNORM, usage,
VK_IMAGE_TILING_OPTIMAL, vvl::make_span(queue_families, 2));
vkt::Image image(*m_device, image_ci);
// Release image
VkImageMemoryBarrier barrier = vku::InitStructHelper();
barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
// Specify EXTERNAL for both queue families to trigger VU
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
barrier.image = image;
barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-None-09052");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr,
0, nullptr, 1, &barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, BufferBarrierWithHostStage) {
TEST_DESCRIPTION("Buffer barrier includes VK_PIPELINE_STAGE_2_HOST_BIT as srcStageMask or dstStageMask");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
VkBufferMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.buffer = buffer;
barrier.size = VK_WHOLE_SIZE;
// source and destination families should be equal if HOST stage is used
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = 0;
// HOST stage as source
barrier.srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
barrier.srcAccessMask = VK_ACCESS_2_HOST_WRITE_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkBufferMemoryBarrier2-srcStageMask-03851");
m_command_buffer.Barrier(barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
// HOST stage as destination
barrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
barrier.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
barrier.dstAccessMask = VK_ACCESS_2_HOST_READ_BIT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkBufferMemoryBarrier2-srcStageMask-03851");
m_command_buffer.Barrier(barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, ImageBarrierWithHostStage) {
TEST_DESCRIPTION("Image barrier includes VK_PIPELINE_STAGE_2_HOST_BIT as srcStageMask or dstStageMask");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
vkt::Image image(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
VkImageMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.image = image;
barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
// source and destination families should be equal if HOST stage is used
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = 0;
// HOST stage as source
barrier.srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
barrier.srcAccessMask = VK_ACCESS_2_HOST_WRITE_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-srcStageMask-03854");
m_command_buffer.Barrier(barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
// HOST stage as destination
barrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
barrier.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
barrier.dstAccessMask = VK_ACCESS_2_HOST_READ_BIT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-srcStageMask-03854");
m_command_buffer.Barrier(barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, BufferBarrierWithHostStageSync1) {
TEST_DESCRIPTION("Buffer barrier includes VK_PIPELINE_STAGE_HOST_BIT as srcStageMask or dstStageMask");
RETURN_IF_SKIP(Init());
if (m_device->Physical().queue_properties_.size() < 2) {
GTEST_SKIP() << "Two queue families are required";
}
vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
VkBufferMemoryBarrier barrier = vku::InitStructHelper();
barrier.srcQueueFamilyIndex = 0;
barrier.dstQueueFamilyIndex = 1; // dstQueueFamilyIndex != srcQueueFamilyIndex
barrier.buffer = buffer;
barrier.size = VK_WHOLE_SIZE;
// HOST stage as source
barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-srcStageMask-09634");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1,
&barrier, 0, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
// HOST stage as destination
barrier.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_2_HOST_READ_BIT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-srcStageMask-09634");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 1,
&barrier, 0, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, ImageBarrierWithHostStageSync1) {
TEST_DESCRIPTION("Image barrier includes VK_PIPELINE_STAGE_HOST_BIT as srcStageMask or dstStageMask");
RETURN_IF_SKIP(Init());
if (m_device->Physical().queue_properties_.size() < 2) {
GTEST_SKIP() << "Two queue families are required";
}
vkt::Image image(*m_device, 128, 128, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
VkImageMemoryBarrier barrier = vku::InitStructHelper();
barrier.srcQueueFamilyIndex = 0;
barrier.dstQueueFamilyIndex = 1; // dstQueueFamilyIndex != srcQueueFamilyIndex
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.image = image;
barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
// HOST stage as source
barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-srcStageMask-09633");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0,
nullptr, 1, &barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
// HOST stage as destination
barrier.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_2_HOST_READ_BIT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-srcStageMask-09633");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 0,
nullptr, 1, &barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
// TODO - Figure out if test or VU are bad
TEST_F(NegativeSyncObject, BarrierQueueFamilyWithMemExt) {
TEST_DESCRIPTION("Create and submit barriers with invalid queue families when memory extension is enabled ");
AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
// Find queues of two families
const uint32_t submit_family = m_device->graphics_queue_node_index_;
const uint32_t invalid = static_cast<uint32_t>(m_device->Physical().queue_properties_.size());
const uint32_t other_family = submit_family != 0 ? 0 : 1;
const bool only_one_family = (invalid == 1) || (m_device->Physical().queue_properties_[other_family].queueCount == 0);
std::vector<uint32_t> qf_indices{{submit_family, other_family}};
if (only_one_family) {
qf_indices.resize(1);
}
BarrierQueueFamilyTestHelper::Context test_context(this, qf_indices);
BarrierQueueFamilyTestHelper excl_test(&test_context);
excl_test.Init(nullptr); // no queue families means *exclusive* sharing mode.
excl_test("VUID-VkImageMemoryBarrier-image-09118", "VUID-VkBufferMemoryBarrier-buffer-09096", submit_family, invalid);
excl_test("VUID-VkImageMemoryBarrier-image-09117", "VUID-VkBufferMemoryBarrier-buffer-09095", invalid, submit_family);
excl_test(submit_family, submit_family);
excl_test(submit_family, VK_QUEUE_FAMILY_EXTERNAL_KHR);
excl_test(VK_QUEUE_FAMILY_EXTERNAL_KHR, submit_family);
}
// TODO - Figure out if test or VU are bad
TEST_F(NegativeSyncObject, BarrierQueueFamilyWithMemExt2) {
TEST_DESCRIPTION("Create and submit barriers with invalid queue families when memory extension is enabled ");
AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
// Find queues of two families
const uint32_t submit_family = m_device->graphics_queue_node_index_;
const uint32_t invalid = static_cast<uint32_t>(m_device->Physical().queue_properties_.size());
const uint32_t other_family = submit_family != 0 ? 0 : 1;
const bool only_one_family = (invalid == 1) || (m_device->Physical().queue_properties_[other_family].queueCount == 0);
if (only_one_family) {
GTEST_SKIP() << "Single queue family found";
}
std::vector<uint32_t> qf_indices{{submit_family, other_family}};
BarrierQueueFamilyTestHelper::Context test_context(this, qf_indices);
std::vector<uint32_t> families = {submit_family, other_family};
BarrierQueueFamilyTestHelper conc_test(&test_context);
conc_test.Init(&families);
const char *img_vuid = "VUID-VkImageMemoryBarrier-None-09053";
const char *buf_vuid = "VUID-VkBufferMemoryBarrier-None-09050";
conc_test(img_vuid, buf_vuid, submit_family, submit_family);
conc_test(VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED);
conc_test(VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_EXTERNAL_KHR);
conc_test(VK_QUEUE_FAMILY_EXTERNAL_KHR, VK_QUEUE_FAMILY_IGNORED);
conc_test("VUID-VkImageMemoryBarrier-None-09053", "VUID-VkBufferMemoryBarrier-None-09050", submit_family,
VK_QUEUE_FAMILY_IGNORED);
conc_test("VUID-VkImageMemoryBarrier-None-09054", "VUID-VkBufferMemoryBarrier-None-09051", VK_QUEUE_FAMILY_IGNORED,
submit_family);
// This is to flag the errors that would be considered only "unexpected" in the parallel case above
conc_test(VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_EXTERNAL_KHR);
conc_test(VK_QUEUE_FAMILY_EXTERNAL_KHR, VK_QUEUE_FAMILY_IGNORED);
}
TEST_F(NegativeSyncObject, ImageBarrierWithBadRange) {
TEST_DESCRIPTION("VkImageMemoryBarrier with an invalid subresourceRange");
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkImageMemoryBarrier img_barrier_template = vku::InitStructHelper();
img_barrier_template.srcAccessMask = 0;
img_barrier_template.dstAccessMask = 0;
img_barrier_template.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
img_barrier_template.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
img_barrier_template.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
img_barrier_template.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
// subresourceRange to be set later for the for the purposes of this test
img_barrier_template.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 0, 0};
const uint32_t submit_family = m_device->graphics_queue_node_index_;
const uint32_t invalid = static_cast<uint32_t>(m_device->Physical().queue_properties_.size());
const uint32_t other_family = submit_family != 0 ? 0 : 1;
const bool only_one_family = (invalid == 1) || (m_device->Physical().queue_properties_[other_family].queueCount == 0);
std::vector<uint32_t> qf_indices{{submit_family, other_family}};
if (only_one_family) {
qf_indices.resize(1);
}
BarrierQueueFamilyTestHelper::Context test_context(this, qf_indices);
// Use image unbound to memory in barrier
// Use buffer unbound to memory in barrier
BarrierQueueFamilyTestHelper conc_test(&test_context);
conc_test.Init(nullptr);
img_barrier_template.image = conc_test.image_;
conc_test.image_barrier_ = img_barrier_template;
// Nested scope here confuses clang-format, somehow
// clang-format off
// try for vk::CmdPipelineBarrier
{
// Try baseMipLevel >= image.mipLevels with VK_REMAINING_MIP_LEVELS
{
conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 1, VK_REMAINING_MIP_LEVELS, 0, 1};
conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01486");
}
// Try baseMipLevel >= image.mipLevels without VK_REMAINING_MIP_LEVELS
{
conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 0, 1};
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-01724");
conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01486");
}
// Try levelCount = 0
{
conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 0, 1};
conc_test("VUID-VkImageSubresourceRange-levelCount-01720");
}
// Try baseMipLevel + levelCount > image.mipLevels
{
conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 2, 0, 1};
conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01724");
}
// Try baseArrayLayer >= image.arrayLayers with VK_REMAINING_ARRAY_LAYERS
{
conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, VK_REMAINING_ARRAY_LAYERS};
conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01488");
}
// Try baseArrayLayer >= image.arrayLayers without VK_REMAINING_ARRAY_LAYERS
{
conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, 1};
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-01725");
conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01488");
}
// Try layerCount = 0
{
conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 0};
conc_test("VUID-VkImageSubresourceRange-layerCount-01721");
}
// Try baseArrayLayer + layerCount > image.arrayLayers
{
conc_test.image_barrier_.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 2};
conc_test("VUID-VkImageMemoryBarrier-subresourceRange-01725");
}
}
m_command_buffer.Begin();
// try for vk::CmdWaitEvents
{
vkt::Event event(*m_device);
// Try baseMipLevel >= image.mipLevels with VK_REMAINING_MIP_LEVELS
{
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-01486");
const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 1, VK_REMAINING_MIP_LEVELS, 0, 1};
VkImageMemoryBarrier img_barrier = img_barrier_template;
img_barrier.subresourceRange = range;
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier);
m_errorMonitor->VerifyFound();
}
// Try baseMipLevel >= image.mipLevels without VK_REMAINING_MIP_LEVELS
{
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-01486");
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-01724");
const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 0, 1};
VkImageMemoryBarrier img_barrier = img_barrier_template;
img_barrier.subresourceRange = range;
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier);
m_errorMonitor->VerifyFound();
}
// Try levelCount = 0
{
m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceRange-levelCount-01720");
const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 0, 1};
VkImageMemoryBarrier img_barrier = img_barrier_template;
img_barrier.subresourceRange = range;
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier);
m_errorMonitor->VerifyFound();
}
// Try baseMipLevel + levelCount > image.mipLevels
{
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-01724");
const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 2, 0, 1};
VkImageMemoryBarrier img_barrier = img_barrier_template;
img_barrier.subresourceRange = range;
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier);
m_errorMonitor->VerifyFound();
}
// Try baseArrayLayer >= image.arrayLayers with VK_REMAINING_ARRAY_LAYERS
{
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-01488");
const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, VK_REMAINING_ARRAY_LAYERS};
VkImageMemoryBarrier img_barrier = img_barrier_template;
img_barrier.subresourceRange = range;
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier);
m_errorMonitor->VerifyFound();
}
// Try baseArrayLayer >= image.arrayLayers without VK_REMAINING_ARRAY_LAYERS
{
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-01488");
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-01725");
const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 1, 1};
VkImageMemoryBarrier img_barrier = img_barrier_template;
img_barrier.subresourceRange = range;
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier);
m_errorMonitor->VerifyFound();
}
// Try layerCount = 0
{
m_errorMonitor->SetDesiredError("VUID-VkImageSubresourceRange-layerCount-01721");
const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 0};
VkImageMemoryBarrier img_barrier = img_barrier_template;
img_barrier.subresourceRange = range;
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier);
m_errorMonitor->VerifyFound();
}
// Try baseArrayLayer + layerCount > image.arrayLayers
{
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-subresourceRange-01725");
const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 2};
VkImageMemoryBarrier img_barrier = img_barrier_template;
img_barrier.subresourceRange = range;
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 1, &img_barrier);
m_errorMonitor->VerifyFound();
}
}
// clang-format on
}
TEST_F(NegativeSyncObject, Sync2BarrierQueueFamily) {
TEST_DESCRIPTION("Create and submit barriers with invalid queue families with synchronization2");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
// Find queues of two families
const uint32_t submit_family = m_device->graphics_queue_node_index_;
const uint32_t invalid = static_cast<uint32_t>(m_device->Physical().queue_properties_.size());
const uint32_t other_family = submit_family != 0 ? 0 : 1;
const bool only_one_family = (invalid == 1) || (m_device->Physical().queue_properties_[other_family].queueCount == 0);
std::vector<uint32_t> qf_indices{{submit_family, other_family}};
if (only_one_family) {
qf_indices.resize(1);
}
BarrierQueueFamilyTestHelper::Context test_context(this, qf_indices);
Barrier2QueueFamilyTestHelper::Context test_context2(this, qf_indices);
Barrier2QueueFamilyTestHelper excl_test(&test_context2);
excl_test.Init(); // *exclusive* sharing mode.
excl_test("VUID-VkImageMemoryBarrier2-image-09118", "VUID-VkBufferMemoryBarrier2-buffer-09096", submit_family, invalid);
excl_test("VUID-VkImageMemoryBarrier2-image-09117", "VUID-VkBufferMemoryBarrier2-buffer-09095", invalid, submit_family);
excl_test(submit_family, submit_family);
excl_test(submit_family, VK_QUEUE_FAMILY_EXTERNAL_KHR);
excl_test(VK_QUEUE_FAMILY_EXTERNAL_KHR, submit_family);
}
TEST_F(NegativeSyncObject, BufferBarrierQueuesExternalAndForeign) {
TEST_DESCRIPTION("Test buffer barrier with one family EXTERNAL and another one FOREIGN_EXT");
AddRequiredExtensions(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME);
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VkBufferMemoryBarrier bmb = vku::InitStructHelper();
bmb.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
bmb.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
bmb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
bmb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
bmb.buffer = buffer;
bmb.offset = 0;
bmb.size = VK_WHOLE_SIZE;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-srcQueueFamilyIndex-10388");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1, &bmb, 0, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, BufferBarrierQueuesExternalAndForeign2) {
TEST_DESCRIPTION("Test buffer barrier with one family EXTERNAL and another one FOREIGN_EXT");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VkBufferMemoryBarrier2 bmb = vku::InitStructHelper();
bmb.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
bmb.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
bmb.dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
bmb.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
bmb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
bmb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
bmb.buffer = buffer;
bmb.offset = 0;
bmb.size = VK_WHOLE_SIZE;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-srcQueueFamilyIndex-10387");
m_command_buffer.Barrier(bmb);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, BarrierAccessSync2) {
TEST_DESCRIPTION("Test barrier VkAccessFlagBits2.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 mem_barrier = vku::InitStructHelper();
mem_barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
m_command_buffer.Begin();
// srcAccessMask and srcStageMask
mem_barrier.srcAccessMask = VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03900");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_INDEX_READ_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03901");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03902");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03903");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_UNIFORM_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03904");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03905");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03906");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03907");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-07454");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03909");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03910");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03911");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03912");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03913");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03914");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03915");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_HOST_READ_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03916");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_HOST_READ_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03916");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_HOST_WRITE_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-03917");
m_command_buffer.BarrierKHR(mem_barrier);
// now test dstAccessMask and dstStageMask
mem_barrier.srcAccessMask = VK_ACCESS_2_HOST_WRITE_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
mem_barrier.dstAccessMask = VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT;
mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03900");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_INDEX_READ_BIT;
mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03901");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03902");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03903");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_UNIFORM_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03904");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03905");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03906");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03907");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-07454");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03909");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03910");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03911");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03912");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03913");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03914");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03915");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_HOST_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03916");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.dstAccessMask = VK_ACCESS_2_HOST_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03917");
m_command_buffer.BarrierKHR(mem_barrier);
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, BarrierAccessSync1) {
TEST_DESCRIPTION("Special cases for sync1 that worth to check. Sync2 testing is enough for other checks");
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
VkMemoryBarrier mem_barrier = vku::InitStructHelper();
mem_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-srcAccessMask-02815");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 1,
&mem_barrier, 0, nullptr, 0, nullptr);
m_errorMonitor->VerifyFound();
mem_barrier = vku::InitStructHelper();
mem_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-dstAccessMask-02816");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 1,
&mem_barrier, 0, nullptr, 0, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, BarrierAccessSync2RtxMaintenance1) {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredFeature(vkt::Feature::rayTracingMaintenance1);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 mem_barrier = vku::InitStructHelper();
m_command_buffer.Begin();
mem_barrier.srcAccessMask = VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
mem_barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-07272");
m_command_buffer.BarrierKHR(mem_barrier);
m_errorMonitor->VerifyFound();
mem_barrier.srcAccessMask = VK_ACCESS_2_HOST_WRITE_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
mem_barrier.dstAccessMask = VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR;
mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-07272");
m_command_buffer.BarrierKHR(mem_barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, BarrierAccessSync2DescriptorBuffer) {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredFeature(vkt::Feature::descriptorBuffer);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 mem_barrier = vku::InitStructHelper();
m_command_buffer.Begin();
mem_barrier.srcAccessMask = VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
mem_barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-08118");
m_command_buffer.BarrierKHR(mem_barrier);
m_errorMonitor->VerifyFound();
mem_barrier.srcAccessMask = VK_ACCESS_2_HOST_WRITE_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
mem_barrier.dstAccessMask = VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT;
mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-08118");
m_command_buffer.BarrierKHR(mem_barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, BarrierAccessSync2MemoryDecompression) {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 mem_barrier = vku::InitStructHelper();
m_command_buffer.Begin();
// srcAccessMask mismatch: decompression READ access without decompression stage
mem_barrier = vku::InitStructHelper();
mem_barrier.srcAccessMask = VK_ACCESS_2_MEMORY_DECOMPRESSION_READ_BIT_EXT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-11771");
m_command_buffer.BarrierKHR(mem_barrier);
m_errorMonitor->VerifyFound();
// srcAccessMask mismatch: decompression WRITE access without decompression stage
mem_barrier = vku::InitStructHelper();
mem_barrier.srcAccessMask = VK_ACCESS_2_MEMORY_DECOMPRESSION_WRITE_BIT_EXT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-11772");
m_command_buffer.BarrierKHR(mem_barrier);
m_errorMonitor->VerifyFound();
// dstAccessMask mismatch: decompression READ access without decompression stage
mem_barrier = vku::InitStructHelper();
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
mem_barrier.dstAccessMask = VK_ACCESS_2_MEMORY_DECOMPRESSION_READ_BIT_EXT;
mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-11771");
m_command_buffer.BarrierKHR(mem_barrier);
m_errorMonitor->VerifyFound();
// dstAccessMask mismatch: decompression WRITE access without decompression stage
mem_barrier = vku::InitStructHelper();
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
mem_barrier.dstAccessMask = VK_ACCESS_2_MEMORY_DECOMPRESSION_WRITE_BIT_EXT;
mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-11772");
m_command_buffer.BarrierKHR(mem_barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, BarrierAccessVideoDecode) {
TEST_DESCRIPTION("Test barrier with access decode read bit.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 mem_barrier = vku::InitStructHelper();
mem_barrier.srcAccessMask = VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR;
mem_barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT;
mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-04858");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-04859");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-04860");
m_command_buffer.BarrierKHR(mem_barrier);
mem_barrier.srcAccessMask = VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcAccessMask-04861");
m_command_buffer.BarrierKHR(mem_barrier);
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, Sync2LayoutFeature) {
SetTargetApiVersion(VK_API_VERSION_1_3);
RETURN_IF_SKIP(Init());
VkImageCreateInfo info = vkt::Image::ImageCreateInfo2D(1, 1, 1, 1, VK_FORMAT_B8G8R8A8_UNORM,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
vkt::Image image(*m_device, info, vkt::set_layout);
m_command_buffer.Begin();
VkImageMemoryBarrier2 img_barrier = vku::InitStructHelper();
img_barrier.image = image;
img_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
img_barrier.srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
img_barrier.dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
img_barrier.oldLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL;
img_barrier.newLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-synchronization2-03848");
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-synchronization2-07793"); // oldLayout
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-synchronization2-07794"); // newLayout
m_command_buffer.Barrier(img_barrier);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, ZeroInitializeLayoutFeature) {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_EXT_ZERO_INITIALIZE_DEVICE_MEMORY_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkImageCreateInfo info =
vkt::Image::ImageCreateInfo2D(1, 1, 1, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::Image image(*m_device, info, vkt::set_layout);
m_command_buffer.Begin();
VkImageMemoryBarrier2 img_barrier = vku::InitStructHelper();
img_barrier.image = image;
img_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
img_barrier.srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
img_barrier.dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
img_barrier.oldLayout = VK_IMAGE_LAYOUT_ZERO_INITIALIZED_EXT;
img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-oldLayout-10767");
m_command_buffer.Barrier(img_barrier);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, ZeroInitializeLayoutSubresource) {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_EXT_ZERO_INITIALIZE_DEVICE_MEMORY_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredFeature(vkt::Feature::zeroInitializeDeviceMemory);
RETURN_IF_SKIP(Init());
VkImageCreateInfo info =
vkt::Image::ImageCreateInfo2D(4, 4, 2, 2, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::Image image(*m_device, info);
m_command_buffer.Begin();
VkImageMemoryBarrier2 img_barrier = vku::InitStructHelper();
img_barrier.image = image;
img_barrier.srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
img_barrier.dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
img_barrier.oldLayout = VK_IMAGE_LAYOUT_ZERO_INITIALIZED_EXT;
img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
img_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 2, 1, 1};
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-oldLayout-10768");
m_command_buffer.Barrier(img_barrier);
m_errorMonitor->VerifyFound();
img_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 0, 2};
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-oldLayout-10768");
m_command_buffer.Barrier(img_barrier);
m_errorMonitor->VerifyFound();
img_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 2};
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-oldLayout-10768");
m_command_buffer.Barrier(img_barrier);
m_errorMonitor->VerifyFound();
img_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 2, 0, 1};
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-oldLayout-10768");
m_command_buffer.Barrier(img_barrier);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, SubmitSignaledFence) {
RETURN_IF_SKIP(Init());
VkFenceCreateInfo fenceInfo = vku::InitStructHelper();
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
vkt::Fence testFence(*m_device, fenceInfo);
m_command_buffer.Begin();
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit-fence-00063");
m_default_queue->Submit(m_command_buffer, testFence);
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, QueueSubmitWaitingSameSemaphore) {
TEST_DESCRIPTION("Submit to queue with waitSemaphore that another queue is already waiting on.");
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
all_queue_count_ = true;
RETURN_IF_SKIP(Init());
if ((m_second_queue_caps & VK_QUEUE_GRAPHICS_BIT) == 0) {
GTEST_SKIP() << "2 graphics queues are needed";
}
vkt::Semaphore semaphore(*m_device);
{
VkPipelineStageFlags stage_flags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
m_default_queue->Submit(vkt::no_cmd, vkt::Signal(semaphore));
m_default_queue->Submit(vkt::no_cmd, vkt::Wait(semaphore, stage_flags));
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit-pWaitSemaphores-00068");
m_second_queue->Submit(vkt::no_cmd, vkt::Wait(semaphore, stage_flags));
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
m_second_queue->Wait();
}
if (m_device->Physical().queue_properties_[m_default_queue->family_index].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) {
VkBindSparseInfo signal_bind = vku::InitStructHelper();
signal_bind.signalSemaphoreCount = 1;
signal_bind.pSignalSemaphores = &semaphore.handle();
VkBindSparseInfo wait_bind = vku::InitStructHelper();
wait_bind.waitSemaphoreCount = 1;
wait_bind.pWaitSemaphores = &semaphore.handle();
vk::QueueBindSparse(m_default_queue->handle(), 1, &signal_bind, VK_NULL_HANDLE);
vk::QueueBindSparse(m_default_queue->handle(), 1, &wait_bind, VK_NULL_HANDLE);
m_errorMonitor->SetDesiredError("VUID-vkQueueBindSparse-pWaitSemaphores-01116");
vk::QueueBindSparse(m_second_queue->handle(), 1, &wait_bind, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
m_second_queue->Wait();
}
// sync 2
{
VkSemaphoreSubmitInfo signal_sem_info = vku::InitStructHelper();
signal_sem_info.semaphore = semaphore;
signal_sem_info.stageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkSubmitInfo2 signal_submit = vku::InitStructHelper();
signal_submit.signalSemaphoreInfoCount = 1;
signal_submit.pSignalSemaphoreInfos = &signal_sem_info;
VkSemaphoreSubmitInfo wait_sem_info = vku::InitStructHelper();
wait_sem_info.semaphore = semaphore;
wait_sem_info.stageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkSubmitInfo2 wait_submit = vku::InitStructHelper();
wait_submit.waitSemaphoreInfoCount = 1;
wait_submit.pWaitSemaphoreInfos = &wait_sem_info;
vk::QueueSubmit2KHR(m_default_queue->handle(), 1, &signal_submit, VK_NULL_HANDLE);
vk::QueueSubmit2KHR(m_default_queue->handle(), 1, &wait_submit, VK_NULL_HANDLE);
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit2-semaphore-03871");
vk::QueueSubmit2KHR(m_second_queue->handle(), 1, &wait_submit, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
m_second_queue->Wait();
}
}
TEST_F(NegativeSyncObject, QueueSubmit2KHRUsedButSynchronizaion2Disabled) {
TEST_DESCRIPTION("Using QueueSubmit2KHR when synchronization2 is not enabled");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
bool vulkan_13 = (DeviceValidationVersion() >= VK_API_VERSION_1_3);
VkSubmitInfo2 submit_info = vku::InitStructHelper();
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit2-synchronization2-03866");
vk::QueueSubmit2KHR(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
if (vulkan_13) {
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit2-synchronization2-03866");
m_default_queue->Submit2(vkt::no_cmd);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeSyncObject, WaitEventsDifferentQueueFamilies) {
TEST_DESCRIPTION("Using CmdWaitEvents with invalid barrier queue families");
RETURN_IF_SKIP(Init());
InitRenderTarget();
const std::optional<uint32_t> no_gfx = m_device->QueueFamilyWithoutCapabilities(VK_QUEUE_GRAPHICS_BIT);
if (!no_gfx) {
GTEST_SKIP() << "Required queue families not present (non-graphics non-compute capable required)";
}
vkt::Event event(*m_device);
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VkBufferMemoryBarrier BufferMemoryBarrier = vku::InitStructHelper();
BufferMemoryBarrier.srcAccessMask = 0;
BufferMemoryBarrier.dstAccessMask = 0;
BufferMemoryBarrier.buffer = buffer;
BufferMemoryBarrier.offset = 0;
BufferMemoryBarrier.size = 256;
BufferMemoryBarrier.srcQueueFamilyIndex = m_device->graphics_queue_node_index_;
BufferMemoryBarrier.dstQueueFamilyIndex = no_gfx.value();
vkt::Image image(*m_device, 32, 32, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
VkImageMemoryBarrier ImageMemoryBarrier = vku::InitStructHelper();
ImageMemoryBarrier.srcAccessMask = 0;
ImageMemoryBarrier.dstAccessMask = 0;
ImageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
ImageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
ImageMemoryBarrier.image = image;
ImageMemoryBarrier.srcQueueFamilyIndex = m_device->graphics_queue_node_index_;
ImageMemoryBarrier.dstQueueFamilyIndex = no_gfx.value();
ImageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
ImageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
ImageMemoryBarrier.subresourceRange.baseMipLevel = 0;
ImageMemoryBarrier.subresourceRange.layerCount = 1;
ImageMemoryBarrier.subresourceRange.levelCount = 1;
m_command_buffer.Begin();
vk::CmdSetEvent(m_command_buffer, event, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents-srcQueueFamilyIndex-02803");
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0,
nullptr, 1, &BufferMemoryBarrier, 0, nullptr);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents-srcQueueFamilyIndex-02803");
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0,
nullptr, 0, nullptr, 1, &ImageMemoryBarrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, CmdWaitEvents2DependencyFlags) {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
vkt::Event event(*m_device);
VkEvent event_handle = event;
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.dependencyFlags = VK_DEPENDENCY_VIEW_LOCAL_BIT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents2-dependencyFlags-10394");
vk::CmdWaitEvents2KHR(m_command_buffer, 1, &event_handle, &dependency_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, WaitEvent2HostStage) {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
InitRenderTarget();
vkt::Event event(*m_device);
VkEvent event_handle = event;
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
barrier.srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.memoryBarrierCount = 1;
dependency_info.pMemoryBarriers = &barrier;
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents2-dependencyFlags-03844");
vk::CmdWaitEvents2KHR(m_command_buffer, 1, &event_handle, &dependency_info);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, SemaphoreTypeCreateInfoCore) {
TEST_DESCRIPTION("Invalid usage of VkSemaphoreTypeCreateInfo with a 1.2 core version");
SetTargetApiVersion(VK_API_VERSION_1_2);
// Core 1.2 supports timelineSemaphore feature bit but not enabled
RETURN_IF_SKIP(Init());
VkSemaphore semaphore;
VkSemaphoreTypeCreateInfo semaphore_type_create_info = vku::InitStructHelper();
semaphore_type_create_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
semaphore_type_create_info.initialValue = 1;
VkSemaphoreCreateInfo semaphore_create_info = vku::InitStructHelper(&semaphore_type_create_info);
semaphore_create_info.flags = 0;
// timelineSemaphore feature bit not set
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreTypeCreateInfo-timelineSemaphore-03252");
vk::CreateSemaphore(device(), &semaphore_create_info, nullptr, &semaphore);
m_errorMonitor->VerifyFound();
// Binary semaphore can't be initialValue 0
semaphore_type_create_info.semaphoreType = VK_SEMAPHORE_TYPE_BINARY;
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreTypeCreateInfo-semaphoreType-03279");
vk::CreateSemaphore(device(), &semaphore_create_info, nullptr, &semaphore);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, SemaphoreTypeCreateInfoExtension) {
TEST_DESCRIPTION("Invalid usage of VkSemaphoreTypeCreateInfo with extension");
SetTargetApiVersion(VK_API_VERSION_1_1); // before timelineSemaphore was added to core
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
// Enabled extension but not the timelineSemaphore feature bit
RETURN_IF_SKIP(Init());
VkSemaphore semaphore;
VkSemaphoreTypeCreateInfo semaphore_type_create_info = vku::InitStructHelper();
semaphore_type_create_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
semaphore_type_create_info.initialValue = 1;
VkSemaphoreCreateInfo semaphore_create_info = vku::InitStructHelper(&semaphore_type_create_info);
semaphore_create_info.flags = 0;
// timelineSemaphore feature bit not set
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreTypeCreateInfo-timelineSemaphore-03252");
vk::CreateSemaphore(device(), &semaphore_create_info, nullptr, &semaphore);
m_errorMonitor->VerifyFound();
// Binary semaphore can't be initialValue 0
semaphore_type_create_info.semaphoreType = VK_SEMAPHORE_TYPE_BINARY;
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreTypeCreateInfo-semaphoreType-03279");
vk::CreateSemaphore(device(), &semaphore_create_info, nullptr, &semaphore);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, MixedTimelineAndBinarySemaphores) {
TEST_DESCRIPTION("Submit mixtures of timeline and binary semaphores");
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceTimelineSemaphorePropertiesKHR timelineproperties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(timelineproperties);
VkSemaphoreTypeCreateInfo semaphore_type_create_info = vku::InitStructHelper();
semaphore_type_create_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
semaphore_type_create_info.initialValue = 5;
VkSemaphoreCreateInfo semaphore_create_info = vku::InitStructHelper(&semaphore_type_create_info);
VkSemaphore semaphore[2];
vk::CreateSemaphore(device(), &semaphore_create_info, nullptr, &semaphore[0]);
// index 1 should be a binary semaphore
semaphore_create_info.pNext = nullptr;
vk::CreateSemaphore(device(), &semaphore_create_info, nullptr, &semaphore[1]);
VkSemaphore extra_binary;
vk::CreateSemaphore(device(), &semaphore_create_info, nullptr, &extra_binary);
VkSemaphoreSignalInfo semaphore_signal_info = vku::InitStructHelper();
semaphore_signal_info.semaphore = semaphore[0];
semaphore_signal_info.value = 3;
semaphore_signal_info.value = 10;
vk::SignalSemaphoreKHR(device(), &semaphore_signal_info);
VkTimelineSemaphoreSubmitInfo timeline_semaphore_submit_info = vku::InitStructHelper();
uint64_t signalValue = 20;
timeline_semaphore_submit_info.waitSemaphoreValueCount = 0;
timeline_semaphore_submit_info.pWaitSemaphoreValues = nullptr;
// this array needs a length of 2, even though the binary semaphore won't look at the values array
timeline_semaphore_submit_info.signalSemaphoreValueCount = 1;
timeline_semaphore_submit_info.pSignalSemaphoreValues = &signalValue;
VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkSubmitInfo submit_info = vku::InitStructHelper(&timeline_semaphore_submit_info);
submit_info.pWaitDstStageMask = &stageFlags;
submit_info.waitSemaphoreCount = 0;
submit_info.pWaitSemaphores = nullptr;
submit_info.signalSemaphoreCount = 2;
submit_info.pSignalSemaphores = semaphore;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pNext-03241");
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
uint64_t values[2] = {signalValue, 0 /*ignored*/};
timeline_semaphore_submit_info.signalSemaphoreValueCount = 2;
timeline_semaphore_submit_info.pSignalSemaphoreValues = values;
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
// the indexes in pWaitSemaphores and pWaitSemaphoreValues should match
VkSemaphore reversed[2] = {semaphore[1], semaphore[0]};
uint64_t reversed_values[2] = {vvl::kU64Max /* ignored */, 20};
VkPipelineStageFlags wait_stages[2] = {VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT};
submit_info.signalSemaphoreCount = 0;
submit_info.pSignalSemaphores = nullptr;
submit_info.waitSemaphoreCount = 2;
submit_info.pWaitSemaphores = reversed;
submit_info.pWaitDstStageMask = wait_stages;
timeline_semaphore_submit_info.signalSemaphoreValueCount = 0;
timeline_semaphore_submit_info.pSignalSemaphoreValues = nullptr;
timeline_semaphore_submit_info.waitSemaphoreValueCount = 2;
timeline_semaphore_submit_info.pWaitSemaphoreValues = reversed_values;
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
// if we only signal a binary semaphore we don't need a 'values' array
timeline_semaphore_submit_info.waitSemaphoreValueCount = 0;
timeline_semaphore_submit_info.pWaitSemaphoreValues = nullptr;
timeline_semaphore_submit_info.signalSemaphoreValueCount = 0;
timeline_semaphore_submit_info.pSignalSemaphoreValues = nullptr;
submit_info.waitSemaphoreCount = 0;
submit_info.pWaitSemaphores = nullptr;
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &extra_binary;
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_default_queue->Wait();
vk::DestroySemaphore(device(), semaphore[0], nullptr);
vk::DestroySemaphore(device(), semaphore[1], nullptr);
vk::DestroySemaphore(device(), extra_binary, nullptr);
}
TEST_F(NegativeSyncObject, QueueSubmitNoTimelineSemaphoreInfo) {
TEST_DESCRIPTION("Submit a queue with a timeline semaphore but not a VkTimelineSemaphoreSubmitInfo.");
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
VkSemaphoreTypeCreateInfo semaphore_type_create_info = vku::InitStructHelper();
semaphore_type_create_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
VkSemaphoreCreateInfo semaphore_create_info = vku::InitStructHelper(&semaphore_type_create_info);
VkSemaphore semaphore;
ASSERT_EQ(VK_SUCCESS, vk::CreateSemaphore(device(), &semaphore_create_info, nullptr, &semaphore));
VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkSubmitInfo submit_info[2] = {};
submit_info[0] = vku::InitStructHelper();
submit_info[0].commandBufferCount = 0;
submit_info[0].pWaitDstStageMask = &stageFlags;
submit_info[0].signalSemaphoreCount = 1;
submit_info[0].pSignalSemaphores = &semaphore;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pWaitSemaphores-03239");
vk::QueueSubmit(m_default_queue->handle(), 1, submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
VkTimelineSemaphoreSubmitInfo timeline_semaphore_submit_info = vku::InitStructHelper();
uint64_t signalValue = 1;
timeline_semaphore_submit_info.signalSemaphoreValueCount = 1;
timeline_semaphore_submit_info.pSignalSemaphoreValues = &signalValue;
submit_info[0].pNext = &timeline_semaphore_submit_info;
submit_info[1] = vku::InitStructHelper();
submit_info[1].commandBufferCount = 0;
submit_info[1].pWaitDstStageMask = &stageFlags;
submit_info[1].waitSemaphoreCount = 1;
submit_info[1].pWaitSemaphores = &semaphore;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pWaitSemaphores-03239");
vk::QueueSubmit(m_default_queue->handle(), 2, submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
vk::DestroySemaphore(device(), semaphore, nullptr);
}
TEST_F(NegativeSyncObject, QueueSubmitTimelineSemaphoreValue) {
TEST_DESCRIPTION("Submit a queue with a timeline semaphore using a wrong payload value.");
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceTimelineSemaphorePropertiesKHR timelineproperties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(timelineproperties);
VkSemaphoreTypeCreateInfo semaphore_type_create_info = vku::InitStructHelper();
semaphore_type_create_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
VkSemaphoreCreateInfo semaphore_create_info = vku::InitStructHelper(&semaphore_type_create_info);
vkt::Semaphore semaphore(*m_device, semaphore_create_info);
VkTimelineSemaphoreSubmitInfo timeline_semaphore_submit_info = vku::InitStructHelper();
uint64_t signalValue = 1;
uint64_t waitValue = 3;
timeline_semaphore_submit_info.signalSemaphoreValueCount = 1;
timeline_semaphore_submit_info.pSignalSemaphoreValues = &signalValue;
timeline_semaphore_submit_info.waitSemaphoreValueCount = 1;
timeline_semaphore_submit_info.pWaitSemaphoreValues = &waitValue;
VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkSubmitInfo submit_info = vku::InitStructHelper(&timeline_semaphore_submit_info);
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &semaphore.handle();
submit_info.pWaitDstStageMask = &stageFlags;
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &semaphore.handle();
timeline_semaphore_submit_info.signalSemaphoreValueCount = 0;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pNext-03241");
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
timeline_semaphore_submit_info.signalSemaphoreValueCount = 1;
timeline_semaphore_submit_info.waitSemaphoreValueCount = 0;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pNext-03240");
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
signalValue = 5;
{
VkSemaphoreSignalInfo semaphore_signal_info = vku::InitStructHelper();
semaphore_signal_info.semaphore = semaphore;
semaphore_signal_info.value = signalValue;
ASSERT_EQ(VK_SUCCESS, vk::SignalSemaphoreKHR(device(), &semaphore_signal_info));
}
timeline_semaphore_submit_info.waitSemaphoreValueCount = 1;
// Check for re-signalling an already completed value (5)
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pSignalSemaphores-03242");
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
// Submit (6)
signalValue++;
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
// Check against a pending value (6)
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pSignalSemaphores-03242");
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
{
// Double signal with the same value (7)
signalValue++;
uint64_t signal_values[2] = {signalValue, signalValue};
VkSemaphore signal_sems[2] = {semaphore, semaphore};
VkTimelineSemaphoreSubmitInfo tl_info_2 = vku::InitStructHelper();
tl_info_2.signalSemaphoreValueCount = 2;
tl_info_2.pSignalSemaphoreValues = signal_values;
VkSubmitInfo submit_info2 = vku::InitStructHelper(&tl_info_2);
submit_info2.signalSemaphoreCount = 2;
submit_info2.pSignalSemaphores = signal_sems;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pSignalSemaphores-03242");
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info2, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
}
// Check if we can test violations of maxTimelineSemaphoreValueDifference
if (timelineproperties.maxTimelineSemaphoreValueDifference < vvl::kU64Max) {
uint64_t bigValue = signalValue + timelineproperties.maxTimelineSemaphoreValueDifference + 1;
timeline_semaphore_submit_info.pSignalSemaphoreValues = &bigValue;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pSignalSemaphores-03244");
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
if (signalValue < vvl::kU64Max) {
signalValue++;
timeline_semaphore_submit_info.pSignalSemaphoreValues = &signalValue;
waitValue = signalValue + timelineproperties.maxTimelineSemaphoreValueDifference + 1;
submit_info.signalSemaphoreCount = 0;
timeline_semaphore_submit_info.signalSemaphoreValueCount = 0;
timeline_semaphore_submit_info.waitSemaphoreValueCount = 1;
timeline_semaphore_submit_info.pWaitSemaphoreValues = &waitValue;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pWaitSemaphores-03243");
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
}
}
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, QueueBindSparseTimelineSemaphoreValue) {
TEST_DESCRIPTION("Submit a queue with a timeline semaphore using a wrong payload value.");
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
auto index = m_device->graphics_queue_node_index_;
if ((m_device->Physical().queue_properties_[index].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) == 0) {
GTEST_SKIP() << "Graphics queue does not have sparse binding bit";
}
VkPhysicalDeviceTimelineSemaphorePropertiesKHR timelineproperties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(timelineproperties);
VkSemaphoreTypeCreateInfo semaphore_type_create_info = vku::InitStructHelper();
semaphore_type_create_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
VkSemaphoreCreateInfo semaphore_create_info = vku::InitStructHelper(&semaphore_type_create_info);
vkt::Semaphore semaphore(*m_device, semaphore_create_info);
VkTimelineSemaphoreSubmitInfo timeline_semaphore_submit_info = vku::InitStructHelper();
uint64_t signalValue = 1;
uint64_t waitValue = 3;
timeline_semaphore_submit_info.signalSemaphoreValueCount = 1;
timeline_semaphore_submit_info.pSignalSemaphoreValues = &signalValue;
timeline_semaphore_submit_info.waitSemaphoreValueCount = 1;
timeline_semaphore_submit_info.pWaitSemaphoreValues = &waitValue;
VkBindSparseInfo submit_info = vku::InitStructHelper();
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &semaphore.handle();
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &semaphore.handle();
// error for both signal and wait
m_errorMonitor->SetDesiredError("VUID-VkBindSparseInfo-pWaitSemaphores-03246");
m_errorMonitor->SetDesiredError("VUID-VkBindSparseInfo-pWaitSemaphores-03246");
vk::QueueBindSparse(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
submit_info.pNext = &timeline_semaphore_submit_info;
timeline_semaphore_submit_info.signalSemaphoreValueCount = 0;
m_errorMonitor->SetDesiredError("VUID-VkBindSparseInfo-pNext-03248");
vk::QueueBindSparse(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
timeline_semaphore_submit_info.signalSemaphoreValueCount = 1;
submit_info.signalSemaphoreCount = 1;
timeline_semaphore_submit_info.waitSemaphoreValueCount = 0;
submit_info.waitSemaphoreCount = 1;
m_errorMonitor->SetDesiredError("VUID-VkBindSparseInfo-pNext-03247");
vk::QueueBindSparse(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
signalValue = 5;
{
VkSemaphoreSignalInfo semaphore_signal_info = vku::InitStructHelper();
semaphore_signal_info.semaphore = semaphore;
semaphore_signal_info.value = signalValue;
ASSERT_EQ(VK_SUCCESS, vk::SignalSemaphoreKHR(device(), &semaphore_signal_info));
}
timeline_semaphore_submit_info.waitSemaphoreValueCount = 1;
submit_info.waitSemaphoreCount = 1;
// Check for re-signalling an already completed value (5)
m_errorMonitor->SetDesiredError("VUID-VkBindSparseInfo-pSignalSemaphores-03249");
vk::QueueBindSparse(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
// Submit (6)
signalValue++;
vk::QueueBindSparse(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
// Check against a pending value (6)
m_errorMonitor->SetDesiredError("VUID-VkBindSparseInfo-pSignalSemaphores-03249");
vk::QueueBindSparse(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
{
// Double signal with the same value (7)
signalValue++;
uint64_t signal_values[2] = {signalValue, signalValue};
VkSemaphore signal_sems[2] = {semaphore, semaphore};
VkTimelineSemaphoreSubmitInfo tl_info_2 = vku::InitStructHelper();
tl_info_2.signalSemaphoreValueCount = 2;
tl_info_2.pSignalSemaphoreValues = signal_values;
VkBindSparseInfo submit_info2 = vku::InitStructHelper(&tl_info_2);
submit_info2.signalSemaphoreCount = 2;
submit_info2.pSignalSemaphores = signal_sems;
m_errorMonitor->SetDesiredError("VUID-VkBindSparseInfo-pSignalSemaphores-03249");
vk::QueueBindSparse(m_default_queue->handle(), 1, &submit_info2, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
}
// Check if we can test violations of maxTimelineSemaphoreValueDifference
if (timelineproperties.maxTimelineSemaphoreValueDifference < vvl::kU64Max) {
uint64_t bigValue = signalValue + timelineproperties.maxTimelineSemaphoreValueDifference + 1;
timeline_semaphore_submit_info.pSignalSemaphoreValues = &bigValue;
m_errorMonitor->SetDesiredError("VUID-VkBindSparseInfo-pSignalSemaphores-03251");
vk::QueueBindSparse(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
if (signalValue < vvl::kU64Max) {
waitValue = bigValue;
submit_info.signalSemaphoreCount = 0;
submit_info.waitSemaphoreCount = 1;
timeline_semaphore_submit_info.signalSemaphoreValueCount = 0;
timeline_semaphore_submit_info.waitSemaphoreValueCount = 1;
timeline_semaphore_submit_info.pWaitSemaphoreValues = &waitValue;
m_errorMonitor->SetDesiredError("VUID-VkBindSparseInfo-pWaitSemaphores-03250");
vk::QueueBindSparse(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
}
}
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, Sync2QueueSubmitTimelineSemaphoreValue) {
TEST_DESCRIPTION("Submit a queue with a timeline semaphore using a wrong payload value.");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceTimelineSemaphorePropertiesKHR timelineproperties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(timelineproperties);
uint64_t value = 5;
vkt::Semaphore semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE, value);
// Check for re-signalling an already completed value (5)
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo2-semaphore-03882");
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineSignal(semaphore, value), vkt::no_fence, true);
m_errorMonitor->VerifyFound();
// Submit (6)
value++;
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineSignal(semaphore, value), vkt::no_fence, true);
// Check against a pending value (6)
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo2-semaphore-03882");
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineSignal(semaphore, value), vkt::no_fence, true);
m_errorMonitor->VerifyFound();
// Double signal with the same value (7)
value++;
{
VkSemaphoreSubmitInfo signal_info = vku::InitStructHelper();
signal_info.value = value;
signal_info.semaphore = semaphore;
signal_info.stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
VkSemaphoreSubmitInfo double_signal_info[2];
double_signal_info[0] = signal_info;
double_signal_info[1] = signal_info;
VkSubmitInfo2 submit_info = vku::InitStructHelper();
submit_info.signalSemaphoreInfoCount = 2;
submit_info.pSignalSemaphoreInfos = double_signal_info;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo2-semaphore-03882");
vk::QueueSubmit2KHR(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
}
// Check if we can test violations of maxTimelineSemaphoreValueDifference
if (value < (value + timelineproperties.maxTimelineSemaphoreValueDifference + 1)) {
value += timelineproperties.maxTimelineSemaphoreValueDifference + 1;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo2-semaphore-03883");
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineSignal(semaphore, value), vkt::no_fence, true);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo2-semaphore-03884");
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineWait(semaphore, value), vkt::no_fence, true);
m_errorMonitor->VerifyFound();
}
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, QueueSubmitBinarySemaphoreNotSignaled) {
TEST_DESCRIPTION("Submit a queue with a waiting binary semaphore not previously signaled.");
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
VkSemaphoreCreateInfo semaphore_create_info = vku::InitStructHelper();
// VUIDs reported change if the extension is enabled, even if the timelineSemaphore feature isn't supported.
{
vkt::Semaphore semaphore_0(*m_device, semaphore_create_info);
vkt::Semaphore semaphore_1(*m_device, semaphore_create_info);
vkt::Semaphore semaphore_2(*m_device, semaphore_create_info);
VkPipelineStageFlags stage_flags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkSubmitInfo submit_info[3] = {};
submit_info[0] = vku::InitStructHelper();
submit_info[0].pWaitDstStageMask = &stage_flags;
submit_info[0].waitSemaphoreCount = 1;
submit_info[0].pWaitSemaphores = &semaphore_0.handle();
submit_info[0].signalSemaphoreCount = 1;
submit_info[0].pSignalSemaphores = &semaphore_1.handle();
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit-pWaitSemaphores-03238");
vk::QueueSubmit(m_default_queue->handle(), 1, submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
submit_info[1] = vku::InitStructHelper();
submit_info[1].pWaitDstStageMask = &stage_flags;
submit_info[1].waitSemaphoreCount = 1;
submit_info[1].pWaitSemaphores = &semaphore_1.handle();
submit_info[1].signalSemaphoreCount = 1;
submit_info[1].pSignalSemaphores = &semaphore_2.handle();
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit-pWaitSemaphores-03238");
vk::QueueSubmit(m_default_queue->handle(), 2, &submit_info[0], VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
submit_info[2] = vku::InitStructHelper();
submit_info[2].signalSemaphoreCount = 1;
submit_info[2].pSignalSemaphores = &semaphore_0.handle();
ASSERT_EQ(VK_SUCCESS, vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info[2], VK_NULL_HANDLE));
ASSERT_EQ(VK_SUCCESS, vk::QueueSubmit(m_default_queue->handle(), 2, submit_info, VK_NULL_HANDLE));
m_default_queue->Wait();
}
if (m_device->Physical().queue_properties_[m_default_queue->family_index].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) {
vkt::Semaphore semaphore_0(*m_device, semaphore_create_info);
vkt::Semaphore semaphore_1(*m_device, semaphore_create_info);
vkt::Semaphore semaphore_2(*m_device, semaphore_create_info);
VkBindSparseInfo bind_info[3] = {};
bind_info[0] = vku::InitStructHelper();
bind_info[0].waitSemaphoreCount = 1;
bind_info[0].pWaitSemaphores = &semaphore_0.handle();
bind_info[0].signalSemaphoreCount = 1;
bind_info[0].pSignalSemaphores = &semaphore_1.handle();
m_errorMonitor->SetDesiredError("VUID-vkQueueBindSparse-pWaitSemaphores-03245");
vk::QueueBindSparse(m_default_queue->handle(), 1, &bind_info[0], VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
bind_info[1] = vku::InitStructHelper();
bind_info[1].waitSemaphoreCount = 1;
bind_info[1].pWaitSemaphores = &semaphore_1.handle();
bind_info[1].signalSemaphoreCount = 1;
bind_info[1].pSignalSemaphores = &semaphore_2.handle();
m_errorMonitor->SetDesiredError("VUID-vkQueueBindSparse-pWaitSemaphores-03245");
vk::QueueBindSparse(m_default_queue->handle(), 2, bind_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
bind_info[2] = vku::InitStructHelper();
bind_info[2].signalSemaphoreCount = 1;
bind_info[2].pSignalSemaphores = &semaphore_0.handle();
ASSERT_EQ(VK_SUCCESS, vk::QueueBindSparse(m_default_queue->handle(), 1, &bind_info[2], VK_NULL_HANDLE));
ASSERT_EQ(VK_SUCCESS, vk::QueueBindSparse(m_default_queue->handle(), 2, bind_info, VK_NULL_HANDLE));
m_default_queue->Wait();
}
{
vkt::Semaphore semaphore[3];
semaphore[0].Init(*m_device, semaphore_create_info);
semaphore[1].Init(*m_device, semaphore_create_info);
semaphore[2].Init(*m_device, semaphore_create_info);
VkSemaphoreSubmitInfo sem_info[3];
for (int i = 0; i < 3; i++) {
sem_info[i] = vku::InitStructHelper();
sem_info[i].semaphore = semaphore[i];
sem_info[i].stageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
}
VkSubmitInfo2 submit_info[3] = {};
submit_info[0] = vku::InitStructHelper();
submit_info[0].waitSemaphoreInfoCount = 1;
submit_info[0].pWaitSemaphoreInfos = &sem_info[0];
submit_info[0].signalSemaphoreInfoCount = 1;
submit_info[0].pSignalSemaphoreInfos = &sem_info[1];
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit2-semaphore-03873");
vk::QueueSubmit2KHR(m_default_queue->handle(), 1, &submit_info[0], VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
submit_info[1] = vku::InitStructHelper();
submit_info[1].waitSemaphoreInfoCount = 1;
submit_info[1].pWaitSemaphoreInfos = &sem_info[1];
submit_info[1].signalSemaphoreInfoCount = 1;
submit_info[1].pSignalSemaphoreInfos = &sem_info[2];
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit2-semaphore-03873");
vk::QueueSubmit2KHR(m_default_queue->handle(), 2, submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
submit_info[2] = vku::InitStructHelper();
submit_info[2].signalSemaphoreInfoCount = 1;
submit_info[2].pSignalSemaphoreInfos = &sem_info[0];
ASSERT_EQ(VK_SUCCESS, vk::QueueSubmit2KHR(m_default_queue->handle(), 1, &submit_info[2], VK_NULL_HANDLE));
ASSERT_EQ(VK_SUCCESS, vk::QueueSubmit2KHR(m_default_queue->handle(), 2, submit_info, VK_NULL_HANDLE));
m_default_queue->Wait();
}
}
TEST_F(NegativeSyncObject, QueueSubmitTimelineSemaphoreOutOfOrder) {
TEST_DESCRIPTION("Submit out-of-order timeline semaphores.");
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "Two queues are needed to run this test";
}
vkt::Semaphore semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE, 5);
m_default_queue->Submit(vkt::no_cmd, vkt::TimelineWait(semaphore, 10), vkt::TimelineSignal(semaphore, 100));
m_second_queue->Submit(vkt::no_cmd, vkt::TimelineWait(semaphore, 0), vkt::TimelineSignal(semaphore, 10));
m_device->Wait();
}
TEST_F(NegativeSyncObject, WaitSemaphoresType) {
TEST_DESCRIPTION("Wait for a non Timeline Semaphore");
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
VkSemaphoreTypeCreateInfo semaphore_type_create_info = vku::InitStructHelper();
semaphore_type_create_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
VkSemaphoreCreateInfo semaphore_create_info = vku::InitStructHelper(&semaphore_type_create_info);
VkSemaphore semaphore[2];
vk::CreateSemaphore(device(), &semaphore_create_info, nullptr, &(semaphore[0]));
semaphore_type_create_info.semaphoreType = VK_SEMAPHORE_TYPE_BINARY;
vk::CreateSemaphore(device(), &semaphore_create_info, nullptr, &(semaphore[1]));
VkSemaphoreWaitInfo semaphore_wait_info = vku::InitStructHelper();
semaphore_wait_info.semaphoreCount = 2;
semaphore_wait_info.pSemaphores = &semaphore[0];
const uint64_t wait_values[] = {10, 40};
semaphore_wait_info.pValues = &wait_values[0];
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreWaitInfo-pSemaphores-03256");
vk::WaitSemaphoresKHR(device(), &semaphore_wait_info, 10000);
m_errorMonitor->VerifyFound();
vk::DestroySemaphore(device(), semaphore[0], nullptr);
vk::DestroySemaphore(device(), semaphore[1], nullptr);
}
TEST_F(NegativeSyncObject, SignalSemaphoreType) {
TEST_DESCRIPTION("Signal a non Timeline Semaphore");
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
vkt::Semaphore semaphore(*m_device);
VkSemaphoreSignalInfo semaphore_signal_info = vku::InitStructHelper();
semaphore_signal_info.semaphore = semaphore;
semaphore_signal_info.value = 10;
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreSignalInfo-semaphore-03257");
vk::SignalSemaphoreKHR(device(), &semaphore_signal_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, SignalSemaphoreValue) {
TEST_DESCRIPTION("Signal a Timeline Semaphore with invalid values");
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceTimelineSemaphorePropertiesKHR timelineproperties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(timelineproperties);
vkt::Semaphore timeline0(*m_device, VK_SEMAPHORE_TYPE_TIMELINE, 5);
vkt::Semaphore timeline1(*m_device, VK_SEMAPHORE_TYPE_TIMELINE, 5);
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreSignalInfo-value-03258");
timeline0.SignalKHR(3);
m_errorMonitor->VerifyFound();
timeline0.SignalKHR(10);
m_default_queue->Submit(vkt::no_cmd, vkt::TimelineWait(timeline1, 10), vkt::TimelineSignal(timeline0, 20));
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreSignalInfo-value-03259");
timeline0.SignalKHR(25);
m_errorMonitor->VerifyFound();
timeline0.SignalKHR(15);
timeline1.SignalKHR(15);
// Test violations of maxTimelineSemaphoreValueDifference
if (timelineproperties.maxTimelineSemaphoreValueDifference < vvl::kU64Max) {
vkt::Semaphore sem(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreSignalInfo-value-03260");
sem.SignalKHR(timelineproperties.maxTimelineSemaphoreValueDifference + 1);
m_errorMonitor->VerifyFound();
sem.SignalKHR(timelineproperties.maxTimelineSemaphoreValueDifference);
m_default_queue->Wait();
}
// Regression test for value difference validations ran against binary semaphores
{
vkt::Semaphore timeline_sem(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
vkt::Semaphore binary_sem(*m_device);
uint64_t signalValue = 1;
uint64_t offendingValue = timelineproperties.maxTimelineSemaphoreValueDifference + 1;
VkTimelineSemaphoreSubmitInfo timeline_semaphore_submit_info = vku::InitStructHelper();
timeline_semaphore_submit_info.waitSemaphoreValueCount = 1;
timeline_semaphore_submit_info.pWaitSemaphoreValues = &signalValue;
// These two assignments are not required by the spec, but would segfault on older versions of validation layers
timeline_semaphore_submit_info.signalSemaphoreValueCount = 1;
timeline_semaphore_submit_info.pSignalSemaphoreValues = &offendingValue;
VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkSubmitInfo submit_info = vku::InitStructHelper(&timeline_semaphore_submit_info);
submit_info.pWaitDstStageMask = &stageFlags;
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &timeline_sem.handle();
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &binary_sem.handle();
vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
timeline_sem.SignalKHR(signalValue);
m_default_queue->Wait();
}
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, Sync2SignalSemaphoreValue) {
TEST_DESCRIPTION("Signal a Timeline Semaphore with invalid values");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceTimelineSemaphorePropertiesKHR timelineproperties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(timelineproperties);
VkSemaphoreTypeCreateInfo semaphore_type_create_info = vku::InitStructHelper();
semaphore_type_create_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
semaphore_type_create_info.initialValue = 5;
VkSemaphoreCreateInfo semaphore_create_info = vku::InitStructHelper(&semaphore_type_create_info);
vkt::Semaphore semaphore_0(*m_device, semaphore_create_info);
vkt::Semaphore semaphore_1(*m_device, semaphore_create_info);
VkSemaphoreSignalInfo semaphore_signal_info = vku::InitStructHelper();
semaphore_signal_info.semaphore = semaphore_0;
semaphore_signal_info.value = 10;
ASSERT_EQ(VK_SUCCESS, vk::SignalSemaphore(device(), &semaphore_signal_info));
VkSemaphoreSubmitInfo signal_info = vku::InitStructHelper();
signal_info.semaphore = semaphore_0;
VkSemaphoreSubmitInfo wait_info = vku::InitStructHelper();
wait_info.semaphore = semaphore_0;
wait_info.stageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkSubmitInfo2 submit_info = vku::InitStructHelper();
submit_info.signalSemaphoreInfoCount = 1;
submit_info.pSignalSemaphoreInfos = &signal_info;
submit_info.waitSemaphoreInfoCount = 1;
submit_info.pWaitSemaphoreInfos = &wait_info;
// signal value > wait value
signal_info.value = 11;
wait_info.value = 11;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo2-semaphore-03881");
vk::QueueSubmit2KHR(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
// signal value == current value
signal_info.value = 10;
wait_info.value = 5;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo2-semaphore-03882");
vk::QueueSubmit2KHR(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
signal_info.value = 20;
wait_info.value = 15;
wait_info.semaphore = semaphore_1;
ASSERT_EQ(VK_SUCCESS, vk::QueueSubmit2KHR(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE));
semaphore_signal_info.value = 25;
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreSignalInfo-value-03259");
vk::SignalSemaphore(device(), &semaphore_signal_info);
m_errorMonitor->VerifyFound();
semaphore_signal_info.value = 15;
ASSERT_EQ(VK_SUCCESS, vk::SignalSemaphore(device(), &semaphore_signal_info));
semaphore_signal_info.semaphore = semaphore_1;
ASSERT_EQ(VK_SUCCESS, vk::SignalSemaphore(device(), &semaphore_signal_info));
// Check if we can test violations of maxTimelineSemaphoreValueDifference
if (timelineproperties.maxTimelineSemaphoreValueDifference < vvl::kU64Max) {
// Regression test for value difference validations ran against binary semaphores
semaphore_type_create_info.initialValue = 0;
vkt::Semaphore timeline_sem(*m_device, semaphore_create_info);
vkt::Semaphore binary_sem(*m_device);
wait_info.semaphore = timeline_sem;
wait_info.value = 1;
signal_info.semaphore = binary_sem;
signal_info.value = timelineproperties.maxTimelineSemaphoreValueDifference + 1;
vk::QueueSubmit2KHR(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
semaphore_signal_info.semaphore = timeline_sem;
semaphore_signal_info.value = 1;
vk::SignalSemaphore(device(), &semaphore_signal_info);
m_default_queue->Wait();
}
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, SemaphoreCounterType) {
TEST_DESCRIPTION("Get payload from a non Timeline Semaphore");
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
vkt::Semaphore semaphore(*m_device);
uint64_t value = 0xdeadbeef;
m_errorMonitor->SetDesiredError("VUID-vkGetSemaphoreCounterValue-semaphore-03255");
vk::GetSemaphoreCounterValueKHR(device(), semaphore, &value);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, EventStageMaskOneCommandBufferPass) {
RETURN_IF_SKIP(Init());
vkt::Event event(*m_device);
m_command_buffer.Begin();
vk::CmdSetEvent(m_command_buffer, event, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, nullptr, 0, nullptr, 0, nullptr);
m_command_buffer.End();
m_default_queue->SubmitAndWait(m_command_buffer);
}
TEST_F(NegativeSyncObject, EventStageMaskOneCommandBufferFail) {
RETURN_IF_SKIP(Init());
vkt::Event event(*m_device);
m_command_buffer.Begin();
vk::CmdSetEvent(m_command_buffer, event, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
// wrong srcStageMask
m_errorMonitor->SetAllowedFailureMsg("VUID-vkCmdWaitEvents-srcStageMask-01158");
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0, nullptr, 0, nullptr, 0, nullptr);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents-srcStageMask-parameter");
m_default_queue->Submit(m_command_buffer);
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, EventStageMaskTwoCommandBufferPass) {
RETURN_IF_SKIP(Init());
vkt::CommandBuffer commandBuffer1(*m_device, m_command_pool);
vkt::CommandBuffer commandBuffer2(*m_device, m_command_pool);
vkt::Event event(*m_device);
commandBuffer1.Begin();
vk::CmdSetEvent(commandBuffer1, event, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
commandBuffer1.End();
m_default_queue->Submit(commandBuffer1);
commandBuffer2.Begin();
vk::CmdWaitEvents(commandBuffer2, 1, &event.handle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, nullptr, 0, nullptr, 0, nullptr);
commandBuffer2.End();
m_default_queue->Submit(commandBuffer2);
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, EventStageMaskTwoCommandBufferFail) {
RETURN_IF_SKIP(Init());
vkt::CommandBuffer commandBuffer1(*m_device, m_command_pool);
vkt::CommandBuffer commandBuffer2(*m_device, m_command_pool);
vkt::Event event(*m_device);
commandBuffer1.Begin();
vk::CmdSetEvent(commandBuffer1, event, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
commandBuffer1.End();
m_default_queue->Submit(commandBuffer1);
commandBuffer2.Begin();
// wrong srcStageMask
vk::CmdWaitEvents(commandBuffer2, 1, &event.handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0, nullptr, 0, nullptr, 0, nullptr);
commandBuffer2.End();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents-srcStageMask-parameter");
m_default_queue->Submit(commandBuffer2);
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, DetectInterQueueEventUsage) {
TEST_DESCRIPTION("Sets event on one queue and tries to wait on a different queue (CmdSetEvent/CmdWaitEvents)");
all_queue_count_ = true;
RETURN_IF_SKIP(Init());
if ((m_second_queue_caps & VK_QUEUE_GRAPHICS_BIT) == 0) {
GTEST_SKIP() << "2 graphics queues are needed";
}
const vkt::Event event(*m_device);
vkt::CommandBuffer cb1(*m_device, m_command_pool);
cb1.Begin();
vk::CmdSetEvent(cb1, event, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
cb1.End();
vkt::CommandPool pool2(*m_device, m_second_queue->family_index);
vkt::CommandBuffer cb2(*m_device, pool2);
cb2.Begin();
vk::CmdWaitEvents(cb2, 1, &event.handle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, nullptr,
0, nullptr, 0, nullptr);
cb2.End();
m_default_queue->Submit(cb1);
m_errorMonitor->SetDesiredError("UNASSIGNED-SubmitValidation-WaitEvents-WrongQueue");
m_second_queue->Submit(cb2);
m_errorMonitor->VerifyFound();
m_device->Wait();
}
TEST_F(NegativeSyncObject, DetectInterQueueEventUsage2) {
TEST_DESCRIPTION("Sets event on one queue and tries to wait on a different queue (CmdSetEvent2/CmdWaitEvents2)");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::synchronization2);
all_queue_count_ = true;
RETURN_IF_SKIP(Init());
if ((m_second_queue_caps & VK_QUEUE_GRAPHICS_BIT) == 0) {
GTEST_SKIP() << "2 graphics queues are needed";
}
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcAccessMask = 0;
barrier.dstAccessMask = 0;
barrier.srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_NONE;
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.memoryBarrierCount = 1;
dependency_info.pMemoryBarriers = &barrier;
const vkt::Event event(*m_device);
vkt::CommandBuffer cb1(*m_device, m_command_pool);
cb1.Begin();
vk::CmdSetEvent2(cb1, event, &dependency_info);
cb1.End();
vkt::CommandPool pool2(*m_device, m_second_queue->family_index);
vkt::CommandBuffer cb2(*m_device, pool2);
cb2.Begin();
vk::CmdWaitEvents2(cb2, 1, &event.handle(), &dependency_info);
cb2.End();
m_default_queue->Submit(cb1);
m_errorMonitor->SetDesiredError("UNASSIGNED-SubmitValidation-WaitEvents-WrongQueue");
m_second_queue->Submit(cb2);
m_errorMonitor->VerifyFound();
m_device->Wait();
}
TEST_F(NegativeSyncObject, SignalSignaledSemaphore) {
TEST_DESCRIPTION("Call VkQueueSubmit with a semaphore that is already signaled but not waited on by the queue.");
RETURN_IF_SKIP(Init());
vkt::Semaphore semaphore(*m_device);
// Signal semaphore
vkt::CommandBuffer cb(*m_device, m_command_pool);
cb.Begin();
cb.End();
m_default_queue->Submit(cb, vkt::Signal(semaphore));
// Signal again
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit-pSignalSemaphores-00067");
m_default_queue->Submit(vkt::no_cmd, vkt::Signal(semaphore));
m_errorMonitor->VerifyFound();
m_device->Wait();
}
TEST_F(NegativeSyncObject, PipelineStageConditionalRenderingWithWrongQueue) {
TEST_DESCRIPTION("Run CmdPipelineBarrier with VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT and wrong VkQueueFlagBits");
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::conditionalRendering);
RETURN_IF_SKIP(Init());
auto only_transfer_queueFamilyIndex = m_device->TransferOnlyQueueFamily();
if (!only_transfer_queueFamilyIndex.has_value()) {
GTEST_SKIP() << "Transfer only queue is not supported";
}
vkt::Image image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::CommandPool commandPool(*m_device, only_transfer_queueFamilyIndex.value());
vkt::CommandBuffer commandBuffer(*m_device, commandPool);
commandBuffer.Begin();
VkImageMemoryBarrier imb = vku::InitStructHelper();
imb.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
imb.dstAccessMask = VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT;
imb.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
imb.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
imb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imb.image = image;
imb.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-srcStageMask-06461");
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-dstStageMask-06462");
vk::CmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT, 0,
0, nullptr, 0, nullptr, 1, &imb);
m_errorMonitor->VerifyFound();
commandBuffer.End();
}
TEST_F(NegativeSyncObject, WaitOnNoEvent) {
RETURN_IF_SKIP(Init());
VkEvent bad_event = CastToHandle<VkEvent, uintptr_t>(0xbaadbeef);
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents-pEvents-parameter");
vk::CmdWaitEvents(m_command_buffer, 1, &bad_event, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr,
0, nullptr, 0, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, InvalidDeviceOnlyEvent) {
TEST_DESCRIPTION("Attempt to use device only event with host commands.");
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkEventCreateInfo event_ci = vku::InitStructHelper();
event_ci.flags = VK_EVENT_CREATE_DEVICE_ONLY_BIT;
vkt::Event ev(*m_device, event_ci);
m_errorMonitor->SetDesiredError("VUID-vkResetEvent-event-03823");
vk::ResetEvent(*m_device, ev);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkSetEvent-event-03941");
vk::SetEvent(*m_device, ev);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, SetEvent2DependencyFlags) {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
vkt::Event event(*m_device);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent2-dependencyFlags-03825");
vk::CmdSetEvent2(m_command_buffer, event, &dependency_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, SetEvent2HostStage) {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
barrier.srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.memoryBarrierCount = 1;
dependency_info.pMemoryBarriers = &barrier;
vkt::Event event(*m_device);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent2-srcStageMask-09391"); // src
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent2-dstStageMask-09392"); // dst
vk::CmdSetEvent2(m_command_buffer, event, &dependency_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, SetEvent2HostStageKHR) {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
barrier.srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.memoryBarrierCount = 1;
dependency_info.pMemoryBarriers = &barrier;
vkt::Event event(*m_device);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent2-srcStageMask-09391"); // src
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent2-dstStageMask-09392"); // dst
vk::CmdSetEvent2KHR(m_command_buffer, event, &dependency_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, WaitEventRenderPassHostBit) {
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vkt::Event event(*m_device);
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents-srcStageMask-07308");
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, nullptr,
0, nullptr, 0, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, StageMaskHost) {
TEST_DESCRIPTION("Test invalid usage of VK_PIPELINE_STAGE_HOST_BIT.");
RETURN_IF_SKIP(Init());
vkt::Event event(*m_device);
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent-stageMask-01149");
vk::CmdSetEvent(m_command_buffer, event, VK_PIPELINE_STAGE_HOST_BIT);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdResetEvent-stageMask-01153");
vk::CmdResetEvent(m_command_buffer, event, VK_PIPELINE_STAGE_HOST_BIT);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
vkt::Semaphore semaphore(*m_device);
// Signal the semaphore so we can wait on it.
m_default_queue->Submit(vkt::no_cmd, vkt::Signal(semaphore));
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pWaitDstStageMask-00078");
m_default_queue->Submit(vkt::no_cmd, vkt::Wait(semaphore, VK_PIPELINE_STAGE_HOST_BIT));
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, ResetEventThenSet) {
TEST_DESCRIPTION("Reset an event then set it after the reset has been submitted.");
RETURN_IF_SKIP(Init());
vkt::Event event(*m_device);
m_command_buffer.Begin();
vk::CmdResetEvent(m_command_buffer, event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
m_command_buffer.End();
m_default_queue->Submit(m_command_buffer);
m_errorMonitor->SetDesiredError("VUID-vkSetEvent-event-09543");
vk::SetEvent(device(), event);
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
}
// This test should only be used for manual inspection
// Because a command buffer with vkCmdWaitEvents is submitted with an
// event that is never signaled, the test results in a VK_ERROR_DEVICE_LOST
TEST_F(NegativeSyncObject, DISABLED_WaitEventThenSet) {
#if defined(VVL_ENABLE_TSAN)
// NOTE: This test in particular has failed sporadically on CI when TSAN is enabled.
GTEST_SKIP() << "https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/5965";
#endif
TEST_DESCRIPTION("Wait on a event then set it after the wait has been submitted.");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
vkt::Event event(*m_device);
m_command_buffer.Begin();
vk::CmdWaitEvents(m_command_buffer, 1, &event.handle(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0,
nullptr, 0, nullptr, 0, nullptr);
vk::CmdResetEvent(m_command_buffer, event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
m_command_buffer.End();
m_default_queue->Submit(m_command_buffer);
m_errorMonitor->SetDesiredError("VUID-vkSetEvent-event-09543");
vk::SetEvent(device(), event);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, RenderPassPipelineBarrierGraphicsStage) {
TEST_DESCRIPTION("Use non-graphics pipeline stage inside a renderpass");
RETURN_IF_SKIP(Init());
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL});
rp.AddColorAttachment(0);
rp.AddSubpassDependency();
rp.CreateRenderPass();
vkt::Image image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView view = image.CreateView();
vkt::Framebuffer fb(*m_device, rp, 1, &view.handle());
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp, fb);
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-None-07889");
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-None-07889");
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-None-07892");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0,
nullptr, 0, nullptr, 0, nullptr);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, MemoryBarrierStageNotSupportedByQueue) {
TEST_DESCRIPTION("Memory barrier uses pipeline stages not supported by the queue family");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
std::optional<uint32_t> transfer_only_family = m_device->TransferOnlyQueueFamily();
if (!transfer_only_family.has_value()) {
GTEST_SKIP() << "Transfer-only queue family is required";
}
vkt::CommandPool transfer_pool(*m_device, transfer_only_family.value());
vkt::CommandBuffer transfer_cb(*m_device, transfer_pool);
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
VkMemoryBarrier2 barrier_src_gfx = vku::InitStructHelper();
barrier_src_gfx.srcStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; // graphics stage
barrier_src_gfx.srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
barrier_src_gfx.dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT;
barrier_src_gfx.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
VkMemoryBarrier2 barrier_dst_gfx = vku::InitStructHelper();
barrier_dst_gfx.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT;
barrier_dst_gfx.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
barrier_dst_gfx.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; // graphics stage
barrier_dst_gfx.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
transfer_cb.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-srcStageMask-09673");
transfer_cb.Barrier(barrier_src_gfx);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-dstStageMask-09674");
transfer_cb.Barrier(barrier_dst_gfx);
m_errorMonitor->VerifyFound();
transfer_cb.End();
}
TEST_F(NegativeSyncObject, BufferBarrierStageNotSupportedByQueue) {
TEST_DESCRIPTION("Buffer memory barrier without ownership transfer uses pipeline stages not supported by the queue family");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
std::optional<uint32_t> compute_only_family = m_device->ComputeOnlyQueueFamily();
if (!compute_only_family.has_value()) {
GTEST_SKIP() << "Compute-only queue family is required";
}
vkt::CommandPool compute_pool(*m_device, compute_only_family.value());
vkt::CommandBuffer compute_cb(*m_device, compute_pool);
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
VkBufferMemoryBarrier2 barrier_src_gfx = vku::InitStructHelper();
barrier_src_gfx.srcStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; // graphics stage
barrier_src_gfx.srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
barrier_src_gfx.dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT;
barrier_src_gfx.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
barrier_src_gfx.buffer = buffer;
barrier_src_gfx.offset = 0;
barrier_src_gfx.size = 256;
VkBufferMemoryBarrier2 barrier_dst_gfx = vku::InitStructHelper();
barrier_dst_gfx.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT;
barrier_dst_gfx.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
barrier_dst_gfx.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; // graphics stage
barrier_dst_gfx.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
barrier_dst_gfx.buffer = buffer;
barrier_dst_gfx.offset = 0;
barrier_dst_gfx.size = 256;
compute_cb.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-srcStageMask-09675");
compute_cb.Barrier(barrier_src_gfx);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-dstStageMask-09676");
compute_cb.Barrier(barrier_dst_gfx);
m_errorMonitor->VerifyFound();
compute_cb.End();
}
TEST_F(NegativeSyncObject, BufferOwnershipTransferStageNotSupportedByQueue) {
TEST_DESCRIPTION("Buffer memory barrier with ownership transfer uses pipeline stages not supported by the queue family");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::synchronization2);
// Enable feature to use stage other than ALL_COMMANDS during ownership transfer
AddRequiredExtensions(VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::maintenance8);
RETURN_IF_SKIP(Init());
std::optional<uint32_t> transfer_only_family = m_device->TransferOnlyQueueFamily();
if (!transfer_only_family.has_value()) {
GTEST_SKIP() << "Transfer-only queue family is required";
}
vkt::CommandPool transfer_pool(*m_device, transfer_only_family.value(), VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
vkt::CommandBuffer transfer_cb(*m_device, transfer_pool);
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
// Acquire operation on transfer queue.
// The src stage should be a valid transfer stage.
VkBufferMemoryBarrier2 acquire_barrier = vku::InitStructHelper();
acquire_barrier.srcStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; // Not a valid transfer stage
acquire_barrier.srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
acquire_barrier.dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT;
acquire_barrier.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
acquire_barrier.srcQueueFamilyIndex = m_default_queue->family_index;
acquire_barrier.dstQueueFamilyIndex = transfer_only_family.value();
acquire_barrier.buffer = buffer;
acquire_barrier.offset = 0;
acquire_barrier.size = 256;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-srcStageMask-09675");
transfer_cb.Begin();
// Use dependency flag to be able to use src stage other then ALL_COMMAND
transfer_cb.Barrier(acquire_barrier, VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR);
transfer_cb.End();
m_errorMonitor->VerifyFound();
// Release operation on transfer queue.
// The dst stage should be a valid transfer stage.
VkBufferMemoryBarrier2 release_barrier = vku::InitStructHelper();
release_barrier.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT;
release_barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
release_barrier.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; // Not valid transfer stage
release_barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
release_barrier.srcQueueFamilyIndex = transfer_only_family.value();
release_barrier.dstQueueFamilyIndex = m_default_queue->family_index;
release_barrier.buffer = buffer;
release_barrier.offset = 0;
release_barrier.size = 256;
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-dstStageMask-09676");
transfer_cb.Begin();
// Use dependency flag to be able to use dst stage other then ALL_COMMAND
transfer_cb.Barrier(release_barrier, VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR);
transfer_cb.End();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, BarrierOwnershipTransferUseAllStages) {
SetTargetApiVersion(VK_API_VERSION_1_1);
// Enable extension but do not enable maintenance8 feature
AddRequiredExtensions(VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
vkt::Buffer buffer(*m_device, 256, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
VkBufferMemoryBarrier barrier = vku::InitStructHelper();
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.buffer = buffer;
barrier.offset = 0;
barrier.size = 256;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-maintenance8-10206");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR, 0, nullptr, 1, &barrier, 0,
nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, EventOwnershipTransferUseAllStagesNoFeature) {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::synchronization2);
// Enable extension but do not enable maintenance8 feature
AddRequiredExtensions(VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
vkt::Event event(*m_device);
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.dependencyFlags = VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents2-dependencyFlags-10394");
vk::CmdWaitEvents2(m_command_buffer, 1, &event.handle(), &dependency_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, EventOwnershipTransferUseAllStages) {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredExtensions(VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::maintenance8);
RETURN_IF_SKIP(Init());
vkt::Event event(*m_device);
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.dependencyFlags =
VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR | VK_DEPENDENCY_VIEW_LOCAL_BIT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents2-maintenance8-10205");
vk::CmdWaitEvents2(m_command_buffer, 1, &event.handle(), &dependency_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, ImageBarrierStageNotSupportedByQueue) {
TEST_DESCRIPTION("Image memory barrier without ownership transfer uses pipeline stages not supported by the queue family");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
std::optional<uint32_t> compute_only_family = m_device->ComputeOnlyQueueFamily();
if (!compute_only_family.has_value()) {
GTEST_SKIP() << "Compute-only queue family is required";
}
vkt::CommandPool compute_pool(*m_device, compute_only_family.value());
vkt::CommandBuffer compute_cb(*m_device, compute_pool);
vkt::Image image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
VkImageMemoryBarrier2 barrier_src_gfx = vku::InitStructHelper();
barrier_src_gfx.srcStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; // graphics stage
barrier_src_gfx.srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
barrier_src_gfx.dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT;
barrier_src_gfx.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
barrier_src_gfx.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier_src_gfx.newLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier_src_gfx.image = image;
barrier_src_gfx.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
VkImageMemoryBarrier2 barrier_dst_gfx = vku::InitStructHelper();
barrier_dst_gfx.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT;
barrier_dst_gfx.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
barrier_dst_gfx.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; // graphics stage
barrier_dst_gfx.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
barrier_dst_gfx.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier_dst_gfx.newLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier_dst_gfx.image = image;
barrier_dst_gfx.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
compute_cb.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-srcStageMask-09675");
compute_cb.Barrier(barrier_src_gfx);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-dstStageMask-09676");
compute_cb.Barrier(barrier_dst_gfx);
m_errorMonitor->VerifyFound();
compute_cb.End();
}
TEST_F(NegativeSyncObject, TimelineTwoHostSignals) {
TEST_DESCRIPTION("Signal on the host two times");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
vkt::Semaphore semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
semaphore.Signal(2);
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreSignalInfo-value-03258");
semaphore.Signal(1);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, TimelineHostSignalAndInUseTracking) {
TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8476");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
vkt::Semaphore semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
VkSemaphore handle = semaphore;
m_default_queue->Submit(vkt::no_cmd, vkt::TimelineWait(semaphore, 1));
semaphore.Signal(1); // signal should not initiate forward progress on the queue thread
// In the case of regression, this delay gives the queue thread additional time to mark
// the semaphore as not in use which will fail the following check. If the queue thread
// was not fast enough the test will pass without detecting regression (false-negative).
std::this_thread::sleep_for(std::chrono::milliseconds{50});
m_errorMonitor->SetDesiredError("VUID-vkDestroySemaphore-semaphore-05149");
semaphore.Destroy();
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
vk::DestroySemaphore(*m_device, handle, nullptr);
}
TEST_F(NegativeSyncObject, TimelineSubmitSignalAndInUseTracking) {
TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8370");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
all_queue_count_ = true;
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "2 queues are needed";
}
vkt::Semaphore semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
VkSemaphore handle = semaphore;
m_default_queue->Submit(vkt::no_cmd, vkt::TimelineWait(semaphore, 1));
m_second_queue->Submit(vkt::no_cmd, vkt::TimelineSignal(semaphore, 1));
// Waiting for the second (signaling) queue should not initiate queue thread forward
// progress on the default (waiting) queue.
m_second_queue->Wait();
// In the case of regression, this delay gives the queue thread additional time to mark
// the semaphore as not in use which will fail the following check. If the queue thread
// was not fast enough the test will pass without detecting regression (false-negative).
std::this_thread::sleep_for(std::chrono::milliseconds{50});
m_errorMonitor->SetDesiredError("VUID-vkDestroySemaphore-semaphore-05149");
semaphore.Destroy();
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
vk::DestroySemaphore(*m_device, handle, nullptr);
}
TEST_F(NegativeSyncObject, TimelineCannotFixBinaryWaitBeforeSignal) {
TEST_DESCRIPTION("Binary signal should be submitted before binary wait. Timeline can't help with ordering");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "Two queues are needed";
}
vkt::Semaphore timeline_semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
vkt::Semaphore binary_semaphore(*m_device);
// Although timeline wait postpones binary wait, the specification still does not
// allow to submit binary wait before binary signal
// https://gitlab.khronos.org/vulkan/vulkan/-/issues/4046
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineWait(timeline_semaphore, 1));
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit2-semaphore-03873");
m_default_queue->Submit2(vkt::no_cmd, vkt::Wait(binary_semaphore));
m_errorMonitor->VerifyFound();
m_second_queue->Submit2(vkt::no_cmd, vkt::Signal(binary_semaphore));
m_second_queue->Submit2(vkt::no_cmd, vkt::TimelineSignal(timeline_semaphore, 1));
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, DecreasingTimelineSignals) {
TEST_DESCRIPTION("Signal timeline value smaller than previous signal");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
vkt::Semaphore semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
m_default_queue->Submit(vkt::no_cmd, vkt::TimelineSignal(semaphore, 2));
// NOTE: VerifyFound goes after Wait because validation is performed by the Queue thread
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pSignalSemaphores-03242");
m_default_queue->Submit(vkt::no_cmd, vkt::TimelineSignal(semaphore, 1));
m_default_queue->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, TimelineHostSignalLargerThanPendingSignal) {
TEST_DESCRIPTION("Timeline host signal can't be larger than pending signal");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
vkt::Semaphore semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineSignal(semaphore, 2));
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreSignalInfo-value-03259");
semaphore.Signal(3);
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, TimelineHostSignalLargerThanPendingSignal2) {
TEST_DESCRIPTION("Timeline host signal can't be larger than pending signal");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "2 queues are needed";
}
vkt::Semaphore semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineWait(semaphore, 2), vkt::TimelineSignal(semaphore, 4));
m_second_queue->Submit2(vkt::no_cmd, vkt::TimelineSignal(semaphore, 2));
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreSignalInfo-value-03259");
semaphore.Signal(3);
m_errorMonitor->VerifyFound();
m_device->Wait();
}
TEST_F(NegativeSyncObject, DifferentSignalingOrderThanSubmitOrder) {
TEST_DESCRIPTION("Timeline values are increasing in submit order but reordered by wait-before-signal at runtime");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "2 queues are needed";
}
vkt::Semaphore semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
m_default_queue->Submit(vkt::no_cmd, vkt::TimelineWait(semaphore, 1));
m_default_queue->Submit(vkt::no_cmd, vkt::TimelineSignal(semaphore, 2));
// Signal 3 resolves wait 1 then value 2 is signaled
// NOTE: VerifyFound goes after Wait because validation is performed by the Queue thread
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pSignalSemaphores-03242");
m_second_queue->Submit(vkt::no_cmd, vkt::TimelineSignal(semaphore, 3));
m_default_queue->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, DifferentSignalingOrderThanSubmitOrder2) {
TEST_DESCRIPTION("Timeline values are increasing in submit order but reordered by wait-before-signal at runtime");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "2 queues are needed";
}
vkt::Semaphore semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineWait(semaphore, 1));
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineSignal(semaphore, 1));
// Signal 3 resolves wait 1 then value 1 is signaled
// NOTE: VerifyFound goes after Wait because validation is performed by the Queue thread
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo2-semaphore-03882");
m_second_queue->Submit2(vkt::no_cmd, vkt::TimelineSignal(semaphore, 3));
m_default_queue->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeSyncObject, BinarySyncDependsOnTimelineWait) {
TEST_DESCRIPTION("Binary semaphore signal->wait after timeline wait-before-signal");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "Two queues are needed";
}
vkt::Semaphore timeline_semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
vkt::Semaphore binary_semaphore(*m_device);
m_default_queue->Submit(vkt::no_cmd, vkt::TimelineWait(timeline_semaphore, 1));
m_default_queue->Submit(vkt::no_cmd, vkt::Signal(binary_semaphore));
// There is a matching binary signal for this wait, but that signal depends on another not yet submitted timeline signal
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit-pWaitSemaphores-03238");
m_default_queue->Submit(vkt::no_cmd, vkt::Wait(binary_semaphore));
m_errorMonitor->VerifyFound();
m_second_queue->Submit(vkt::no_cmd, vkt::TimelineSignal(timeline_semaphore, 1));
m_device->Wait();
}
TEST_F(NegativeSyncObject, BinarySyncDependsOnTimelineWait2) {
TEST_DESCRIPTION("Binary semaphore signal-wait depends on timeline wait-before-signal");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "Two queues are needed";
}
vkt::Semaphore timeline_semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
vkt::Semaphore binary_semaphore(*m_device);
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineWait(timeline_semaphore, 1), vkt::Signal(binary_semaphore));
// There is a matching binary signal for this wait, but that signal depends on another not yet submitted timeline signal
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit2-semaphore-03873");
m_default_queue->Submit2(vkt::no_cmd, vkt::Wait(binary_semaphore));
m_errorMonitor->VerifyFound();
m_second_queue->Submit2(vkt::no_cmd, vkt::TimelineSignal(timeline_semaphore, 1));
m_device->Wait();
}
TEST_F(NegativeSyncObject, BinarySyncDependsOnTimelineWait3) {
TEST_DESCRIPTION("Binary semaphore signal-wait depends on timeline wait-before-signal");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "Two queues are needed";
}
vkt::Semaphore timeline_semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
vkt::Semaphore timeline_semaphore2(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
vkt::Semaphore binary_semaphore(*m_device);
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineWait(timeline_semaphore, 1), vkt::TimelineSignal(timeline_semaphore2, 1));
m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineWait(timeline_semaphore2, 1), vkt::Signal(binary_semaphore));
// There is a matching binary signal for this wait, but that signal depends on another not yet submitted timeline signal
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit2-semaphore-03873");
m_default_queue->Submit2(vkt::no_cmd, vkt::Wait(binary_semaphore));
m_errorMonitor->VerifyFound();
m_second_queue->Submit2(vkt::no_cmd, vkt::TimelineSignal(timeline_semaphore, 1));
m_device->Wait();
}
TEST_F(NegativeSyncObject, BinarySyncDependsOnTimelineWait4) {
TEST_DESCRIPTION("Binary semaphore signal-wait depends on timeline wait-before-signal. Use sparse binding operation");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "Two queues are needed";
}
if (!(m_default_queue_caps & VK_QUEUE_SPARSE_BINDING_BIT)) {
GTEST_SKIP() << "Graphics queue does not have sparse binding bit";
}
vkt::Semaphore timeline_semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
vkt::Semaphore binary_semaphore(*m_device);
m_default_queue->Submit(vkt::no_cmd, vkt::TimelineWait(timeline_semaphore, 1));
m_default_queue->Submit(vkt::no_cmd, vkt::Signal(binary_semaphore));
VkBindSparseInfo bind_info = vku::InitStructHelper();
bind_info.waitSemaphoreCount = 1;
bind_info.pWaitSemaphores = &binary_semaphore.handle();
m_errorMonitor->SetDesiredError("VUID-vkQueueBindSparse-pWaitSemaphores-03245");
vk::QueueBindSparse(*m_default_queue, 1, &bind_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
m_second_queue->Submit(vkt::no_cmd, vkt::TimelineSignal(timeline_semaphore, 1));
m_device->Wait();
}
TEST_F(NegativeSyncObject, BinarySyncDependsOnTimelineWait5) {
TEST_DESCRIPTION("Binary semaphore signal-wait depends on timeline wait-before-signal. Use sparse binding operation");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "Two queues are needed";
}
if (!(m_default_queue_caps & VK_QUEUE_SPARSE_BINDING_BIT)) {
GTEST_SKIP() << "Graphics queue does not have sparse binding bit";
}
vkt::Semaphore timeline_semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
vkt::Semaphore binary_semaphore(*m_device);
// Submit timeline signal using sparse submit
const uint64_t timeline_value = 1;
VkTimelineSemaphoreSubmitInfo timeline_submit_info = vku::InitStructHelper();
timeline_submit_info.waitSemaphoreValueCount = 1;
timeline_submit_info.pWaitSemaphoreValues = &timeline_value;
VkBindSparseInfo bind_info = vku::InitStructHelper(&timeline_submit_info);
bind_info.waitSemaphoreCount = 1;
bind_info.pWaitSemaphores = &timeline_semaphore.handle();
vk::QueueBindSparse(*m_default_queue, 1, &bind_info, VK_NULL_HANDLE);
m_default_queue->Submit2(vkt::no_cmd, vkt::Signal(binary_semaphore));
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit2-semaphore-03873");
m_default_queue->Submit2(vkt::no_cmd, vkt::Wait(binary_semaphore));
m_errorMonitor->VerifyFound();
m_second_queue->Submit(vkt::no_cmd, vkt::TimelineSignal(timeline_semaphore, 1));
m_device->Wait();
}
TEST_F(NegativeSyncObject, CmdWaitEvents2KHRUsedButSynchronizaion2Disabled) {
TEST_DESCRIPTION("Using CmdWaitEvents2KHR when synchronization2 is not enabled");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
vkt::Event event(*m_device);
VkEvent event_handle = event;
VkDependencyInfo dependency_info = vku::InitStructHelper();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents2-synchronization2-03836");
vk::CmdWaitEvents2KHR(m_command_buffer, 1, &event_handle, &dependency_info);
m_errorMonitor->VerifyFound();
if (DeviceValidationVersion() >= VK_API_VERSION_1_3) {
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents2-synchronization2-03836");
vk::CmdWaitEvents2(m_command_buffer, 1, &event_handle, &dependency_info);
m_errorMonitor->VerifyFound();
}
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, Sync2FeatureDisabled) {
TEST_DESCRIPTION("Call sync2 functions when the feature is disabled");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool vulkan_13 = (DeviceValidationVersion() >= VK_API_VERSION_1_3);
bool timestamp = false;
uint32_t queue_count;
vk::GetPhysicalDeviceQueueFamilyProperties(Gpu(), &queue_count, NULL);
std::vector<VkQueueFamilyProperties> queue_props(queue_count);
vk::GetPhysicalDeviceQueueFamilyProperties(Gpu(), &queue_count, queue_props.data());
if (queue_props[m_device->graphics_queue_node_index_].timestampValidBits > 0) {
timestamp = true;
}
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-synchronization2-03848");
m_command_buffer.BarrierKHR(vku::InitStruct<VkDependencyInfo>());
m_errorMonitor->VerifyFound();
vkt::Event event(*m_device);
VkPipelineStageFlagBits2 stage = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
m_errorMonitor->SetDesiredError("VUID-vkCmdResetEvent2-synchronization2-03829");
vk::CmdResetEvent2KHR(m_command_buffer, event, stage);
m_errorMonitor->VerifyFound();
VkDependencyInfo dependency_info = vku::InitStructHelper();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent2-synchronization2-03824");
vk::CmdSetEvent2KHR(m_command_buffer, event, &dependency_info);
m_errorMonitor->VerifyFound();
if (timestamp) {
vkt::QueryPool query_pool(*m_device, VK_QUERY_TYPE_TIMESTAMP, 1);
m_errorMonitor->SetDesiredError("VUID-vkCmdWriteTimestamp2-synchronization2-03858");
vk::CmdWriteTimestamp2KHR(m_command_buffer, stage, query_pool, 0);
m_errorMonitor->VerifyFound();
if (vulkan_13) {
m_errorMonitor->SetDesiredError("VUID-vkCmdWriteTimestamp2-synchronization2-03858");
vk::CmdWriteTimestamp2(m_command_buffer, stage, query_pool, 0);
m_errorMonitor->VerifyFound();
}
}
if (vulkan_13) {
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier2-synchronization2-03848");
m_command_buffer.Barrier(vku::InitStruct<VkDependencyInfo>());
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdResetEvent2-synchronization2-03829");
vk::CmdResetEvent2(m_command_buffer, event, stage);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent2-synchronization2-03824");
vk::CmdSetEvent2(m_command_buffer, event, &dependency_info);
m_errorMonitor->VerifyFound();
}
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, BufferMemoryBarrierUnbound) {
RETURN_IF_SKIP(Init());
VkBufferCreateInfo buffer_ci = vku::InitStructHelper();
buffer_ci.flags = 0u;
buffer_ci.size = 256u;
buffer_ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
vkt::Buffer buffer(*m_device, buffer_ci, vkt::no_mem);
m_command_buffer.Begin();
VkBufferMemoryBarrier bmb = vku::InitStructHelper();
bmb.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
bmb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
bmb.buffer = buffer;
bmb.offset = 0;
bmb.size = VK_WHOLE_SIZE;
m_errorMonitor->SetDesiredError("VUID-VkBufferMemoryBarrier-buffer-01931");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr,
1u, &bmb, 0u, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, BufferMemoryBarrierQueueFamilyExternal) {
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "Two queues are needed to run this test";
}
uint32_t qfi[2] = {m_default_queue->family_index, m_second_queue->family_index};
VkBufferCreateInfo buffer_ci = vku::InitStructHelper();
buffer_ci.flags = 0u;
buffer_ci.size = 256u;
buffer_ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
buffer_ci.sharingMode = VK_SHARING_MODE_CONCURRENT;
buffer_ci.queueFamilyIndexCount = 2u;
buffer_ci.pQueueFamilyIndices = qfi;
vkt::Buffer buffer(*m_device, buffer_ci, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
m_command_buffer.Begin();
VkBufferMemoryBarrier bmb = vku::InitStructHelper();
bmb.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
bmb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
bmb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
bmb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bmb.buffer = buffer;
bmb.offset = 0;
bmb.size = VK_WHOLE_SIZE;
m_errorMonitor->SetDesiredError("VUID-VkBufferMemoryBarrier-None-09097");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr,
1u, &bmb, 0u, nullptr);
m_errorMonitor->VerifyFound();
bmb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bmb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
m_errorMonitor->SetDesiredError("VUID-VkBufferMemoryBarrier-None-09098");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr,
1u, &bmb, 0u, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, ImageMemoryBarrier2QueueFamilyExternal) {
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
if (!m_second_queue) {
GTEST_SKIP() << "Two queues are needed to run this test";
}
uint32_t queue_families[2] = {m_default_queue->family_index, m_second_queue->family_index};
VkImageCreateInfo image_ci = vkt::Image::ImageCreateInfo2D(32u, 32u, 1u, 1u, VK_FORMAT_B8G8R8A8_UNORM,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
VK_IMAGE_TILING_OPTIMAL, vvl::make_span(queue_families, 2u));
vkt::Image image(*m_device, image_ci);
m_command_buffer.Begin();
VkImageMemoryBarrier2 imb = vku::InitStructHelper();
imb.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
imb.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
imb.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
imb.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
imb.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imb.newLayout = VK_IMAGE_LAYOUT_GENERAL;
imb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
imb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imb.image = image;
imb.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-None-09119");
m_command_buffer.BarrierKHR(imb);
m_errorMonitor->VerifyFound();
imb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-None-09120");
m_command_buffer.BarrierKHR(imb);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, BufferMemoryBarrierQueueFamilyForeign) {
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
VkBufferCreateInfo buffer_ci = vku::InitStructHelper();
buffer_ci.flags = 0u;
buffer_ci.size = 256u;
buffer_ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
vkt::Buffer buffer(*m_device, buffer_ci, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
m_command_buffer.Begin();
VkBufferMemoryBarrier bmb = vku::InitStructHelper();
bmb.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
bmb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
bmb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
bmb.dstQueueFamilyIndex = m_default_queue->family_index;
bmb.buffer = buffer;
bmb.offset = 0;
bmb.size = VK_WHOLE_SIZE;
m_errorMonitor->SetDesiredError("VUID-VkBufferMemoryBarrier-srcQueueFamilyIndex-09099");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr,
1u, &bmb, 0u, nullptr);
m_errorMonitor->VerifyFound();
bmb.srcQueueFamilyIndex = m_default_queue->family_index;
bmb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
m_errorMonitor->SetDesiredError("VUID-VkBufferMemoryBarrier-dstQueueFamilyIndex-09100");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr,
1u, &bmb, 0u, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, UnsupportedBarrierAccessMaskConditionalRendering) {
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredExtensions(VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::conditionalRendering);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcStageMask = 0u;
barrier.srcAccessMask = 0u;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
barrier.dstAccessMask = VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03918");
m_command_buffer.BarrierKHR(barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, UnsupportedBarrierAccessMaskFragmentDensityMap) {
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredExtensions(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::fragmentDensityMap);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcStageMask = 0u;
barrier.srcAccessMask = 0u;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
barrier.dstAccessMask = VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03919");
m_command_buffer.BarrierKHR(barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, UnsupportedBarrierAccessMaskXfb) {
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredExtensions(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::transformFeedback);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcStageMask = 0u;
barrier.srcAccessMask = 0u;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
barrier.dstAccessMask = VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03920");
m_command_buffer.BarrierKHR(barrier);
m_errorMonitor->VerifyFound();
barrier.dstAccessMask = VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT;
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-04747");
m_command_buffer.BarrierKHR(barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, UnsupportedBarrierAccessMaskBlendOperationAdvanced) {
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredExtensions(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::advancedBlendCoherentOperations);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcStageMask = 0u;
barrier.srcAccessMask = 0u;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
barrier.dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-dstAccessMask-03926");
m_command_buffer.BarrierKHR(barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, ImageMemoryBarrier2QueueFamilyForeign) {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkImageCreateInfo image_ci =
vkt::Image::ImageCreateInfo2D(32u, 32u, 1u, 1u, VK_FORMAT_B8G8R8A8_UNORM,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL);
vkt::Image image(*m_device, image_ci);
m_command_buffer.Begin();
VkImageMemoryBarrier2 imb = vku::InitStructHelper();
imb.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
imb.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
imb.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
imb.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
imb.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imb.newLayout = VK_IMAGE_LAYOUT_GENERAL;
imb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
imb.dstQueueFamilyIndex = m_default_queue->family_index;
imb.image = image;
imb.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-09121");
m_command_buffer.BarrierKHR(imb);
m_errorMonitor->VerifyFound();
imb.srcQueueFamilyIndex = m_default_queue->family_index;
imb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-dstQueueFamilyIndex-09122");
m_command_buffer.BarrierKHR(imb);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, UnsupportedPipelineBarrierStages) {
AddOptionalExtensions(VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME);
AddOptionalExtensions(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME);
AddOptionalExtensions(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-dstStageMask-04091");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT,
0u, 0u, nullptr, 0u, nullptr, 0u, nullptr);
m_errorMonitor->VerifyFound();
if (IsExtensionsEnabled(VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME)) {
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-dstStageMask-04092");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT,
0u, 0u, nullptr, 0u, nullptr, 0u, nullptr);
m_errorMonitor->VerifyFound();
}
if (IsExtensionsEnabled(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME)) {
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-dstStageMask-04093");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT, 0u, 0u, nullptr, 0u, nullptr, 0u, nullptr);
m_errorMonitor->VerifyFound();
}
if (IsExtensionsEnabled(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME)) {
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-dstStageMask-04094");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
0u, 0u, nullptr, 0u, nullptr, 0u, nullptr);
m_errorMonitor->VerifyFound();
}
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-dstStageMask-03937");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0u, 0u, 0u, nullptr, 0u, nullptr, 0u, nullptr);
m_errorMonitor->VerifyFound();
if (IsExtensionsEnabled(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) {
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-dstStageMask-07318");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, 0u, 0u, nullptr, 0u, nullptr, 0u,
nullptr);
m_errorMonitor->VerifyFound();
}
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, UnsupportedBufferMemoryBarrier2Stages) {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredExtensions(VK_HUAWEI_SUBPASS_SHADING_EXTENSION_NAME);
AddRequiredExtensions(VK_HUAWEI_INVOCATION_MASK_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
VkBufferMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.buffer = buffer;
barrier.size = VK_WHOLE_SIZE;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkBufferMemoryBarrier2-dstStageMask-04957");
m_command_buffer.BarrierKHR(barrier);
m_errorMonitor->VerifyFound();
barrier.dstStageMask = VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI;
m_errorMonitor->SetDesiredError("VUID-VkBufferMemoryBarrier2-dstStageMask-04995");
m_command_buffer.BarrierKHR(barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, InvalidBarrierPNext) {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
VkImageCreateInfo image_ci =
vkt::Image::ImageCreateInfo2D(32u, 32u, 1u, 1u, VK_FORMAT_B8G8R8A8_UNORM,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL);
vkt::Image image(*m_device, image_ci);
VkMemoryBarrier2 memory_barrier = vku::InitStructHelper();
VkBufferMemoryBarrier2 buffer_barrier = vku::InitStructHelper(&memory_barrier);
buffer_barrier.buffer = buffer;
buffer_barrier.size = VK_WHOLE_SIZE;
buffer_barrier.dstStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR;
VkImageMemoryBarrier2 image_barrier = vku::InitStructHelper(&memory_barrier);
image_barrier.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
image_barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
image_barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
image_barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
image_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
image_barrier.image = image;
image_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.bufferMemoryBarrierCount = 1u;
dependency_info.pBufferMemoryBarriers = &buffer_barrier;
dependency_info.pImageMemoryBarriers = &image_barrier;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkBufferMemoryBarrier2-pNext-pNext");
vk::CmdPipelineBarrier2KHR(m_command_buffer, &dependency_info);
m_errorMonitor->VerifyFound();
dependency_info.bufferMemoryBarrierCount = 0u;
dependency_info.imageMemoryBarrierCount = 1u;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier2-pNext-pNext");
vk::CmdPipelineBarrier2KHR(m_command_buffer, &dependency_info);
m_errorMonitor->VerifyFound();
dependency_info.imageMemoryBarrierCount = 0u;
dependency_info.pNext = &memory_barrier;
m_errorMonitor->SetDesiredError("VUID-VkDependencyInfo-pNext-pNext");
vk::CmdPipelineBarrier2KHR(m_command_buffer, &dependency_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, AcquireWithoutRelease) {
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
auto only_transfer_queueFamilyIndex = m_device->TransferOnlyQueueFamily();
if (!only_transfer_queueFamilyIndex.has_value()) {
GTEST_SKIP() << "Transfer only queue is not supported";
}
vkt::Buffer buffer(*m_device, 256u, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VkBufferMemoryBarrier buffer_memory_barrier = vku::InitStructHelper();
buffer_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
buffer_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
buffer_memory_barrier.srcQueueFamilyIndex = only_transfer_queueFamilyIndex.value();
buffer_memory_barrier.dstQueueFamilyIndex = m_device->graphics_queue_node_index_;
buffer_memory_barrier.buffer = buffer;
buffer_memory_barrier.offset = 0u;
buffer_memory_barrier.size = VK_WHOLE_SIZE;
m_command_buffer.Begin();
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 1u,
&buffer_memory_barrier, 0u, nullptr);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit-pSubmits-02207");
m_default_queue->Submit(m_command_buffer);
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit2-commandBuffer-03879");
m_default_queue->Submit2(m_command_buffer, vkt::no_fence, true);
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, AccessFlags3) {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::maintenance8);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
VkImageCreateInfo image_ci =
vkt::Image::ImageCreateInfo2D(32u, 32u, 1u, 1u, VK_FORMAT_B8G8R8A8_UNORM,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL);
vkt::Image image(*m_device, image_ci);
VkMemoryBarrierAccessFlags3KHR memory_barrier_access_flags1 = vku::InitStructHelper();
memory_barrier_access_flags1.srcAccessMask3 = VK_ACCESS_3_NONE_KHR;
memory_barrier_access_flags1.dstAccessMask3 = VK_ACCESS_3_NONE_KHR;
VkMemoryBarrierAccessFlags3KHR memory_barrier_access_flags2 = vku::InitStructHelper(&memory_barrier_access_flags1);
memory_barrier_access_flags2.srcAccessMask3 = VK_ACCESS_3_NONE_KHR;
memory_barrier_access_flags2.dstAccessMask3 = VK_ACCESS_3_NONE_KHR;
VkMemoryBarrier2 memory_barrier = vku::InitStructHelper(&memory_barrier_access_flags2);
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkDependencyInfo-pMemoryBarriers-10605");
m_command_buffer.BarrierKHR(memory_barrier);
m_errorMonitor->VerifyFound();
memory_barrier.pNext = &image_ci;
m_errorMonitor->SetDesiredError("VUID-VkDependencyInfo-pMemoryBarriers-10606");
m_command_buffer.BarrierKHR(memory_barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, AccelerationBuildStageWithoutEnabledFeature) {
TEST_DESCRIPTION("Use VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR without enabling accelerationStructure feature");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkPipelineStageFlags stage = VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR;
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcStageMask = stage;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcStageMask-10751");
m_command_buffer.Barrier(barrier);
m_errorMonitor->VerifyFound();
vkt::Event event(*m_device);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent-stageMask-10754");
vk::CmdSetEvent(m_command_buffer, event, stage);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, AccelerationCopyStageWithoutEnabledFeature) {
TEST_DESCRIPTION("Use VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR without enabling rayTracingMaintenance1 feature");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcStageMask = VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcStageMask-10752");
m_command_buffer.Barrier(barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, MicromapBuildStageWithoutEnabledFeature) {
TEST_DESCRIPTION("Use VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT without enabling micromap feature");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_EXT_OPACITY_MICROMAP_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcStageMask = VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkMemoryBarrier2-srcStageMask-10753");
m_command_buffer.Barrier(barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, RayTracingStageFlagWithoutFeature) {
TEST_DESCRIPTION("Test using the ray tracing stage flag without enabling any of ray tracing features");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
vkt::Semaphore semaphore(*m_device);
VkPipelineStageFlags stage = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
VkSubmitInfo submit_info = vku::InitStructHelper();
submit_info.signalSemaphoreCount = 1u;
submit_info.pSignalSemaphores = &semaphore.handle();
vk::QueueSubmit(m_default_queue->handle(), 1u, &submit_info, VK_NULL_HANDLE);
submit_info.signalSemaphoreCount = 0u;
submit_info.waitSemaphoreCount = 1u;
submit_info.pWaitSemaphores = &semaphore.handle();
submit_info.pWaitDstStageMask = &stage;
m_errorMonitor->SetDesiredError("VUID-VkSubmitInfo-pWaitDstStageMask-07949");
vk::QueueSubmit(m_default_queue->handle(), 1u, &submit_info, VK_NULL_HANDLE);
m_errorMonitor->VerifyFound();
vkt::Event event(*m_device);
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent-stageMask-07949");
vk::CmdSetEvent(m_command_buffer, event, stage);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdResetEvent-stageMask-07949");
vk::CmdResetEvent(m_command_buffer, event, stage);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents-srcStageMask-07949");
vk::CmdWaitEvents(m_command_buffer, 1u, &event.handle(), stage, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, nullptr, 0u, nullptr,
0u, nullptr);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents-dstStageMask-07949");
vk::CmdWaitEvents(m_command_buffer, 1u, &event.handle(), VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, stage, 0u, nullptr, 0u, nullptr,
0u, nullptr);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-srcStageMask-07949");
vk::CmdPipelineBarrier(m_command_buffer, stage, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0u, 0u, nullptr, 0u, nullptr, 0u,
nullptr);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdPipelineBarrier-dstStageMask-07949");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, stage, 0u, 0u, nullptr, 0u, nullptr, 0u, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, TimelineSemaphoreAndExportedCopyCooperation) {
TEST_DESCRIPTION("Signal smaller value than the current value when semaphores share payload");
#ifdef VK_USE_PLATFORM_WIN32_KHR
const auto extension_name = VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME;
const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT;
#else
const auto extension_name = VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME;
const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
#endif
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(extension_name);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
if (IsPlatformMockICD()) {
GTEST_SKIP() << "Test not supported by MockICD";
}
if (!m_second_queue) {
GTEST_SKIP() << "Two queues are needed";
}
if (!SemaphoreExportImportSupported(Gpu(), VK_SEMAPHORE_TYPE_TIMELINE, handle_type)) {
GTEST_SKIP() << "Semaphore does not support export and import through opaque handle";
}
VkSemaphoreTypeCreateInfo semaphore_type_ci = vku::InitStructHelper();
semaphore_type_ci.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
VkExportSemaphoreCreateInfo export_info = vku::InitStructHelper(&semaphore_type_ci);
export_info.handleTypes = handle_type;
VkSemaphoreCreateInfo semaphore_ci = vku::InitStructHelper(&export_info);
vkt::Semaphore semaphore(*m_device, semaphore_ci);
vkt::Semaphore import_semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE);
ExternalHandle handle{};
semaphore.ExportHandle(handle, handle_type);
import_semaphore.ImportHandle(handle, handle_type);
m_default_queue->Submit(vkt::no_cmd, vkt::TimelineSignal(semaphore, 1));
m_second_queue->Submit(vkt::no_cmd, vkt::TimelineWait(import_semaphore, 1), vkt::TimelineSignal(import_semaphore, 3));
// Wait until imported copy reaches value 3
import_semaphore.Wait(3, kWaitTimeout);
// This will update current value for original semaphore to 3.
semaphore.GetCounterValue();
// Signal smaller value (2) than the current value (3)
m_errorMonitor->SetDesiredError("VUID-VkSemaphoreSignalInfo-value-03258");
semaphore.Signal(2);
m_errorMonitor->VerifyFound();
m_device->Wait();
}
TEST_F(NegativeSyncObject, Transition3dImageSlice) {
AddRequiredExtensions(VK_KHR_MAINTENANCE_1_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::maintenance9);
RETURN_IF_SKIP(Init());
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.flags = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
image_create_info.imageType = VK_IMAGE_TYPE_3D;
image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM;
image_create_info.extent = {32u, 32u, 4u};
image_create_info.mipLevels = 1u;
image_create_info.arrayLayers = 1u;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
vkt::Image image(*m_device, image_create_info, vkt::set_layout);
VkImageMemoryBarrier image_memory_barrier = vku::InitStructHelper();
image_memory_barrier.srcAccessMask = VK_ACCESS_NONE;
image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = image;
image_memory_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 4, VK_REMAINING_ARRAY_LAYERS};
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-maintenance9-10798");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u,
nullptr, 1u, &image_memory_barrier);
m_errorMonitor->VerifyFound();
image_memory_barrier.subresourceRange.baseArrayLayer = 0u;
image_memory_barrier.subresourceRange.layerCount = 5u;
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-maintenance9-10800");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u,
nullptr, 1u, &image_memory_barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, Transition3dImageWithMipLevels) {
AddRequiredExtensions(VK_KHR_MAINTENANCE_1_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::maintenance9);
RETURN_IF_SKIP(Init());
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.flags = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
image_create_info.imageType = VK_IMAGE_TYPE_3D;
image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM;
image_create_info.extent = {32u, 32u, 4u};
image_create_info.mipLevels = 2u;
image_create_info.arrayLayers = 1u;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
vkt::Image image(*m_device, image_create_info);
VkImageMemoryBarrier image_memory_barrier = vku::InitStructHelper();
image_memory_barrier.srcAccessMask = VK_ACCESS_NONE;
image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = image;
image_memory_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 2, 0, 1};
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkImageMemoryBarrier-maintenance9-10799");
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u,
nullptr, 1u, &image_memory_barrier);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, AsymmetricSetEvent2) {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::maintenance9);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 barriers[2];
barriers[0] = vku::InitStructHelper();
barriers[0].srcAccessMask = 0;
barriers[0].dstAccessMask = 0;
barriers[0].srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
barriers[0].dstStageMask = 0;
barriers[1] = vku::InitStructHelper();
barriers[1].srcAccessMask = 0;
barriers[1].dstAccessMask = 0;
barriers[1].srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
barriers[1].dstStageMask = 0;
vkt::Buffer buffer(*m_device, 256u, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VkBufferMemoryBarrier2 buffer_barrier = vku::InitStructHelper();
buffer_barrier.buffer = buffer;
buffer_barrier.offset = 0u;
buffer_barrier.size = VK_WHOLE_SIZE;
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.dependencyFlags = VK_DEPENDENCY_ASYMMETRIC_EVENT_BIT_KHR;
dependency_info.memoryBarrierCount = 1u;
dependency_info.pMemoryBarriers = barriers;
dependency_info.bufferMemoryBarrierCount = 1u;
dependency_info.pBufferMemoryBarriers = &buffer_barrier;
const vkt::Event event(*m_device);
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent2-dependencyFlags-10785");
vk::CmdSetEvent2(m_command_buffer, event, &dependency_info);
m_errorMonitor->VerifyFound();
dependency_info.bufferMemoryBarrierCount = 0u;
dependency_info.memoryBarrierCount = 2u;
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent2-dependencyFlags-10786");
vk::CmdSetEvent2(m_command_buffer, event, &dependency_info);
m_errorMonitor->VerifyFound();
dependency_info.memoryBarrierCount = 1u;
barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
m_errorMonitor->SetDesiredError("VUID-vkCmdSetEvent2-dependencyFlags-10787");
vk::CmdSetEvent2(m_command_buffer, event, &dependency_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeSyncObject, AsymmetricWaitEvent2) {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::maintenance9);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcStageMask = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.memoryBarrierCount = 1u;
dependency_info.pMemoryBarriers = &barrier;
const vkt::Event event(*m_device);
m_command_buffer.Begin();
vk::CmdSetEvent2(m_command_buffer, event, &dependency_info);
dependency_info.dependencyFlags = VK_DEPENDENCY_ASYMMETRIC_EVENT_BIT_KHR;
barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
vk::CmdWaitEvents2(m_command_buffer, 1, &event.handle(), &dependency_info);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents2-pEvents-10789");
m_default_queue->Submit(m_command_buffer);
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, MismatchedDependencyInfo) {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::maintenance9);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcStageMask = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.memoryBarrierCount = 1u;
dependency_info.pMemoryBarriers = &barrier;
const vkt::Event event(*m_device);
m_command_buffer.Begin();
vk::CmdSetEvent2(m_command_buffer, event, &dependency_info);
barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
vk::CmdWaitEvents2(m_command_buffer, 1, &event.handle(), &dependency_info);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents2-pEvents-10788");
m_default_queue->Submit(m_command_buffer);
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
}
TEST_F(NegativeSyncObject, InvalidAssymetricSrcStagemask) {
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::maintenance9);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredFeature(vkt::Feature::geometryShader);
RETURN_IF_SKIP(Init());
VkMemoryBarrier2 barrier = vku::InitStructHelper();
barrier.srcStageMask = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
VkDependencyInfo dependency_info = vku::InitStructHelper();
dependency_info.dependencyFlags = VK_DEPENDENCY_ASYMMETRIC_EVENT_BIT_KHR;
dependency_info.memoryBarrierCount = 1u;
dependency_info.pMemoryBarriers = &barrier;
const vkt::Event event(*m_device);
m_command_buffer.Begin();
vk::CmdSetEvent2(m_command_buffer, event, &dependency_info);
barrier.srcStageMask |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
vk::CmdWaitEvents2(m_command_buffer, 1, &event.handle(), &dependency_info);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-vkCmdWaitEvents2-pEvents-10790");
m_default_queue->Submit(m_command_buffer);
m_errorMonitor->VerifyFound();
m_default_queue->Wait();
}