blob: 0053d0080121a2add7502482ae0543e631ae6e1d [file] [log] [blame]
/*
* Copyright (c) 2015-2021 The Khronos Group Inc.
* Copyright (c) 2015-2021 Valve Corporation
* Copyright (c) 2015-2021 LunarG, Inc.
* Copyright (c) 2015-2021 Google, Inc.
* Modifications Copyright (C) 2020-2021 Advanced Micro Devices, Inc. All rights reserved.
* Modifications Copyright (C) 2021 ARM, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Author: Chia-I Wu <olvaffe@gmail.com>
* Author: Chris Forbes <chrisf@ijw.co.nz>
* Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
* Author: Mark Lobodzinski <mark@lunarg.com>
* Author: Mike Stroyan <mike@LunarG.com>
* Author: Tobin Ehlis <tobine@google.com>
* Author: Tony Barbour <tony@LunarG.com>
* Author: Cody Northrop <cnorthrop@google.com>
* Author: Dave Houlton <daveh@lunarg.com>
* Author: Jeremy Kniager <jeremyk@lunarg.com>
* Author: Shannon McPherson <shannon@lunarg.com>
* Author: John Zulauf <jzulauf@lunarg.com>
* Author: Tobias Hector <tobias.hector@amd.com>
* Author: Quentin Huot-Marchand <quentin.huot-marchand@arm.com
*/
#include "cast_utils.h"
#include "layer_validation_tests.h"
TEST_F(VkLayerTest, ValidationArrayOOBRayTracingShaders) {
TEST_DESCRIPTION(
"Core validation: Verify detection of out-of-bounds descriptor array indexing and use of uninitialized descriptors for "
"ray tracing shaders.");
OOBRayTracingShadersTestBody(false);
}
TEST_F(VkLayerTest, InvalidDescriptorPoolConsistency) {
VkResult err;
TEST_DESCRIPTION("Allocate descriptor sets from one DS pool and attempt to delete them from another.");
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkFreeDescriptorSets-pDescriptorSets-parent");
ASSERT_NO_FATAL_FAILURE(Init());
ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
VkDescriptorPoolSize ds_type_count = {};
ds_type_count.type = VK_DESCRIPTOR_TYPE_SAMPLER;
ds_type_count.descriptorCount = 1;
VkDescriptorPoolCreateInfo ds_pool_ci = {};
ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
ds_pool_ci.pNext = NULL;
ds_pool_ci.flags = 0;
ds_pool_ci.maxSets = 1;
ds_pool_ci.poolSizeCount = 1;
ds_pool_ci.pPoolSizes = &ds_type_count;
VkDescriptorPool bad_pool;
err = vk::CreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &bad_pool);
ASSERT_VK_SUCCESS(err);
OneOffDescriptorSet descriptor_set(m_device, {
{0, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr},
});
err = vk::FreeDescriptorSets(m_device->device(), bad_pool, 1, &descriptor_set.set_);
m_errorMonitor->VerifyFound();
vk::DestroyDescriptorPool(m_device->device(), bad_pool, NULL);
}
TEST_F(VkLayerTest, BadSubpassIndices) {
TEST_DESCRIPTION("Create render pass with valid stages");
bool rp2_supported = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
if (rp2_supported) m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
if (rp2_supported) rp2_supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
ASSERT_NO_FATAL_FAILURE(InitState());
VkSubpassDescription sci[2] = {};
sci[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
sci[1].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
const VkPipelineStageFlags kGraphicsStages =
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | 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 | VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
VkSubpassDependency dependency = {};
// Use only 2 subpasses, so these values should trigger validation errors
dependency.srcSubpass = 4;
dependency.dstSubpass = 4;
dependency.srcStageMask = kGraphicsStages;
dependency.dstStageMask = kGraphicsStages;
VkRenderPassCreateInfo rpci = {};
rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
rpci.subpassCount = 2;
rpci.pSubpasses = sci;
rpci.dependencyCount = 1;
rpci.pDependencies = &dependency;
VkRenderPass render_pass = VK_NULL_HANDLE;
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkRenderPassCreateInfo-srcSubpass-02517");
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkRenderPassCreateInfo-dstSubpass-02518");
vk::CreateRenderPass(m_device->device(), &rpci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
if (rp2_supported) {
PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR =
(PFN_vkCreateRenderPass2KHR)vk::GetDeviceProcAddr(m_device->device(), "vkCreateRenderPass2KHR");
safe_VkRenderPassCreateInfo2 create_info2;
ConvertVkRenderPassCreateInfoToV2KHR(rpci, &create_info2);
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkRenderPassCreateInfo2-srcSubpass-02526");
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkRenderPassCreateInfo2-dstSubpass-02527");
vkCreateRenderPass2KHR(m_device->device(), create_info2.ptr(), nullptr, &render_pass);
m_errorMonitor->VerifyFound();
}
}
TEST_F(VkLayerTest, DrawWithPipelineIncompatibleWithSubpass) {
TEST_DESCRIPTION("Use a pipeline for the wrong subpass in a render pass instance");
ASSERT_NO_FATAL_FAILURE(Init());
// A renderpass with two subpasses, both writing the same attachment.
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},
{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr},
};
VkSubpassDependency dep = {0,
1,
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, 2, subpasses, 1, &dep};
VkRenderPass rp;
VkResult err = vk::CreateRenderPass(m_device->device(), &rpci, nullptr, &rp);
ASSERT_VK_SUCCESS(err);
VkImageObj image(m_device);
image.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
VkImageView imageView = image.targetView(VK_FORMAT_R8G8B8A8_UNORM);
VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &imageView, 32, 32, 1};
VkFramebuffer fb;
err = vk::CreateFramebuffer(m_device->device(), &fbci, nullptr, &fb);
ASSERT_VK_SUCCESS(err);
VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
VkPipelineObj pipe(m_device);
pipe.AddDefaultColorAttachment();
pipe.AddShader(&vs);
pipe.AddShader(&fs);
VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f};
m_viewports.push_back(viewport);
pipe.SetViewport(m_viewports);
VkRect2D rect = {};
m_scissors.push_back(rect);
pipe.SetScissor(m_scissors);
const VkPipelineLayoutObj pl(m_device);
pipe.CreateVKPipeline(pl.handle(), rp);
m_commandBuffer->begin();
VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
nullptr,
rp,
fb,
{{
0,
0,
},
{32, 32}},
0,
nullptr};
// subtest 1: bind in the wrong subpass
vk::CmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE);
vk::CmdNextSubpass(m_commandBuffer->handle(), VK_SUBPASS_CONTENTS_INLINE);
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "built for subpass 0 but used in subpass 1");
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdEndRenderPass(m_commandBuffer->handle());
// subtest 2: bind in correct subpass, then transition to next subpass
vk::CmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
vk::CmdNextSubpass(m_commandBuffer->handle(), VK_SUBPASS_CONTENTS_INLINE);
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "built for subpass 0 but used in subpass 1");
vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdEndRenderPass(m_commandBuffer->handle());
m_commandBuffer->end();
vk::DestroyFramebuffer(m_device->device(), fb, nullptr);
vk::DestroyRenderPass(m_device->device(), rp, nullptr);
}
TEST_F(VkLayerTest, ImageBarrierSubpassConflict) {
TEST_DESCRIPTION("Check case where subpass index references different image from image barrier");
ASSERT_NO_FATAL_FAILURE(Init());
// Create RP/FB combo where subpass has incorrect index attachment, this is 2nd half of "VUID-vkCmdPipelineBarrier-image-02635"
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},
{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},
};
// ref attachment points to wrong attachment index compared to img_barrier below
VkAttachmentReference ref = {1, 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, 2, attach, 1, subpasses, 1, &dep};
VkRenderPass rp;
VkResult err = vk::CreateRenderPass(m_device->device(), &rpci, nullptr, &rp);
ASSERT_VK_SUCCESS(err);
VkImageObj image(m_device);
image.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
VkImageView imageView = image.targetView(VK_FORMAT_R8G8B8A8_UNORM);
VkImageObj image2(m_device);
image2.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
VkImageView imageView2 = image2.targetView(VK_FORMAT_R8G8B8A8_UNORM);
// re-use imageView from start of test
VkImageView iv_array[2] = {imageView, imageView2};
VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 2, iv_array, 32, 32, 1};
VkFramebuffer fb;
err = vk::CreateFramebuffer(m_device->device(), &fbci, nullptr, &fb);
ASSERT_VK_SUCCESS(err);
VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
nullptr,
rp,
fb,
{{
0,
0,
},
{32, 32}},
0,
nullptr};
VkImageMemoryBarrier img_barrier = {};
img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
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.handle(); /* barrier references image from attachment index 0 */
img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
img_barrier.subresourceRange.baseArrayLayer = 0;
img_barrier.subresourceRange.baseMipLevel = 0;
img_barrier.subresourceRange.layerCount = 1;
img_barrier.subresourceRange.levelCount = 1;
m_commandBuffer->begin();
vk::CmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE);
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdPipelineBarrier-image-04073");
vk::CmdPipelineBarrier(m_commandBuffer->handle(), 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();
vk::DestroyFramebuffer(m_device->device(), fb, nullptr);
vk::DestroyRenderPass(m_device->device(), rp, nullptr);
}
TEST_F(VkLayerTest, RenderPassCreateAttachmentIndexOutOfRange) {
SetTargetApiVersion(VK_API_VERSION_1_2);
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
ASSERT_NO_FATAL_FAILURE(InitState());
// There are no attachments, but refer to attachment 0.
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},
};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 1, subpasses, 0, nullptr};
// "... must be less than the total number of attachments ..."
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-attachment-00834",
"VUID-VkRenderPassCreateInfo2-attachment-03051");
}
TEST_F(VkLayerTest, RenderPassCreateAttachmentReadOnlyButCleared) {
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
bool maintenance2Supported = false;
// Check for VK_KHR_maintenance2
if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE_2_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
maintenance2Supported = true;
}
ASSERT_NO_FATAL_FAILURE(InitState());
if (DeviceValidationVersion() >= VK_API_VERSION_1_1) {
maintenance2Supported = true;
}
const VkFormat ds_format = FindSupportedDepthStencilFormat(gpu());
if (ds_format == VK_FORMAT_UNDEFINED) {
printf("%s No Depth + Stencil format found rest of tests skipped.\n", kSkipPrefix);
return;
}
VkAttachmentDescription description = {0,
ds_format,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // loadOp
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_GENERAL};
VkAttachmentReference depth_stencil_ref = {0, VK_IMAGE_LAYOUT_GENERAL};
VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, &depth_stencil_ref, 0,
nullptr};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &description, 1, &subpass, 0, nullptr};
// Test both cases when rp2 is not supported
// Set loadOp to clear
description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depth_stencil_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-pAttachments-00836",
"VUID-VkRenderPassCreateInfo2-pAttachments-02522");
if (maintenance2Supported == true) {
depth_stencil_ref.layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkRenderPassCreateInfo-pAttachments-01566", "VUID-VkRenderPassCreateInfo2-pAttachments-02522");
}
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // reset
// Set stencilLoadOp to clear
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depth_stencil_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-pAttachments-02511",
"VUID-VkRenderPassCreateInfo2-pAttachments-02523");
if (maintenance2Supported == true) {
depth_stencil_ref.layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkRenderPassCreateInfo-pAttachments-01567", "VUID-VkRenderPassCreateInfo2-pAttachments-02523");
}
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // reset
}
TEST_F(VkLayerTest, RenderPassCreateAttachmentMismatchingLayoutsColor) {
TEST_DESCRIPTION("Attachment is used simultaneously as two color attachments with different layouts.");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
ASSERT_NO_FATAL_FAILURE(InitState());
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 refs[] = {
{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
{0, VK_IMAGE_LAYOUT_GENERAL},
};
VkSubpassDescription subpasses[] = {
{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 2, refs, nullptr, nullptr, 0, nullptr},
};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, attach, 1, subpasses, 0, nullptr};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"subpass 0 already uses attachment 0 with a different image layout",
"subpass 0 already uses attachment 0 with a different image layout");
}
TEST_F(VkLayerTest, RenderPassCreateAttachmentDescriptionInvalidFinalLayout) {
TEST_DESCRIPTION("VkAttachmentDescription's finalLayout must not be UNDEFINED or PREINITIALIZED");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME);
}
PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR =
(PFN_vkGetPhysicalDeviceFeatures2KHR)vk::GetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR");
auto separate_depth_stencil_layouts_features = LvlInitStruct<VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR>();
auto features2 = LvlInitStruct<VkPhysicalDeviceFeatures2KHR>(&separate_depth_stencil_layouts_features);
if (vkGetPhysicalDeviceFeatures2KHR) {
vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2);
} else {
separate_depth_stencil_layouts_features.separateDepthStencilLayouts = VK_FALSE;
}
ASSERT_NO_FATAL_FAILURE(InitState(nullptr, (vkGetPhysicalDeviceFeatures2KHR) ? &features2 : nullptr));
VkAttachmentDescription attach_desc = {};
attach_desc.format = VK_FORMAT_R8G8B8A8_UNORM;
attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attach_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attach_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkAttachmentReference attach_ref = {};
attach_ref.attachment = 0;
attach_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attach_ref;
VkRenderPassCreateInfo rpci = {};
rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-finalLayout-00843",
"VUID-VkAttachmentDescription2-finalLayout-03061");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-finalLayout-00843",
"VUID-VkAttachmentDescription2-finalLayout-03061");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
auto depth_format = FindSupportedDepthOnlyFormat(gpu());
auto stencil_format = FindSupportedStencilOnlyFormat(gpu());
auto depth_stencil_format = FindSupportedDepthStencilFormat(gpu());
if (separate_depth_stencil_layouts_features.separateDepthStencilLayouts) {
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03286",
"VUID-VkAttachmentDescription2-format-03300");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03286",
"VUID-VkAttachmentDescription2-format-03300");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03286",
"VUID-VkAttachmentDescription2-format-03300");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03286",
"VUID-VkAttachmentDescription2-format-03300");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03287",
"VUID-VkAttachmentDescription2-format-03301");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03287",
"VUID-VkAttachmentDescription2-format-03301");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03287",
"VUID-VkAttachmentDescription2-format-03301");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03287",
"VUID-VkAttachmentDescription2-format-03301");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
if (depth_stencil_format) {
attach_desc.format = depth_stencil_format;
if (rp2Supported) {
safe_VkRenderPassCreateInfo2 rpci2;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
ConvertVkRenderPassCreateInfoToV2KHR(rpci, &rpci2);
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentDescription2-format-03302");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
ConvertVkRenderPassCreateInfoToV2KHR(rpci, &rpci2);
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentDescription2-format-03302");
} else {
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03288", "VUID-VkAttachmentDescription2-format-03302");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03288", "VUID-VkAttachmentDescription2-format-03302");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03288", "VUID-VkAttachmentDescription2-format-03302");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03288", "VUID-VkAttachmentDescription2-format-03302");
}
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
if (rp2Supported) {
safe_VkRenderPassCreateInfo2 rpci2;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
ConvertVkRenderPassCreateInfoToV2KHR(rpci, &rpci2);
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentDescription2-format-03303");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
ConvertVkRenderPassCreateInfoToV2KHR(rpci, &rpci2);
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentDescription2-format-03303");
} else {
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03289", "VUID-VkAttachmentDescription2-format-03303");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03289", "VUID-VkAttachmentDescription2-format-03303");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03289", "VUID-VkAttachmentDescription2-format-03303");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03289", "VUID-VkAttachmentDescription2-format-03303");
}
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
}
if (depth_format) {
attach_desc.format = depth_format;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03290", "VUID-VkAttachmentDescription2-format-03304");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03290", "VUID-VkAttachmentDescription2-format-03304");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03291", "VUID-VkAttachmentDescription2-format-03305");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03291", "VUID-VkAttachmentDescription2-format-03305");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
}
if (stencil_format) {
attach_desc.format = stencil_format;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03292", "VUID-VkAttachmentDescription2-format-03306");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03292", "VUID-VkAttachmentDescription2-format-03306");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03293", "VUID-VkAttachmentDescription2-format-03307");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-format-03293", "VUID-VkAttachmentDescription2-format-03307");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
}
if (rp2Supported && depth_stencil_format) {
attach_desc.format = depth_stencil_format;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
auto attachment_description_stencil_layout = LvlInitStruct<VkAttachmentDescriptionStencilLayoutKHR>();
attachment_description_stencil_layout.stencilInitialLayout = VK_IMAGE_LAYOUT_GENERAL;
attachment_description_stencil_layout.stencilFinalLayout = VK_IMAGE_LAYOUT_GENERAL;
safe_VkRenderPassCreateInfo2 rpci2;
ConvertVkRenderPassCreateInfoToV2KHR(rpci, &rpci2);
rpci2.pAttachments[0].pNext = &attachment_description_stencil_layout;
VkImageLayout forbidden_layouts[] = {
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR,
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
};
auto forbidden_layouts_array_size = sizeof(forbidden_layouts) / sizeof(forbidden_layouts[0]);
for (size_t i = 0; i < forbidden_layouts_array_size; ++i) {
attachment_description_stencil_layout.stencilInitialLayout = forbidden_layouts[i];
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentDescriptionStencilLayout-stencilInitialLayout-03308");
}
attachment_description_stencil_layout.stencilInitialLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
for (size_t i = 0; i < forbidden_layouts_array_size; ++i) {
attachment_description_stencil_layout.stencilFinalLayout = forbidden_layouts[i];
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentDescriptionStencilLayout-stencilFinalLayout-03309");
}
attachment_description_stencil_layout.stencilFinalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentDescriptionStencilLayout-stencilFinalLayout-03310");
attachment_description_stencil_layout.stencilFinalLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentDescriptionStencilLayout-stencilFinalLayout-03310");
rpci2.pAttachments[0].pNext = nullptr;
}
} else {
if (depth_format) {
attach_desc.format = depth_format;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-separateDepthStencilLayouts-03284",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03298");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-separateDepthStencilLayouts-03284",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03298");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-separateDepthStencilLayouts-03285",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03299");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-separateDepthStencilLayouts-03285",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03299");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
}
if (stencil_format) {
attach_desc.format = stencil_format;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-separateDepthStencilLayouts-03284",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03298");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-separateDepthStencilLayouts-03284",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03298");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-separateDepthStencilLayouts-03285",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03299");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkAttachmentDescription-separateDepthStencilLayouts-03285",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03299");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
}
}
// Test invalid layouts for color formats
attach_desc.format = VK_FORMAT_R8G8B8A8_UNORM;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03280",
"VUID-VkAttachmentDescription2-format-03294");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03282",
"VUID-VkAttachmentDescription2-format-03296");
// Test invalid layouts for depth/stencil format
if (depth_stencil_format) {
attach_desc.format = depth_stencil_format;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03281",
"VUID-VkAttachmentDescription2-format-03295");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03283",
"VUID-VkAttachmentDescription2-format-03297");
}
}
TEST_F(VkLayerTest, RenderPassCreateAttachmentsMisc) {
TEST_DESCRIPTION(
"Ensure that CreateRenderPass produces the expected validation errors when a subpass's attachments violate the valid usage "
"conditions.");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
ASSERT_NO_FATAL_FAILURE(InitState());
const VkFormat ds_format = FindSupportedDepthStencilFormat(gpu());
if (ds_format == VK_FORMAT_UNDEFINED) {
printf("%s No Depth + Stencil format found rest of tests skipped.\n", kSkipPrefix);
return;
}
std::vector<VkAttachmentDescription> attachments = {
// input attachments
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_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_GENERAL, VK_IMAGE_LAYOUT_GENERAL},
// color attachments
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_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_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_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_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
// depth attachment
{0, ds_format, VK_SAMPLE_COUNT_4_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_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL},
// resolve attachment
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
// preserve attachments
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_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_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
// depth non-resolve attachment
{0, ds_format, 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_GENERAL, VK_IMAGE_LAYOUT_GENERAL},
};
std::vector<VkAttachmentReference> input = {
{0, VK_IMAGE_LAYOUT_GENERAL},
};
std::vector<VkAttachmentReference> color = {
{1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
{2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
};
VkAttachmentReference depth = {3, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
std::vector<VkAttachmentReference> resolve = {
{4, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
{VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
};
std::vector<uint32_t> preserve = {5};
std::vector<VkAttachmentReference> depth_1bit = {
{6, VK_IMAGE_LAYOUT_GENERAL},
{6, VK_IMAGE_LAYOUT_GENERAL},
};
VkSubpassDescription subpass = {0,
VK_PIPELINE_BIND_POINT_GRAPHICS,
(uint32_t)input.size(),
input.data(),
(uint32_t)color.size(),
color.data(),
resolve.data(),
&depth,
(uint32_t)preserve.size(),
preserve.data()};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
nullptr,
0,
(uint32_t)attachments.size(),
attachments.data(),
1,
&subpass,
0,
nullptr};
// Test too many color attachments
const uint32_t max_color_attachments = m_device->props.limits.maxColorAttachments;
const uint32_t too_big_max_attachments = 65536 + 1; // let's say this is too much to allocate
if (max_color_attachments >= too_big_max_attachments) {
printf(
"%s VkPhysicalDeviceLimits::maxColorAttachments is too large to practically test against -- skipping part of test.\n",
kSkipPrefix);
} else {
std::vector<VkAttachmentReference> too_many_colors(max_color_attachments + 1, color[0]);
VkSubpassDescription test_subpass = subpass;
test_subpass.colorAttachmentCount = (uint32_t)too_many_colors.size();
test_subpass.pColorAttachments = too_many_colors.data();
test_subpass.pResolveAttachments = NULL;
VkRenderPassCreateInfo test_rpci = rpci;
test_rpci.pSubpasses = &test_subpass;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &test_rpci, rp2Supported,
"VUID-VkSubpassDescription-colorAttachmentCount-00845",
"VUID-VkSubpassDescription2-colorAttachmentCount-03063");
}
// Test sample count mismatch between color buffers
attachments[subpass.pColorAttachments[1].attachment].samples = VK_SAMPLE_COUNT_8_BIT;
depth.attachment = VK_ATTACHMENT_UNUSED; // Avoids triggering 01418
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkSubpassDescription-pColorAttachments-01417", "VUID-VkSubpassDescription2-pColorAttachments-03069");
depth.attachment = 3;
attachments[subpass.pColorAttachments[1].attachment].samples = attachments[subpass.pColorAttachments[0].attachment].samples;
// Test sample count mismatch between color buffers and depth buffer
attachments[subpass.pDepthStencilAttachment->attachment].samples = VK_SAMPLE_COUNT_8_BIT;
subpass.colorAttachmentCount = 1;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkSubpassDescription-pDepthStencilAttachment-01418",
"VUID-VkSubpassDescription2-pDepthStencilAttachment-03071");
attachments[subpass.pDepthStencilAttachment->attachment].samples = attachments[subpass.pColorAttachments[0].attachment].samples;
subpass.colorAttachmentCount = (uint32_t)color.size();
// Test resolve attachment with UNUSED color attachment
color[0].attachment = VK_ATTACHMENT_UNUSED;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkSubpassDescription-pResolveAttachments-00847",
"VUID-VkSubpassDescription2-pResolveAttachments-03065");
color[0].attachment = 1;
// Test resolve from a single-sampled color attachment
attachments[subpass.pColorAttachments[0].attachment].samples = VK_SAMPLE_COUNT_1_BIT;
subpass.colorAttachmentCount = 1; // avoid mismatch (00337), and avoid double report
subpass.pDepthStencilAttachment = nullptr; // avoid mismatch (01418)
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkSubpassDescription-pResolveAttachments-00848",
"VUID-VkSubpassDescription2-pResolveAttachments-03066");
attachments[subpass.pColorAttachments[0].attachment].samples = VK_SAMPLE_COUNT_4_BIT;
subpass.colorAttachmentCount = (uint32_t)color.size();
subpass.pDepthStencilAttachment = &depth;
// Test resolve to a multi-sampled resolve attachment
attachments[subpass.pResolveAttachments[0].attachment].samples = VK_SAMPLE_COUNT_4_BIT;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkSubpassDescription-pResolveAttachments-00849",
"VUID-VkSubpassDescription2-pResolveAttachments-03067");
attachments[subpass.pResolveAttachments[0].attachment].samples = VK_SAMPLE_COUNT_1_BIT;
// Test with color/resolve format mismatch
attachments[subpass.pColorAttachments[0].attachment].format = VK_FORMAT_R8G8B8A8_SRGB;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkSubpassDescription-pResolveAttachments-00850",
"VUID-VkSubpassDescription2-pResolveAttachments-03068");
attachments[subpass.pColorAttachments[0].attachment].format = attachments[subpass.pResolveAttachments[0].attachment].format;
// Test for UNUSED preserve attachments
preserve[0] = VK_ATTACHMENT_UNUSED;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDescription-attachment-00853",
"VUID-VkSubpassDescription2-attachment-03073");
preserve[0] = 5;
// Test for preserve attachments used elsewhere in the subpass
color[0].attachment = preserve[0];
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkSubpassDescription-pPreserveAttachments-00854",
"VUID-VkSubpassDescription2-pPreserveAttachments-03074");
color[0].attachment = 1;
input[0].attachment = 0;
input[0].layout = VK_IMAGE_LAYOUT_GENERAL;
// Test for attachment used first as input with loadOp=CLEAR
{
std::vector<VkSubpassDescription> subpasses = {subpass, subpass, subpass};
subpasses[0].inputAttachmentCount = 0;
subpasses[1].inputAttachmentCount = 0;
attachments[input[0].attachment].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
VkRenderPassCreateInfo rpci_multipass = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
nullptr,
0,
(uint32_t)attachments.size(),
attachments.data(),
(uint32_t)subpasses.size(),
subpasses.data(),
0,
nullptr};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci_multipass, rp2Supported,
"VUID-VkSubpassDescription-loadOp-00846", "VUID-VkSubpassDescription2-loadOp-03064");
attachments[input[0].attachment].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
}
// Test for depthStencil and color pointing to same attachment
{
// Both use same VkAttachmentReference
VkSubpassDescription subpass_same = {
0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, depth_1bit.data(), nullptr, depth_1bit.data(), 0, nullptr};
VkRenderPassCreateInfo rpci_same = rpci;
rpci_same.pSubpasses = &subpass_same;
// only test rp1 so can ignore the expected 2nd error
m_errorMonitor->SetUnexpectedError("VUID-VkSubpassDescription-pColorAttachments-02648");
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci_same, rp2Supported,
"VUID-VkSubpassDescription-pDepthStencilAttachment-04438", nullptr);
if (rp2Supported) {
safe_VkRenderPassCreateInfo2 create_info2;
ConvertVkRenderPassCreateInfoToV2KHR(rpci_same, &create_info2);
m_errorMonitor->SetUnexpectedError("VUID-VkSubpassDescription2-pColorAttachments-02898");
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), create_info2.ptr(),
"VUID-VkSubpassDescription2-pDepthStencilAttachment-04440");
}
// Same test but use 2 different VkAttachmentReference to point to same attachment
subpass_same.pDepthStencilAttachment = &depth_1bit.data()[1];
m_errorMonitor->SetUnexpectedError("VUID-VkSubpassDescription-pColorAttachments-02648");
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci_same, rp2Supported,
"VUID-VkSubpassDescription-pDepthStencilAttachment-04438", nullptr);
if (rp2Supported) {
safe_VkRenderPassCreateInfo2 create_info2;
ConvertVkRenderPassCreateInfoToV2KHR(rpci_same, &create_info2);
m_errorMonitor->SetUnexpectedError("VUID-VkSubpassDescription2-pColorAttachments-02898");
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), create_info2.ptr(),
"VUID-VkSubpassDescription2-pDepthStencilAttachment-04440");
}
}
}
TEST_F(VkLayerTest, InvalidRenderPassCreateRenderPassShaderResolveQCOM) {
TEST_DESCRIPTION("Ensure RenderPass create meets the requirements for QCOM_render_pass_shader_resolve");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
bool rpShaderResolveSupport = DeviceExtensionSupported(gpu(), nullptr, VK_QCOM_RENDER_PASS_SHADER_RESOLVE_EXTENSION_NAME);
if (rpShaderResolveSupport) {
m_device_extension_names.push_back(VK_QCOM_RENDER_PASS_SHADER_RESOLVE_EXTENSION_NAME);
} else {
printf("%s test requires QCOM_render_pass_shader_resolve, not available. Skipping.\n", kSkipPrefix);
return;
}
ASSERT_NO_FATAL_FAILURE(InitState());
const VkFormat ds_format = FindSupportedDepthStencilFormat(gpu());
if (ds_format == VK_FORMAT_UNDEFINED) {
printf("%s No Depth + Stencil format found rest of tests skipped.\n", kSkipPrefix);
return;
}
std::vector<VkAttachmentDescription> attachments = {
// input attachments
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_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_GENERAL, VK_IMAGE_LAYOUT_GENERAL},
// color attachments
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_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_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_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_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
// depth attachment
{0, ds_format, VK_SAMPLE_COUNT_4_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_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL},
// resolve attachment
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
};
std::vector<VkAttachmentReference> input = {
{0, VK_IMAGE_LAYOUT_GENERAL},
};
std::vector<VkAttachmentReference> color = {
{1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
{2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
};
VkAttachmentReference depth = {3, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
std::vector<VkAttachmentReference> resolve = {
{4, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
{VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
};
VkSubpassDescription subpass = {0,
VK_PIPELINE_BIND_POINT_GRAPHICS,
(uint32_t)input.size(),
input.data(),
(uint32_t)color.size(),
color.data(),
nullptr,
&depth,
0,
nullptr};
std::vector<VkSubpassDependency> dependency = {
{0, 1, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_ACCESS_MEMORY_WRITE_BIT,
VK_ACCESS_MEMORY_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT},
};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
nullptr,
0,
(uint32_t)attachments.size(),
attachments.data(),
1,
&subpass,
0,
nullptr};
// Create a resolve subpass where the pResolveattachments are not VK_ATTACHMENT_UNUSED
VkSubpassDescription test_subpass = subpass;
test_subpass.pResolveAttachments = resolve.data();
test_subpass.flags = VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM;
VkRenderPassCreateInfo test_rpci = rpci;
test_rpci.pSubpasses = &test_subpass;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &test_rpci, rp2Supported, "VUID-VkSubpassDescription-flags-03341",
"VUID-VkRenderPassCreateInfo2-flags-04907");
// Create a resolve subpass which is not the last subpass in the subpass dependency chain.
{
VkSubpassDescription subpasses[2] = {subpass, subpass};
subpasses[0].pResolveAttachments = nullptr;
subpasses[0].flags = VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM;
subpasses[1].pResolveAttachments = nullptr;
subpasses[1].flags = 0;
VkRenderPassCreateInfo test2_rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
nullptr,
0,
(uint32_t)attachments.size(),
attachments.data(),
2,
subpasses,
(uint32_t)dependency.size(),
dependency.data()};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &test2_rpci, rp2Supported, "VUID-VkSubpassDescription-flags-03343",
"VUID-VkRenderPassCreateInfo2-flags-04909");
}
}
TEST_F(VkLayerTest, RenderPassCreateAttachmentReferenceInvalidLayout) {
TEST_DESCRIPTION("Attachment reference uses PREINITIALIZED or UNDEFINED layouts");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME);
}
PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR =
(PFN_vkGetPhysicalDeviceFeatures2KHR)vk::GetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR");
auto separate_depth_stencil_layouts_features = LvlInitStruct<VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR>();
auto features2 = LvlInitStruct<VkPhysicalDeviceFeatures2KHR>(&separate_depth_stencil_layouts_features);
if (vkGetPhysicalDeviceFeatures2KHR) {
vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2);
} else {
separate_depth_stencil_layouts_features.separateDepthStencilLayouts = VK_FALSE;
}
ASSERT_NO_FATAL_FAILURE(InitState(nullptr, (vkGetPhysicalDeviceFeatures2KHR) ? &features2 : nullptr));
const VkFormat ds_format = FindSupportedDepthStencilFormat(gpu());
const VkFormat depth_only_format = FindSupportedDepthOnlyFormat(gpu());
const VkFormat stencil_only_format = FindSupportedStencilOnlyFormat(gpu());
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},
{0, ds_format, 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_DEPTH_STENCIL_ATTACHMENT_OPTIMAL},
};
VkAttachmentReference refs[] = {
{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, // color
{1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}, // depth stencil
};
VkSubpassDescription subpasses[] = {
{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &refs[0], nullptr, &refs[1], 0, nullptr},
};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 2, attach, 1, subpasses, 0, nullptr};
// Use UNDEFINED layout
refs[0].layout = VK_IMAGE_LAYOUT_UNDEFINED;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentReference-layout-00857",
"VUID-VkAttachmentReference2-layout-03077");
// Use PREINITIALIZED layout
refs[0].layout = VK_IMAGE_LAYOUT_PREINITIALIZED;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentReference-layout-00857",
"VUID-VkAttachmentReference2-layout-03077");
if (rp2Supported) {
safe_VkRenderPassCreateInfo2 rpci2;
ConvertVkRenderPassCreateInfoToV2KHR(rpci, &rpci2);
// set valid values to start
rpci2.pSubpasses[0].pColorAttachments[0].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
rpci2.pSubpasses[0].pColorAttachments[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
rpci2.pSubpasses[0].pDepthStencilAttachment->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
rpci2.pSubpasses[0].pColorAttachments[0].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(), "VUID-VkSubpassDescription2-None-04439");
rpci2.pSubpasses[0].pColorAttachments[0].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(), "VUID-VkSubpassDescription2-None-04439");
rpci2.pSubpasses[0].pColorAttachments[0].layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(), "VUID-VkSubpassDescription2-None-04439");
rpci2.pSubpasses[0].pColorAttachments[0].layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(), "VUID-VkSubpassDescription2-None-04439");
rpci2.pSubpasses[0].pColorAttachments[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // reset
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(), "VUID-VkSubpassDescription2-None-04439");
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR; // reset
if (separate_depth_stencil_layouts_features.separateDepthStencilLayouts) {
// No VkAttachmentReferenceStencilLayout set
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentReference2-attachment-04755");
// Set a valid VkAttachmentReferenceStencilLayout since the feature bit is set
auto attachment_reference_stencil_layout = LvlInitStruct<VkAttachmentReferenceStencilLayout>();
attachment_reference_stencil_layout.stencilLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
rpci2.pSubpasses[0].pDepthStencilAttachment->pNext = &attachment_reference_stencil_layout;
// Tests invalid use of color attachment with layouts
// Duels as tests for 04754 since the attachment format is not a depth/stencil format
{
rpci2.pSubpasses[0].pColorAttachments[0].layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAttachmentReference2-attachment-04754");
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(), "VUID-VkSubpassDescription2-None-04439");
rpci2.pSubpasses[0].pColorAttachments[0].layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAttachmentReference2-attachment-04754");
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(), "VUID-VkSubpassDescription2-None-04439");
rpci2.pSubpasses[0].pColorAttachments[0].layout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAttachmentReference2-attachment-04754");
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(), "VUID-VkSubpassDescription2-None-04439");
rpci2.pSubpasses[0].pColorAttachments[0].layout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAttachmentReference2-attachment-04754");
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(), "VUID-VkSubpassDescription2-None-04439");
}
// reset to valid layout
// The following tests originally were negative tests until it was noticed that the aspectMask only matters for input
// attachments. These tests were converted into positive tests to catch regression
rpci2.pSubpasses[0].pColorAttachments[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
{
rpci2.pSubpasses[0].pDepthStencilAttachment->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
PositiveTestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr());
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
PositiveTestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr());
}
{
rpci2.pSubpasses[0].pDepthStencilAttachment->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
PositiveTestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr());
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
PositiveTestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr());
}
{
rpci2.pSubpasses[0].pDepthStencilAttachment->aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
PositiveTestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr());
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
PositiveTestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr());
}
// Test using depth-only or stencil-only format with wrong layout for the attachment reference
if (depth_only_format != VK_FORMAT_UNDEFINED) {
rpci2.pAttachments[1].format = depth_only_format;
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentReference2-attachment-04756");
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentReference2-attachment-04756");
}
if (stencil_only_format != VK_FORMAT_UNDEFINED) {
rpci2.pAttachments[1].format = stencil_only_format;
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentReference2-attachment-04757");
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentReference2-attachment-04757");
}
rpci2.pAttachments[1].format = ds_format; // reset
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // reset
VkImageLayout forbidden_layouts[] = {VK_IMAGE_LAYOUT_PREINITIALIZED,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR,
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR};
rpci2.pSubpasses[0].pDepthStencilAttachment->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
for (size_t i = 0; i < (sizeof(forbidden_layouts) / sizeof(forbidden_layouts[0])); ++i) {
attachment_reference_stencil_layout.stencilLayout = forbidden_layouts[i];
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentReferenceStencilLayout-stencilLayout-03318");
}
rpci2.pSubpasses[0].pDepthStencilAttachment->pNext = nullptr;
} else {
rpci2.pSubpasses[0].pDepthStencilAttachment->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentReference2-separateDepthStencilLayouts-03313");
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentReference2-separateDepthStencilLayouts-03313");
rpci2.pSubpasses[0].pDepthStencilAttachment->aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentReference2-separateDepthStencilLayouts-03313");
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR;
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), rpci2.ptr(),
"VUID-VkAttachmentReference2-separateDepthStencilLayouts-03313");
}
}
}
TEST_F(VkLayerTest, RenderPassCreateOverlappingCorrelationMasks) {
TEST_DESCRIPTION("Create a subpass with overlapping correlation masks");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
if (!rp2Supported) {
if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MULTIVIEW_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME);
} else {
printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_MULTIVIEW_EXTENSION_NAME);
return;
}
}
ASSERT_NO_FATAL_FAILURE(InitState());
VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr};
uint32_t viewMasks[] = {0x3u};
uint32_t correlationMasks[] = {0x1u, 0x3u};
VkRenderPassMultiviewCreateInfo rpmvci = {
VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, nullptr, 1, viewMasks, 0, nullptr, 2, correlationMasks};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpmvci, 0, 0, nullptr, 1, &subpass, 0, nullptr};
// Correlation masks must not overlap
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkRenderPassMultiviewCreateInfo-pCorrelationMasks-00841",
"VUID-VkRenderPassCreateInfo2-pCorrelatedViewMasks-03056");
// Check for more specific "don't set any correlation masks when multiview is not enabled"
if (rp2Supported) {
viewMasks[0] = 0;
correlationMasks[0] = 0;
correlationMasks[1] = 0;
safe_VkRenderPassCreateInfo2 safe_rpci2;
ConvertVkRenderPassCreateInfoToV2KHR(rpci, &safe_rpci2);
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), safe_rpci2.ptr(),
"VUID-VkRenderPassCreateInfo2-viewMask-03057");
}
}
TEST_F(VkLayerTest, RenderPassCreateInvalidViewMasks) {
TEST_DESCRIPTION("Create a subpass with the wrong number of view masks, or inconsistent setting of view masks");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
if (!rp2Supported) {
if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MULTIVIEW_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME);
} else {
printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_MULTIVIEW_EXTENSION_NAME);
return;
}
}
ASSERT_NO_FATAL_FAILURE(InitState());
VkSubpassDescription subpasses[] = {
{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr},
{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr},
};
uint32_t viewMasks[] = {0x3u, 0u};
VkRenderPassMultiviewCreateInfo rpmvci = {
VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, nullptr, 1, viewMasks, 0, nullptr, 0, nullptr};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpmvci, 0, 0, nullptr, 2, subpasses, 0, nullptr};
// Not enough view masks
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-pNext-01928",
"VUID-VkRenderPassCreateInfo2-viewMask-03058");
}
TEST_F(VkLayerTest, RenderPassCreateInvalidInputAttachmentReferences) {
TEST_DESCRIPTION("Create a subpass with the meta data aspect mask set for an input attachment");
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE_2_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
} else {
printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
return;
}
ASSERT_NO_FATAL_FAILURE(InitState());
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_SHADER_READ_ONLY_OPTIMAL};
VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 0, nullptr, nullptr, nullptr, 0, nullptr};
VkInputAttachmentAspectReference iaar = {0, 0, VK_IMAGE_ASPECT_METADATA_BIT};
VkRenderPassInputAttachmentAspectCreateInfo rpiaaci = {VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO,
nullptr, 1, &iaar};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpiaaci, 0, 1, &attach, 1, &subpass, 0, nullptr};
// Invalid aspect masks
// Cannot/should not avoid getting the unxpected ones too
iaar.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT;
m_errorMonitor->SetUnexpectedError("VUID-VkRenderPassCreateInfo-pNext-01963");
m_errorMonitor->SetUnexpectedError("VUID-VkRenderPassCreateInfo2-attachment-02525");
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkInputAttachmentAspectReference-aspectMask-01964",
nullptr);
iaar.aspectMask = VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT;
m_errorMonitor->SetUnexpectedError("VUID-VkRenderPassCreateInfo-pNext-01963");
m_errorMonitor->SetUnexpectedError("VUID-VkRenderPassCreateInfo2-attachment-02525");
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkInputAttachmentAspectReference-aspectMask-02250",
nullptr);
// Aspect not present
iaar.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01963",
"VUID-VkRenderPassCreateInfo2-attachment-02525");
// Invalid subpass index
iaar.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
iaar.subpass = 1;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01926", nullptr);
iaar.subpass = 0;
// Invalid input attachment index
iaar.inputAttachmentIndex = 1;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01927", nullptr);
}
TEST_F(VkLayerTest, RenderPassCreateInvalidFragmentDensityMapReferences) {
TEST_DESCRIPTION("Create a subpass with the wrong attachment information for a fragment density map ");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
} else {
printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
return;
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME);
} else {
if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME);
} else {
printf("%s Neither extension %s nor %s is not supported.\n", kSkipPrefix, VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME,
VK_EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME);
return;
}
}
ASSERT_NO_FATAL_FAILURE(InitState());
VkAttachmentDescription attach = {0,
VK_FORMAT_R8G8_UNORM,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_LOAD,
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_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT};
// Set 1 instead of 0
VkAttachmentReference ref = {1, VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT};
VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 0, nullptr, nullptr, nullptr, 0, nullptr};
VkRenderPassFragmentDensityMapCreateInfoEXT rpfdmi = {VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT,
nullptr, ref};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpfdmi, 0, 1, &attach, 1, &subpass, 0, nullptr};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false,
"VUID-VkRenderPassFragmentDensityMapCreateInfoEXT-fragmentDensityMapAttachment-02547", nullptr);
// Set wrong VkImageLayout
ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 0, nullptr, nullptr, nullptr, 0, nullptr};
rpfdmi = {VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT, nullptr, ref};
rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpfdmi, 0, 1, &attach, 1, &subpass, 0, nullptr};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false,
"VUID-VkRenderPassFragmentDensityMapCreateInfoEXT-fragmentDensityMapAttachment-02549", nullptr);
// Set wrong load operation
attach = {0,
VK_FORMAT_R8G8_UNORM,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_CLEAR,
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_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT};
ref = {0, VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT};
subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 0, nullptr, nullptr, nullptr, 0, nullptr};
rpfdmi = {VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT, nullptr, ref};
rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpfdmi, 0, 1, &attach, 1, &subpass, 0, nullptr};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false,
"VUID-VkRenderPassFragmentDensityMapCreateInfoEXT-fragmentDensityMapAttachment-02550", nullptr);
// Set wrong store operation
attach = {0,
VK_FORMAT_R8G8_UNORM,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT};
ref = {0, VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT};
subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 0, nullptr, nullptr, nullptr, 0, nullptr};
rpfdmi = {VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT, nullptr, ref};
rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpfdmi, 0, 1, &attach, 1, &subpass, 0, nullptr};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false,
"VUID-VkRenderPassFragmentDensityMapCreateInfoEXT-fragmentDensityMapAttachment-02551", nullptr);
}
TEST_F(VkLayerTest, RenderPassCreateSubpassNonGraphicsPipeline) {
TEST_DESCRIPTION("Create a subpass with the compute pipeline bind point");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
ASSERT_NO_FATAL_FAILURE(InitState());
VkSubpassDescription subpasses[] = {
{0, VK_PIPELINE_BIND_POINT_COMPUTE, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr},
};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 1, subpasses, 0, nullptr};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkSubpassDescription-pipelineBindPoint-04952", "VUID-VkSubpassDescription2-pipelineBindPoint-04953");
}
TEST_F(VkLayerTest, RenderPassCreateSubpassMissingAttributesBitMultiviewNVX) {
TEST_DESCRIPTION("Create a subpass with the VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX flag missing");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
} else {
printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME);
return;
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
if (DeviceExtensionSupported(gpu(), nullptr, VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME) &&
DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MULTIVIEW_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME);
m_device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME);
} else {
printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME);
return;
}
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
ASSERT_NO_FATAL_FAILURE(InitState());
VkSubpassDescription subpasses[] = {
{VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr,
nullptr, 0, nullptr},
};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 1, subpasses, 0, nullptr};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDescription-flags-00856",
"VUID-VkSubpassDescription2-flags-03076");
}
TEST_F(VkLayerTest, RenderPassCreate2SubpassInvalidInputAttachmentParameters) {
TEST_DESCRIPTION("Create a subpass with parameters in the input attachment ref which are invalid");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
} else {
printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
return;
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
if (!rp2Supported) {
printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
return;
}
ASSERT_NO_FATAL_FAILURE(InitState());
VkAttachmentDescription2KHR attach_desc = {};
attach_desc.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR;
attach_desc.format = VK_FORMAT_UNDEFINED;
attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkAttachmentReference2KHR reference = {};
reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
reference.layout = VK_IMAGE_LAYOUT_GENERAL;
reference.aspectMask = 0;
VkSubpassDescription2KHR subpass = {VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR,
nullptr,
0,
VK_PIPELINE_BIND_POINT_GRAPHICS,
0,
1,
&reference,
0,
nullptr,
nullptr,
nullptr,
0,
nullptr};
VkRenderPassCreateInfo2KHR rpci2 = {
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR, nullptr, 0, 1, &attach_desc, 1, &subpass, 0, nullptr, 0, nullptr};
// Test for aspect mask of 0
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSubpassDescription2-pInputAttachments-02897");
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), &rpci2, "VUID-VkSubpassDescription2-attachment-02800");
// Test for invalid aspect mask bits
reference.aspectMask = 0x40000000; // invalid VkImageAspectFlagBits value
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSubpassDescription2-pInputAttachments-02897");
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), &rpci2, "VUID-VkSubpassDescription2-attachment-02799");
// Test for invalid use of VK_IMAGE_ASPECT_METADATA_BIT
reference.aspectMask = VK_IMAGE_ASPECT_METADATA_BIT;
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkSubpassDescription2-pInputAttachments-02897");
TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), &rpci2, "VUID-VkSubpassDescription2-attachment-02801");
}
TEST_F(VkLayerTest, RenderPassCreateInvalidSubpassDependencies) {
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2_supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
bool multiviewSupported = rp2_supported;
if (!rp2_supported && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MULTIVIEW_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME);
multiviewSupported = true;
}
// Add a device features struct enabling NO features
VkPhysicalDeviceFeatures features = {0};
ASSERT_NO_FATAL_FAILURE(InitState(&features));
if (DeviceValidationVersion() >= VK_API_VERSION_1_1) {
multiviewSupported = true;
}
// Create two dummy subpasses
VkSubpassDescription subpasses[] = {
{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr},
{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr},
};
VkSubpassDependency dependency;
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 2, subpasses, 1, &dependency};
// Non graphics stages in subpass dependency
dependency = {0, 1, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
"VUID-VkRenderPassCreateInfo-pDependencies-00837", "VUID-VkRenderPassCreateInfo2-pDependencies-03054");
dependency = {0, 1, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
"VUID-VkRenderPassCreateInfo-pDependencies-00837", "VUID-VkRenderPassCreateInfo2-pDependencies-03054");
dependency = {0, 1, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
"VUID-VkRenderPassCreateInfo-pDependencies-00837", "VUID-VkRenderPassCreateInfo2-pDependencies-03054");
dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
"VUID-VkRenderPassCreateInfo-pDependencies-00838", "VUID-VkRenderPassCreateInfo2-pDependencies-03055");
dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
"VUID-VkRenderPassCreateInfo-pDependencies-00838", "VUID-VkRenderPassCreateInfo2-pDependencies-03055");
dependency = {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
"VUID-VkRenderPassCreateInfo-pDependencies-00837", "VUID-VkRenderPassCreateInfo2-pDependencies-03054");
dependency = {VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
"VUID-VkRenderPassCreateInfo-pDependencies-00838", "VUID-VkRenderPassCreateInfo2-pDependencies-03055");
dependency = {0, 0, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
"VUID-VkRenderPassCreateInfo-pDependencies-00837", "VUID-VkRenderPassCreateInfo2-pDependencies-03054");
// Geometry shaders not enabled source
dependency = {0, 1, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcStageMask-00860",
"VUID-VkSubpassDependency2-srcStageMask-03080");
// Geometry shaders not enabled destination
dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-dstStageMask-00861",
"VUID-VkSubpassDependency2-dstStageMask-03081");
// Tessellation not enabled source
dependency = {0, 1, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcStageMask-00862",
"VUID-VkSubpassDependency2-srcStageMask-03082");
// Tessellation not enabled destination
dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-dstStageMask-00863",
"VUID-VkSubpassDependency2-dstStageMask-03083");
// Potential cyclical dependency
dependency = {1, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcSubpass-00864",
"VUID-VkSubpassDependency2-srcSubpass-03084");
// EXTERNAL to EXTERNAL dependency
dependency = {
VK_SUBPASS_EXTERNAL, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcSubpass-00865",
"VUID-VkSubpassDependency2-srcSubpass-03085");
// Logically later source stages in self dependency
dependency = {0, 0, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcSubpass-00867",
"VUID-VkSubpassDependency2-srcSubpass-03087");
// framebuffer space stages in self dependency with region bit
dependency = {0, 0, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcSubpass-02243",
"VUID-VkSubpassDependency2-srcSubpass-02245");
// Same test but make sure the logical invalid order does not trip other VUID since both are framebuffer space stages
dependency = {0, 0, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcSubpass-02243",
"VUID-VkSubpassDependency2-srcSubpass-02245");
// Source access mask mismatch with source stage mask
dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_ACCESS_UNIFORM_READ_BIT, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcAccessMask-00868",
"VUID-VkSubpassDependency2-srcAccessMask-03088");
// Destination access mask mismatch with destination stage mask
dependency = {
0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-dstAccessMask-00869",
"VUID-VkSubpassDependency2-dstAccessMask-03089");
// srcSubpass larger than subpassCount
dependency = {3, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkRenderPassCreateInfo-srcSubpass-02517",
"VUID-VkRenderPassCreateInfo2-srcSubpass-02526");
// dstSubpass larger than subpassCount
dependency = {0, 3, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkRenderPassCreateInfo-dstSubpass-02518",
"VUID-VkRenderPassCreateInfo2-dstSubpass-02527");
if (multiviewSupported) {
// VIEW_LOCAL_BIT but multiview is not enabled
dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0, 0, VK_DEPENDENCY_VIEW_LOCAL_BIT};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, nullptr,
"VUID-VkRenderPassCreateInfo2-viewMask-03059");
// Enable multiview
uint32_t pViewMasks[2] = {0x3u, 0x3u};
int32_t pViewOffsets[2] = {0, 0};
VkRenderPassMultiviewCreateInfo rpmvci = {
VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, nullptr, 2, pViewMasks, 0, nullptr, 0, nullptr};
rpci.pNext = &rpmvci;
// Excessive view offsets
dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0, 0, VK_DEPENDENCY_VIEW_LOCAL_BIT};
rpmvci.pViewOffsets = pViewOffsets;
rpmvci.dependencyCount = 2;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01929", nullptr);
rpmvci.dependencyCount = 0;
// View offset with subpass self dependency
dependency = {0, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0, 0, VK_DEPENDENCY_VIEW_LOCAL_BIT};
rpmvci.pViewOffsets = pViewOffsets;
pViewOffsets[0] = 1;
rpmvci.dependencyCount = 1;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01930",
"VUID-VkSubpassDependency2-viewOffset-02530");
rpmvci.dependencyCount = 0;
// View offset with no view local bit
if (rp2_supported) {
dependency = {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
rpmvci.pViewOffsets = pViewOffsets;
pViewOffsets[0] = 1;
rpmvci.dependencyCount = 1;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, nullptr,
"VUID-VkSubpassDependency2-dependencyFlags-03092");
rpmvci.dependencyCount = 0;
}
// EXTERNAL subpass with VIEW_LOCAL_BIT - source subpass
dependency = {VK_SUBPASS_EXTERNAL, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0,
VK_DEPENDENCY_VIEW_LOCAL_BIT};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
"VUID-VkSubpassDependency-dependencyFlags-02520", "VUID-VkSubpassDependency2-dependencyFlags-03090");
// EXTERNAL subpass with VIEW_LOCAL_BIT - destination subpass
dependency = {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0,
0, VK_DEPENDENCY_VIEW_LOCAL_BIT};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
"VUID-VkSubpassDependency-dependencyFlags-02521", "VUID-VkSubpassDependency2-dependencyFlags-03091");
// Multiple views but no view local bit in self-dependency
dependency = {0, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcSubpass-00872",
"VUID-VkRenderPassCreateInfo2-pDependencies-03060");
}
}
TEST_F(VkLayerTest, RenderPassCreateInvalidMixedAttachmentSamplesAMD) {
TEST_DESCRIPTION("Verify error messages for supported and unsupported sample counts in render pass attachments.");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
if (DeviceExtensionSupported(gpu(), nullptr, VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME);
} else {
printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME);
return;
}
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
ASSERT_NO_FATAL_FAILURE(InitState());
std::vector<VkAttachmentDescription> attachments;
{
VkAttachmentDescription att = {};
att.format = VK_FORMAT_R8G8B8A8_UNORM;
att.samples = VK_SAMPLE_COUNT_1_BIT;
att.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
att.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
att.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachments.push_back(att);
att.format = VK_FORMAT_D16_UNORM;
att.samples = VK_SAMPLE_COUNT_4_BIT;
att.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
att.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
att.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachments.push_back(att);
}
VkAttachmentReference color_ref = {};
color_ref.attachment = 0;
color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference depth_ref = {};
depth_ref.attachment = 1;
depth_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_ref;
subpass.pDepthStencilAttachment = &depth_ref;
VkRenderPassCreateInfo rpci = {};
rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
rpci.attachmentCount = attachments.size();
rpci.pAttachments = attachments.data();
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
m_errorMonitor->ExpectSuccess();
VkRenderPass rp;
VkResult err;
err = vk::CreateRenderPass(device(), &rpci, NULL, &rp);
m_errorMonitor->VerifyNotFound();
if (err == VK_SUCCESS) vk::DestroyRenderPass(m_device->device(), rp, nullptr);
// Expect an error message for invalid sample counts
attachments[0].samples = VK_SAMPLE_COUNT_4_BIT;
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
"VUID-VkSubpassDescription-pColorAttachments-01506", "VUID-VkSubpassDescription2-pColorAttachments-03070");
}
TEST_F(VkLayerTest, RenderPassBeginInvalidRenderArea) {
TEST_DESCRIPTION("Generate INVALID_RENDER_AREA error by beginning renderpass with extent outside of framebuffer");
SetTargetApiVersion(VK_API_VERSION_1_2);
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
bool device_group_supported = false;
if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DEVICE_GROUP_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_KHR_DEVICE_GROUP_EXTENSION_NAME);
device_group_supported = true;
}
ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
// Framebuffer for render target is 256x256, exceed that for INVALID_RENDER_AREA
m_renderPassBeginInfo.renderArea.extent.width = 257;
m_renderPassBeginInfo.renderArea.extent.height = 256;
const char *vuid =
device_group_supported ? "VUID-VkRenderPassBeginInfo-pNext-02852" : "VUID-VkRenderPassBeginInfo-renderArea-02848";
TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &m_renderPassBeginInfo, rp2Supported, vuid,
vuid);
}
TEST_F(VkLayerTest, RenderPassBeginWithinRenderPass) {
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR = nullptr;
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
ASSERT_NO_FATAL_FAILURE(InitState());
if (rp2Supported) {
vkCmdBeginRenderPass2KHR =
(PFN_vkCmdBeginRenderPass2KHR)vk::GetDeviceProcAddr(m_device->device(), "vkCmdBeginRenderPass2KHR");
}
ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
// Bind a BeginRenderPass within an active RenderPass
m_commandBuffer->begin();
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
// Just use a dummy Renderpass
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBeginRenderPass-renderpass");
vk::CmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
m_errorMonitor->VerifyFound();
if (rp2Supported) {
VkSubpassBeginInfoKHR subpassBeginInfo = {VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR, nullptr, VK_SUBPASS_CONTENTS_INLINE};
m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBeginRenderPass2-renderpass");
vkCmdBeginRenderPass2KHR(m_commandBuffer->handle(), &m_renderPassBeginInfo, &subpassBeginInfo);
m_errorMonitor->VerifyFound();
}
}
TEST_F(VkLayerTest, RenderPassBeginIncompatibleFramebufferRenderPass) {
TEST_DESCRIPTION("Test that renderpass begin is compatible with the framebuffer renderpass ");
ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
// Create a depth stencil image view
VkImageObj image(m_device);
image.Init(128, 128, 1, VK_FORMAT_D16_UNORM, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL);
ASSERT_TRUE(image.initialized());
VkImageView dsv;
VkImageViewCreateInfo dsvci = {};
dsvci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
dsvci.pNext = nullptr;
dsvci.image = image.handle();
dsvci.viewType = VK_IMAGE_VIEW_TYPE_2D;
dsvci.format = VK_FORMAT_D16_UNORM;
dsvci.subresourceRange.layerCount = 1;
dsvci.subresourceRange.baseMipLevel = 0;
dsvci.subresourceRange.levelCount = 1;
dsvci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
vk::CreateImageView(m_device->device(), &dsvci, NULL, &dsv);
// Create a renderPass with a single attachment that uses loadOp CLEAR
VkAttachmentDescription description = {0,
VK_FORMAT_D16_UNORM,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_GENERAL};
VkAttachmentReference depth_stencil_ref = {0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, &depth_stencil_ref, 0,
nullptr};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &description, 1, &subpass, 0, nullptr};
VkRenderPass rp1, rp2;
vk::CreateRenderPass(m_device->device(), &rpci, NULL, &rp1);
subpass.pDepthStencilAttachment = nullptr;
vk::CreateRenderPass(m_device->device(), &rpci, NULL, &rp2);
// Create a framebuffer
VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp1, 1, &dsv, 128, 128, 1};
VkFramebuffer fb;
vk::CreateFramebuffer(m_device->handle(), &fbci, nullptr, &fb);
VkRenderPassBeginInfo rp_begin = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, rp2, fb, {{0, 0}, {128, 128}}, 0, nullptr};
TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, false,
"VUID-VkRenderPassBeginInfo-renderPass-00904", nullptr);
vk::DestroyRenderPass(m_device->device(), rp1, nullptr);
vk::DestroyRenderPass(m_device->device(), rp2, nullptr);
vk::DestroyFramebuffer(m_device->device(), fb, nullptr);
vk::DestroyImageView(m_device->device(), dsv, nullptr);
}
TEST_F(VkLayerTest, RenderPassBeginLayoutsFramebufferImageUsageMismatches) {
TEST_DESCRIPTION(
"Test that renderpass initial/final layouts match up with the usage bits set for each attachment of the framebuffer");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
bool maintenance2Supported = rp2Supported;
// Check for VK_KHR_maintenance2
if (!rp2Supported && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE_2_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
maintenance2Supported = true;
}
ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
if (DeviceValidationVersion() >= VK_API_VERSION_1_1) {
maintenance2Supported = true;
}
// Create an input attachment view
VkImageObj iai(m_device);
iai.InitNoLayout(128, 128, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL);
ASSERT_TRUE(iai.initialized());
VkImageView iav;
VkImageViewCreateInfo iavci = {};
iavci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
iavci.pNext = nullptr;
iavci.image = iai.handle();
iavci.viewType = VK_IMAGE_VIEW_TYPE_2D;
iavci.format = VK_FORMAT_R8G8B8A8_UNORM;
iavci.subresourceRange.layerCount = 1;
iavci.subresourceRange.baseMipLevel = 0;
iavci.subresourceRange.levelCount = 1;
iavci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
vk::CreateImageView(m_device->device(), &iavci, NULL, &iav);
// Create a color attachment view
VkImageObj cai(m_device);
cai.InitNoLayout(128, 128, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL);
ASSERT_TRUE(cai.initialized());
VkImageView cav;
VkImageViewCreateInfo cavci = {};
cavci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
cavci.pNext = nullptr;
cavci.image = cai.handle();
cavci.viewType = VK_IMAGE_VIEW_TYPE_2D;
cavci.format = VK_FORMAT_R8G8B8A8_UNORM;
cavci.subresourceRange.layerCount = 1;
cavci.subresourceRange.baseMipLevel = 0;
cavci.subresourceRange.levelCount = 1;
cavci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
vk::CreateImageView(m_device->device(), &cavci, NULL, &cav);
// Create a renderPass with those attachments
VkAttachmentDescription descriptions[] = {
{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_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL},
{1, 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_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL}};
VkAttachmentReference input_ref = {0, VK_IMAGE_LAYOUT_GENERAL};
VkAttachmentReference color_ref = {1, VK_IMAGE_LAYOUT_GENERAL};
VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &input_ref, 1, &color_ref, nullptr, nullptr, 0, nullptr};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 2, descriptions, 1, &subpass, 0, nullptr};
// Create a framebuffer
VkImageView views[] = {iav, cav};
VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, VK_NULL_HANDLE, 2, views, 128, 128, 1};
VkClearValue clearValues[2];
clearValues[0].color = {{0, 0, 0, 0}};
clearValues[1].color = {{0, 0, 0, 0}};
VkRenderPassBeginInfo rp_begin = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, VK_NULL_HANDLE, VK_NULL_HANDLE, {{0, 0}, {128, 128}}, 2, clearValues};
auto test_layout_helper = [this, &rpci, &rp_begin, rp2Supported, &fbci](const char *rp1_vuid, const char *rp2_vuid) {
vk_testing::RenderPass rp_invalid(*m_device, rpci);
fbci.renderPass = rp_invalid.handle();
vk_testing::Framebuffer fb_invalid(*m_device, fbci);
rp_begin.renderPass = rp_invalid.handle();
rp_begin.framebuffer = fb_invalid.handle();
TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported, rp1_vuid,
rp2_vuid);
};
// Initial layout is VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but attachment doesn't support IMAGE_USAGE_COLOR_ATTACHMENT_BIT
descriptions[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
test_layout_helper("VUID-vkCmdBeginRenderPass-initialLayout-00895", "VUID-vkCmdBeginRenderPass2-initialLayout-03094");
// Initial layout is VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL but attachment doesn't support VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
// / VK_IMAGE_USAGE_SAMPLED_BIT
descriptions[0].initialLayout = VK_IMAGE_LAYOUT_GENERAL;
descriptions[1].initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
test_layout_helper("VUID-vkCmdBeginRenderPass-initialLayout-00897", "VUID-vkCmdBeginRenderPass2-initialLayout-03097");
descriptions[1].initialLayout = VK_IMAGE_LAYOUT_GENERAL;
// Initial layout is VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL but attachment doesn't support VK_IMAGE_USAGE_TRANSFER_SRC_BIT
descriptions[0].initialLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
test_layout_helper("VUID-vkCmdBeginRenderPass-initialLayout-00898", "VUID-vkCmdBeginRenderPass2-initialLayout-03098");
// Initial layout is VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL but attachment doesn't support VK_IMAGE_USAGE_TRANSFER_DST_BIT
descriptions[0].initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
test_layout_helper("VUID-vkCmdBeginRenderPass-initialLayout-00899", "VUID-vkCmdBeginRenderPass2-initialLayout-03099");
// Initial layout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL but attachment doesn't support
// VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
descriptions[0].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
descriptions[0].format = FindSupportedDepthStencilFormat(gpu());
const char *initial_layout_vuid_rp1 =
maintenance2Supported ? "VUID-vkCmdBeginRenderPass-initialLayout-01758" : "VUID-vkCmdBeginRenderPass-initialLayout-00896";
test_layout_helper(initial_layout_vuid_rp1, "VUID-vkCmdBeginRenderPass2-initialLayout-03096");
// Initial layout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL but attachment doesn't support
// VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
descriptions[0].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
test_layout_helper(initial_layout_vuid_rp1, "VUID-vkCmdBeginRenderPass2-initialLayout-03096");
if (maintenance2Supported || rp2Supported) {
// Initial layout is VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL but attachment doesn't support
// VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
descriptions[0].initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
test_layout_helper("VUID-vkCmdBeginRenderPass-initialLayout-01758", "VUID-vkCmdBeginRenderPass2-initialLayout-03096");
// Initial layout is VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL but attachment doesn't support
// VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
descriptions[0].initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
test_layout_helper("VUID-vkCmdBeginRenderPass-initialLayout-01758", "VUID-vkCmdBeginRenderPass2-initialLayout-03096");
}
vk::DestroyImageView(m_device->device(), iav, nullptr);
vk::DestroyImageView(m_device->device(), cav, nullptr);
}
TEST_F(VkLayerTest, RenderPassBeginClearOpMismatch) {
TEST_DESCRIPTION(
"Begin a renderPass where clearValueCount is less than the number of renderPass attachments that use "
"loadOp VK_ATTACHMENT_LOAD_OP_CLEAR.");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
// Create a renderPass with a single attachment that uses loadOp CLEAR
VkAttachmentReference attach = {};
attach.layout = VK_IMAGE_LAYOUT_GENERAL;
VkSubpassDescription subpass = {};
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attach;
VkRenderPassCreateInfo rpci = {};
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.attachmentCount = 1;
VkAttachmentDescription attach_desc = {};
attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM;
// Set loadOp to CLEAR
attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
rpci.pAttachments = &attach_desc;
rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
VkRenderPass rp;
vk::CreateRenderPass(m_device->device(), &rpci, NULL, &rp);
VkRenderPassBeginInfo rp_begin = {};
rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
rp_begin.pNext = NULL;
rp_begin.renderPass = renderPass();
rp_begin.framebuffer = framebuffer();
rp_begin.clearValueCount = 0; // Should be 1
TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported,
"VUID-VkRenderPassBeginInfo-clearValueCount-00902", "VUID-VkRenderPassBeginInfo-clearValueCount-00902");
vk::DestroyRenderPass(m_device->device(), rp, NULL);
}
TEST_F(VkLayerTest, RenderPassBeginSampleLocationsInvalidIndicesEXT) {
TEST_DESCRIPTION("Test that attachment indices and subpass indices specifed by sample locations structures are valid");
// Check for VK_KHR_get_physical_device_properties2
if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
ASSERT_NO_FATAL_FAILURE(InitFramework(m_errorMonitor));
if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME)) {
m_device_extension_names.push_back(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
} else {
printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
return;
}
ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR =
(PFN_vkGetPhysicalDeviceProperties2KHR)vk::GetInstanceProcAddr(instance(), "vkGetPhysicalDeviceProperties2KHR");
assert(vkGetPhysicalDeviceProperties2KHR != nullptr);
VkPhysicalDeviceSampleLocationsPropertiesEXT sample_locations_props =
LvlInitStruct<VkPhysicalDeviceSampleLocationsPropertiesEXT>();
VkPhysicalDeviceProperties2KHR prop2 = LvlInitStruct<VkPhysicalDeviceProperties2KHR>(&sample_locations_props);
vkGetPhysicalDeviceProperties2KHR(gpu(), &prop2);
if ((sample_locations_props.sampleLocationSampleCounts & VK_SAMPLE_COUNT_1_BIT) == 0) {
printf("%s VK_SAMPLE_COUNT_1_BIT sampleLocationSampleCounts is not supported.\n", kSkipPrefix);
return;
}
// Create a depth stencil image view
VkImageObj image(m_device);
image.Init(128, 128, 1, VK_FORMAT_D16_UNORM, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL);
ASSERT_TRUE(image.initialized());
VkImageView dsv;
VkImageViewCreateInfo dsvci = {};
dsvci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
dsvci.pNext = nullptr;
dsvci.image = image.handle();
dsvci.viewType = VK_IMAGE_VIEW_TYPE_2D;
dsvci.format = VK_FORMAT_D16_UNORM;
dsvci.subresourceRange.layerCount = 1;
dsvci.subresourceRange.baseMipLevel = 0;
dsvci.subresourceRange.levelCount = 1;
dsvci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
vk::CreateImageView(m_device->device(), &dsvci, NULL, &dsv);
// Create a renderPass with a single attachment that uses loadOp CLEAR