tests:Add secondary cmd buffer image layout test
Add SecondaryCommandBufferImageLayoutTransitions positive test. This
performs an image layout transition in a secondary command buffer and
then in the primary cmd buffer.
There should be no errors, but previously validation did not correctly
handle layout transitions in a secondary command buffer.
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 55203fb..0ba0800 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -15351,6 +15351,92 @@
//
// These tests do not expect to encounter ANY validation errors pass only if this is true
+TEST_F(VkPositiveLayerTest, SecondaryCommandBufferImageLayoutTransitions) {
+ TEST_DESCRIPTION("Perform an image layout transition in a secondary command buffer followed "
+ "by a transition in the primary.");
+ VkResult err;
+ m_errorMonitor->ExpectSuccess();
+ ASSERT_NO_FATAL_FAILURE(InitState());
+ ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
+ // Allocate a secondary and primary cmd buffer
+ VkCommandBufferAllocateInfo command_buffer_allocate_info = {};
+ command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ command_buffer_allocate_info.commandPool = m_commandPool;
+ command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
+ command_buffer_allocate_info.commandBufferCount = 1;
+
+ VkCommandBuffer secondary_command_buffer;
+ ASSERT_VK_SUCCESS(vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &secondary_command_buffer));
+ command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ VkCommandBuffer primary_command_buffer;
+ ASSERT_VK_SUCCESS(vkAllocateCommandBuffers(m_device->device(), &command_buffer_allocate_info, &primary_command_buffer));
+ VkCommandBufferBeginInfo command_buffer_begin_info = {};
+ VkCommandBufferInheritanceInfo command_buffer_inheritance_info = {};
+ command_buffer_inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
+ command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ command_buffer_begin_info.pInheritanceInfo = &command_buffer_inheritance_info;
+
+ err = vkBeginCommandBuffer(secondary_command_buffer, &command_buffer_begin_info);
+ ASSERT_VK_SUCCESS(err);
+ VkImageObj image(m_device);
+ image.init(128, 128, VK_FORMAT_D24_UNORM_S8_UINT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
+ ASSERT_TRUE(image.initialized());
+ VkImageMemoryBarrier img_barrier = {};
+ img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ img_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
+ img_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ img_barrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ img_barrier.image = image.handle();
+ img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ img_barrier.subresourceRange.baseArrayLayer = 0;
+ img_barrier.subresourceRange.baseMipLevel = 0;
+ img_barrier.subresourceRange.layerCount = 1;
+ img_barrier.subresourceRange.levelCount = 1;
+ vkCmdPipelineBarrier(secondary_command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr,
+ 0, nullptr, 1, &img_barrier);
+ err = vkEndCommandBuffer(secondary_command_buffer);
+ ASSERT_VK_SUCCESS(err);
+
+ // Now update primary cmd buffer to execute secondary and transitions image
+ command_buffer_begin_info.pInheritanceInfo = nullptr;
+ err = vkBeginCommandBuffer(primary_command_buffer, &command_buffer_begin_info);
+ ASSERT_VK_SUCCESS(err);
+ vkCmdExecuteCommands(primary_command_buffer, 1, &secondary_command_buffer);
+ VkImageMemoryBarrier img_barrier2 = {};
+ img_barrier2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ img_barrier2.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
+ img_barrier2.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ img_barrier2.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ img_barrier2.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ img_barrier2.image = image.handle();
+ img_barrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ img_barrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ img_barrier2.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ img_barrier2.subresourceRange.baseArrayLayer = 0;
+ img_barrier2.subresourceRange.baseMipLevel = 0;
+ img_barrier2.subresourceRange.layerCount = 1;
+ img_barrier2.subresourceRange.levelCount = 1;
+ vkCmdPipelineBarrier(primary_command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 0,
+ nullptr, 1, &img_barrier2);
+ err = vkEndCommandBuffer(primary_command_buffer);
+ ASSERT_VK_SUCCESS(err);
+ VkSubmitInfo submit_info = {};
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.commandBufferCount = 1;
+ submit_info.pCommandBuffers = &primary_command_buffer;
+ err = vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
+ ASSERT_VK_SUCCESS(err);
+ m_errorMonitor->VerifyNotFound();
+ err = vkDeviceWaitIdle(m_device->device());
+ ASSERT_VK_SUCCESS(err);
+ vkFreeCommandBuffers(m_device->device(), m_commandPool, 1, &secondary_command_buffer);
+ vkFreeCommandBuffers(m_device->device(), m_commandPool, 1, &primary_command_buffer);
+}
+
// This is a positive test. No failures are expected.
TEST_F(VkPositiveLayerTest, IgnoreUnrelatedDescriptor) {
TEST_DESCRIPTION("Ensure that the vkUpdateDescriptorSets validation code "