blob: 0c7c6ce321bb386c6578f98a2f8b4683147b0aca [file] [log] [blame]
/*
* Copyright (c) 2015-2025 The Khronos Group Inc.
* Copyright (c) 2015-2025 Valve Corporation
* Copyright (c) 2015-2025 LunarG, Inc.
* Copyright (c) 2015-2025 Google, Inc.
* Modifications Copyright (C) 2020-2022 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
*/
#include <gtest/gtest.h>
#include <vulkan/vulkan_core.h>
#include <cstdint>
#include <vector>
#include "utils/cast_utils.h"
#include "utils/convert_utils.h"
#include "../framework/layer_validation_tests.h"
#include "../framework/pipeline_helper.h"
#include "../framework/descriptor_helper.h"
#include "../framework/render_pass_helper.h"
class NegativeRenderPass : public VkLayerTest {
public:
void TestRenderPass2KHRCreate(const VkRenderPassCreateInfo2KHR &create_info, const std::vector<const char *> &vuids);
};
void NegativeRenderPass::TestRenderPass2KHRCreate(const VkRenderPassCreateInfo2KHR &create_info,
const std::vector<const char *> &vuids) {
for (auto vuid : vuids) {
m_errorMonitor->SetDesiredError(vuid);
}
vkt::RenderPass rp(*m_device, create_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, AttachmentIndexOutOfRange) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
// There are no attachments, but refer to attachment 0.
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL});
rp.AddColorAttachment(0);
// "... must be less than the total number of attachments ..."
CreateRenderPassTest(rp.GetCreateInfo(), true, "VUID-VkRenderPassCreateInfo-attachment-00834",
"VUID-VkRenderPassCreateInfo2-attachment-03051");
}
TEST_F(NegativeRenderPass, AttachmentReadOnlyButCleared) {
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
const bool maintenance2Supported = IsExtensionsEnabled(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
const VkFormat ds_format = FindSupportedDepthStencilFormat(Gpu());
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};
auto rpci = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, 1u, &description, 1u, &subpass, 0u, 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;
CreateRenderPassTest(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;
CreateRenderPassTest(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;
CreateRenderPassTest(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;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-pAttachments-01567",
"VUID-VkRenderPassCreateInfo2-pAttachments-02523");
}
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // reset
}
TEST_F(NegativeRenderPass, AttachmentMismatchingLayoutsColor) {
TEST_DESCRIPTION("Attachment is used simultaneously as two color attachments with different layouts.");
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL});
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL});
rp.AddColorAttachment(0);
rp.AddColorAttachment(1);
CreateRenderPassTest(rp.GetCreateInfo(), true, "VUID-VkSubpassDescription-layout-02519",
"VUID-VkSubpassDescription2-layout-02528");
}
TEST_F(NegativeRenderPass, AttachmentDescriptionFinalLayout) {
TEST_DESCRIPTION("VkAttachmentDescription's finalLayout must not be UNDEFINED or PREINITIALIZED");
AddRequiredExtensions(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME); // required for invalid enums
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
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 = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attach_ref;
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-finalLayout-00843",
"VUID-VkAttachmentDescription2-finalLayout-00843");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-finalLayout-00843",
"VUID-VkAttachmentDescription2-finalLayout-00843");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
auto depth_format = FindSupportedDepthOnlyFormat(Gpu());
auto stencil_format = FindSupportedStencilOnlyFormat(Gpu());
if (stencil_format == VK_FORMAT_UNDEFINED) {
GTEST_SKIP() << "Couldn't find a stencil only image format";
}
// Depth
{
attach_desc.format = depth_format;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-separateDepthStencilLayouts-03284",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03284");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-separateDepthStencilLayouts-03284",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03284");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-separateDepthStencilLayouts-03285",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03285");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-separateDepthStencilLayouts-03285",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03285");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Stencil
{
attach_desc.format = stencil_format;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-separateDepthStencilLayouts-03284",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03284");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-separateDepthStencilLayouts-03284",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03284");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-separateDepthStencilLayouts-03285",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03285");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-separateDepthStencilLayouts-03285",
"VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03285");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
}
}
TEST_F(NegativeRenderPass, AttachmentDescriptionFinalLayoutZeroInitialized) {
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_ZERO_INITIALIZE_DEVICE_MEMORY_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::zeroInitializeDeviceMemory);
RETURN_IF_SKIP(Init());
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_ZERO_INITIALIZED_EXT;
VkAttachmentReference attach_ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attach_ref;
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
CreateRenderPassTest(rpci, true, "VUID-VkAttachmentDescription-finalLayout-00843",
"VUID-VkAttachmentDescription2-finalLayout-00843");
}
TEST_F(NegativeRenderPass, AttachmentDescriptionFinalLayoutSeperateDS) {
TEST_DESCRIPTION("VkAttachmentDescription's finalLayout must not be UNDEFINED or PREINITIALIZED");
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::separateDepthStencilLayouts);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
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 = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attach_ref;
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-finalLayout-00843",
"VUID-VkAttachmentDescription2-finalLayout-00843");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-finalLayout-00843",
"VUID-VkAttachmentDescription2-finalLayout-00843");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
auto depth_format = FindSupportedDepthOnlyFormat(Gpu());
auto depth_stencil_format = FindSupportedDepthStencilFormat(Gpu());
auto stencil_format = FindSupportedStencilOnlyFormat(Gpu());
if (stencil_format == VK_FORMAT_UNDEFINED) {
GTEST_SKIP() << "Couldn't find a stencil only image format";
}
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03286",
"VUID-VkAttachmentDescription2-format-03286");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03286",
"VUID-VkAttachmentDescription2-format-03286");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03286",
"VUID-VkAttachmentDescription2-format-03286");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03286",
"VUID-VkAttachmentDescription2-format-03286");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03287",
"VUID-VkAttachmentDescription2-format-03287");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03287",
"VUID-VkAttachmentDescription2-format-03287");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03287",
"VUID-VkAttachmentDescription2-format-03287");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03287",
"VUID-VkAttachmentDescription2-format-03287");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
// depth
{
attach_desc.format = depth_format;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03290",
"VUID-VkAttachmentDescription2-format-03290");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03290",
"VUID-VkAttachmentDescription2-format-03290");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03291",
"VUID-VkAttachmentDescription2-format-03291");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03291",
"VUID-VkAttachmentDescription2-format-03291");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// stencil
{
attach_desc.format = stencil_format;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03292",
"VUID-VkAttachmentDescription2-format-06247");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03292",
"VUID-VkAttachmentDescription2-format-06247");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03293",
"VUID-VkAttachmentDescription2-format-06248");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03293",
"VUID-VkAttachmentDescription2-format-06248");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
}
if (rp2Supported) {
attach_desc.format = depth_stencil_format;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
VkAttachmentDescriptionStencilLayout attachment_description_stencil_layout = vku::InitStructHelper();
attachment_description_stencil_layout.stencilInitialLayout = VK_IMAGE_LAYOUT_GENERAL;
attachment_description_stencil_layout.stencilFinalLayout = VK_IMAGE_LAYOUT_GENERAL;
auto rpci2 = ConvertVkRenderPassCreateInfoToV2KHR(rpci);
rpci2.pAttachments[0].pNext = &attachment_description_stencil_layout;
VkImageLayout forbidden_layouts[] = {
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL,
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(*rpci2.ptr(), {"VUID-VkAttachmentDescriptionStencilLayout-stencilInitialLayout-03308"});
}
attachment_description_stencil_layout.stencilInitialLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
for (size_t i = 0; i < forbidden_layouts_array_size; ++i) {
attachment_description_stencil_layout.stencilFinalLayout = forbidden_layouts[i];
TestRenderPass2KHRCreate(*rpci2.ptr(), {"VUID-VkAttachmentDescriptionStencilLayout-stencilFinalLayout-03309"});
}
attachment_description_stencil_layout.stencilFinalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
TestRenderPass2KHRCreate(*rpci2.ptr(), {"VUID-VkAttachmentDescriptionStencilLayout-stencilFinalLayout-03310"});
attachment_description_stencil_layout.stencilFinalLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
TestRenderPass2KHRCreate(*rpci2.ptr(), {"VUID-VkAttachmentDescriptionStencilLayout-stencilFinalLayout-03310"});
rpci2.pAttachments[0].pNext = nullptr;
}
}
TEST_F(NegativeRenderPass, AttachmentDescriptionFinalLayoutSync2) {
TEST_DESCRIPTION("VkAttachmentDescription's finalLayout must not be UNDEFINED or PREINITIALIZED");
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME); // required for invalid enums
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
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 = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attach_ref;
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-finalLayout-00843",
"VUID-VkAttachmentDescription2-finalLayout-00843");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-finalLayout-00843",
"VUID-VkAttachmentDescription2-finalLayout-00843");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
auto depth_stencil_format = FindSupportedDepthStencilFormat(Gpu());
auto stencil_format = FindSupportedStencilOnlyFormat(Gpu());
if (stencil_format == VK_FORMAT_UNDEFINED) {
GTEST_SKIP() << "Couldn't find a stencil only image format";
}
// 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;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03280",
"VUID-VkAttachmentDescription2-format-03280");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03282",
"VUID-VkAttachmentDescription2-format-03282");
// invalid formats without synchronization2
{
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-synchronization2-06908",
"VUID-VkAttachmentDescription2-synchronization2-06908");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-synchronization2-06908",
"VUID-VkAttachmentDescription2-synchronization2-06908");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-synchronization2-06909",
"VUID-VkAttachmentDescription2-synchronization2-06909");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-synchronization2-06909",
"VUID-VkAttachmentDescription2-synchronization2-06909");
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Test invalid layouts for 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;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03281",
"VUID-VkAttachmentDescription2-format-03281");
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-03283",
"VUID-VkAttachmentDescription2-format-03283");
}
}
TEST_F(NegativeRenderPass, AttachmentsMisc) {
TEST_DESCRIPTION(
"Ensure that CreateRenderPass produces the expected validation errors when a subpass's attachments violate the valid usage "
"conditions.");
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
const VkFormat ds_format = FindSupportedDepthStencilFormat(Gpu());
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,
size32(input),
input.data(),
size32(color),
color.data(),
resolve.data(),
&depth,
size32(preserve),
preserve.data()};
auto rpci =
vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, size32(attachments), attachments.data(), 1u, &subpass, 0u, nullptr);
// Test too many color attachments
const uint32_t max_color_attachments = m_device->Physical().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("VkPhysicalDeviceLimits::maxColorAttachments is too large to practically test against -- skipping part of test.\n");
} else {
std::vector<VkAttachmentReference> too_many_colors(max_color_attachments + 1, color[0]);
VkSubpassDescription test_subpass = subpass;
test_subpass.colorAttachmentCount = size32(too_many_colors);
test_subpass.pColorAttachments = too_many_colors.data();
test_subpass.pResolveAttachments = NULL;
VkRenderPassCreateInfo test_rpci = rpci;
test_rpci.pSubpasses = &test_subpass;
CreateRenderPassTest(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
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkSubpassDescription-pColorAttachments-09430",
"VUID-VkSubpassDescription2-multisampledRenderToSingleSampled-06872");
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;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkSubpassDescription-pDepthStencilAttachment-01418",
"VUID-VkSubpassDescription2-multisampledRenderToSingleSampled-06872");
attachments[subpass.pDepthStencilAttachment->attachment].samples = attachments[subpass.pColorAttachments[0].attachment].samples;
subpass.colorAttachmentCount = size32(color);
// Test resolve attachment with UNUSED color attachment
color[0].attachment = VK_ATTACHMENT_UNUSED;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkSubpassDescription-pResolveAttachments-00847",
"VUID-VkSubpassDescription2-externalFormatResolve-09335");
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)
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkSubpassDescription-pResolveAttachments-00848",
"VUID-VkSubpassDescription2-externalFormatResolve-09338");
attachments[subpass.pColorAttachments[0].attachment].samples = VK_SAMPLE_COUNT_4_BIT;
subpass.colorAttachmentCount = size32(color);
subpass.pDepthStencilAttachment = &depth;
// Test resolve to a multi-sampled resolve attachment
attachments[subpass.pResolveAttachments[0].attachment].samples = VK_SAMPLE_COUNT_4_BIT;
CreateRenderPassTest(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;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkSubpassDescription-pResolveAttachments-00850",
"VUID-VkSubpassDescription2-externalFormatResolve-09339");
attachments[subpass.pColorAttachments[0].attachment].format = attachments[subpass.pResolveAttachments[0].attachment].format;
// Test for UNUSED preserve attachments
preserve[0] = VK_ATTACHMENT_UNUSED;
CreateRenderPassTest(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];
CreateRenderPassTest(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;
auto rpci_multipass = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, size32(attachments), attachments.data(),
size32(subpasses), subpasses.data(), 0u, nullptr);
CreateRenderPassTest(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");
CreateRenderPassTest(rpci_same, false, "VUID-VkSubpassDescription-pDepthStencilAttachment-04438", nullptr);
if (rp2Supported) {
auto create_info2 = ConvertVkRenderPassCreateInfoToV2KHR(rpci_same);
m_errorMonitor->SetUnexpectedError("VUID-VkSubpassDescription2-pColorAttachments-02898");
TestRenderPass2KHRCreate(*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");
CreateRenderPassTest(rpci_same, false, "VUID-VkSubpassDescription-pDepthStencilAttachment-04438", nullptr);
if (rp2Supported) {
auto create_info2 = ConvertVkRenderPassCreateInfoToV2KHR(rpci_same);
m_errorMonitor->SetUnexpectedError("VUID-VkSubpassDescription2-pColorAttachments-02898");
TestRenderPass2KHRCreate(*create_info2.ptr(), {"VUID-VkSubpassDescription2-pDepthStencilAttachment-04440"});
}
}
}
TEST_F(NegativeRenderPass, CustomResolve) {
AddRequiredExtensions(VK_EXT_CUSTOM_RESOLVE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::customResolve);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
const VkFormat ds_format = FindSupportedDepthStencilFormat(Gpu());
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, size32(input), input.data(), size32(color), 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},
};
auto rpci =
vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, size32(attachments), attachments.data(), 1u, &subpass, 0u, 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_CUSTOM_RESOLVE_BIT_EXT;
VkRenderPassCreateInfo test_rpci = rpci;
test_rpci.pSubpasses = &test_subpass;
CreateRenderPassTest(test_rpci, rp2Supported, "VUID-VkSubpassDescription-flags-03341",
"VUID-VkSubpassDescription2-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_CUSTOM_RESOLVE_BIT_EXT;
subpasses[1].pResolveAttachments = nullptr;
subpasses[1].flags = 0;
auto test2_rpci = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, size32(attachments), attachments.data(), 2u,
subpasses, size32(dependency), dependency.data());
CreateRenderPassTest(test2_rpci, rp2Supported, "VUID-VkSubpassDescription-flags-03343",
"VUID-VkSubpassDescription2-flags-04909");
}
}
TEST_F(NegativeRenderPass, CustomResolveNonDynamicRendering) {
AddRequiredExtensions(VK_EXT_CUSTOM_RESOLVE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::customResolve);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
VkBeginCustomResolveInfoEXT begin_resolve_info = vku::InitStructHelper();
m_errorMonitor->SetDesiredError("VUID-vkCmdBeginCustomResolveEXT-renderpass");
vk::CmdBeginCustomResolveEXT(m_command_buffer, &begin_resolve_info);
m_errorMonitor->VerifyFound();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdBeginCustomResolveEXT-commandBuffer-11517");
vk::CmdBeginCustomResolveEXT(m_command_buffer, &begin_resolve_info);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, AttachmentReferenceLayout) {
TEST_DESCRIPTION("Attachment reference uses PREINITIALIZED or UNDEFINED layouts");
AddRequiredExtensions(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
const VkFormat ds_format = FindSupportedDepthStencilFormat(Gpu());
const std::array attachments = {
VkAttachmentDescription{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},
VkAttachmentDescription{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},
};
std::array refs = {
VkAttachmentReference{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, // color
VkAttachmentReference{1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}, // depth stencil
};
const std::array subpasses = {
VkSubpassDescription{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &refs[0], nullptr, &refs[1], 0, nullptr},
};
auto rpci = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, static_cast<uint32_t>(attachments.size()), attachments.data(),
static_cast<uint32_t>(subpasses.size()), subpasses.data(), 0u, nullptr);
// Use UNDEFINED layout
refs[0].layout = VK_IMAGE_LAYOUT_UNDEFINED;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentReference-layout-03077", "VUID-VkAttachmentReference2-layout-03077");
// Use PREINITIALIZED layout
refs[0].layout = VK_IMAGE_LAYOUT_PREINITIALIZED;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentReference-layout-03077", "VUID-VkAttachmentReference2-layout-03077");
if (rp2Supported) {
auto rpci2 = ConvertVkRenderPassCreateInfoToV2KHR(rpci);
// 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_ATTACHMENT_OPTIMAL;
TestRenderPass2KHRCreate(*rpci2.ptr(), {"VUID-VkAttachmentReference2-separateDepthStencilLayouts-03313",
"VUID-VkRenderPassCreateInfo2-attachment-06244"});
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
TestRenderPass2KHRCreate(*rpci2.ptr(), {"VUID-VkAttachmentReference2-separateDepthStencilLayouts-03313",
"VUID-VkRenderPassCreateInfo2-attachment-06244"});
rpci2.pSubpasses[0].pDepthStencilAttachment->aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
TestRenderPass2KHRCreate(*rpci2.ptr(), {"VUID-VkAttachmentReference2-separateDepthStencilLayouts-03313",
"VUID-VkRenderPassCreateInfo2-attachment-06245"});
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL;
TestRenderPass2KHRCreate(*rpci2.ptr(), {"VUID-VkAttachmentReference2-separateDepthStencilLayouts-03313",
"VUID-VkRenderPassCreateInfo2-attachment-06245"});
}
// test RenderPass 1
refs[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
refs[1].layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
m_errorMonitor->SetDesiredError("VUID-VkRenderPassCreateInfo2-attachment-06244");
CreateRenderPassTest(rpci, false, "VUID-VkAttachmentReference-separateDepthStencilLayouts-03313", nullptr);
}
TEST_F(NegativeRenderPass, AttachmentReferenceLayoutSeparateDepthStencilLayoutsFeature) {
TEST_DESCRIPTION("Attachment reference uses PREINITIALIZED or UNDEFINED layouts");
AddRequiredExtensions(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::separateDepthStencilLayouts);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
const VkFormat ds_format = FindSupportedDepthStencilFormat(Gpu());
const VkFormat stencil_format = VK_FORMAT_S8_UINT;
const std::array attachments = {
VkAttachmentDescription{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},
VkAttachmentDescription{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},
VkAttachmentDescription{0, stencil_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_GENERAL}};
VkImageFormatProperties imageFormatProperties;
VkResult res;
res = vk::GetPhysicalDeviceImageFormatProperties(gpu_, attachments[0].format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0u, &imageFormatProperties);
if (res != VK_SUCCESS) {
GTEST_SKIP() << "Image format not supported";
}
res = vk::GetPhysicalDeviceImageFormatProperties(gpu_, attachments[1].format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0u, &imageFormatProperties);
if (res != VK_SUCCESS) {
GTEST_SKIP() << "Image format not supported";
}
res = vk::GetPhysicalDeviceImageFormatProperties(gpu_, attachments[2].format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0u, &imageFormatProperties);
if (res != VK_SUCCESS) {
GTEST_SKIP() << "Image format not supported";
}
std::array refs = {
VkAttachmentReference{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, // color
VkAttachmentReference{1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}, // depth stencil
};
const std::array subpasses = {
VkSubpassDescription{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &refs[0], nullptr, &refs[1], 0, nullptr},
};
auto rpci = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, static_cast<uint32_t>(attachments.size()), attachments.data(),
static_cast<uint32_t>(subpasses.size()), subpasses.data(), 0u, nullptr);
// Use UNDEFINED layout
refs[0].layout = VK_IMAGE_LAYOUT_UNDEFINED;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentReference-layout-03077", "VUID-VkAttachmentReference2-layout-03077");
// Use PREINITIALIZED layout
refs[0].layout = VK_IMAGE_LAYOUT_PREINITIALIZED;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentReference-layout-03077", "VUID-VkAttachmentReference2-layout-03077");
if (rp2Supported) {
auto rpci2 = ConvertVkRenderPassCreateInfoToV2KHR(rpci);
// 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_ATTACHMENT_OPTIMAL;
// Set a valid VkAttachmentReferenceStencilLayout since the feature bit is set
VkAttachmentReferenceStencilLayout attachment_reference_stencil_layout = vku::InitStructHelper();
attachment_reference_stencil_layout.stencilLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL;
rpci2.pSubpasses[0].pDepthStencilAttachment->pNext = &attachment_reference_stencil_layout;
// 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;
vkt::RenderPass rp1(*m_device, *rpci2.ptr());
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
vkt::RenderPass rp2(*m_device, *rpci2.ptr());
}
{
rpci2.pSubpasses[0].pDepthStencilAttachment->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
const auto original_attachment = rpci2.pSubpasses[0].pDepthStencilAttachment->attachment;
rpci2.pSubpasses[0].pDepthStencilAttachment->attachment = 2;
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
vkt::RenderPass rp1(*m_device, *rpci2.ptr());
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
vkt::RenderPass rp2(*m_device, *rpci2.ptr());
rpci2.pSubpasses[0].pDepthStencilAttachment->attachment = original_attachment;
}
{
rpci2.pSubpasses[0].pDepthStencilAttachment->aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
vkt::RenderPass rp1(*m_device, *rpci2.ptr());
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
vkt::RenderPass rp2(*m_device, *rpci2.ptr());
}
rpci2.pAttachments[1].format = ds_format; // reset
rpci2.pSubpasses[0].pDepthStencilAttachment->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // reset
std::array forbidden_layouts = {
VK_IMAGE_LAYOUT_PREINITIALIZED,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL,
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 // Would need VK_KHR_swapchain
};
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;
for (size_t i = 0; i < forbidden_layouts.size(); ++i) {
attachment_reference_stencil_layout.stencilLayout = forbidden_layouts[i];
TestRenderPass2KHRCreate(*rpci2.ptr(), {"VUID-VkAttachmentReferenceStencilLayout-stencilLayout-03318"});
}
attachment_reference_stencil_layout.stencilLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentDescriptionStencilLayout attachment_description_stencil_layout = vku::InitStructHelper();
attachment_description_stencil_layout.stencilInitialLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
attachment_description_stencil_layout.stencilFinalLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
rpci2.pAttachments[1].pNext = &attachment_description_stencil_layout;
rpci2.pAttachments[1].initialLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
rpci2.pAttachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
TestRenderPass2KHRCreate(*rpci2.ptr(), {"VUID-VkAttachmentDescription2-format-06906"});
rpci2.pAttachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
rpci2.pAttachments[1].finalLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
TestRenderPass2KHRCreate(*rpci2.ptr(), {"VUID-VkAttachmentDescription2-format-06907"});
rpci2.pAttachments[1].pNext = nullptr;
rpci2.pAttachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
rpci2.pAttachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
TestRenderPass2KHRCreate(*rpci2.ptr(), {"VUID-VkAttachmentDescription2-format-06249"});
rpci2.pAttachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
rpci2.pAttachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
TestRenderPass2KHRCreate(*rpci2.ptr(), {"VUID-VkAttachmentDescription2-format-06250"});
rpci2.pSubpasses[0].pDepthStencilAttachment->pNext = nullptr;
}
}
TEST_F(NegativeRenderPass, AttachmentReferenceSync2Layout) {
TEST_DESCRIPTION("Attachment reference uses sync2 and ATTACHMENT_OPTIMAL_KHR or READ_ONLY_OPTIMAL_KHR layouts");
SetTargetApiVersion(VK_API_VERSION_1_3);
// synchronization2 not enabled
RETURN_IF_SKIP(Init());
const VkFormat ds_format = FindSupportedDepthStencilFormat(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},
};
auto rpci = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, 2u, attach, 1u, subpasses, 0u, nullptr);
// Use READ_ONLY_OPTIMAL_KHR layout
refs[0].layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL;
{
m_errorMonitor->SetDesiredError("VUID-VkAttachmentReference-synchronization2-06910");
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription-attachment-06922");
vkt::RenderPass rp(*m_device, rpci);
m_errorMonitor->VerifyFound();
}
{
auto rpci2 = ConvertVkRenderPassCreateInfoToV2KHR(rpci);
m_errorMonitor->SetDesiredError("VUID-VkAttachmentReference2-synchronization2-06910");
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription2-attachment-06922");
vkt::RenderPass rp2_core(*m_device, *rpci2.ptr());
m_errorMonitor->VerifyFound();
}
// Use ATTACHMENT_OPTIMAL_KHR layout
refs[0].layout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, true, "VUID-VkAttachmentReference-synchronization2-06910",
"VUID-VkAttachmentReference2-synchronization2-06910");
}
TEST_F(NegativeRenderPass, MixedAttachmentSamplesAMD) {
TEST_DESCRIPTION("Verify error messages for supported and unsupported sample counts in render pass attachments.");
AddRequiredExtensions(VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
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 = vku::InitStructHelper();
rpci.attachmentCount = attachments.size();
rpci.pAttachments = attachments.data();
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
{
// creating and destroying a RenderPass1 should work;
vkt::RenderPass(*m_device, rpci);
}
// Expect an error message for invalid sample counts
attachments[0].samples = VK_SAMPLE_COUNT_4_BIT;
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkSubpassDescription-None-09431", "VUID-VkSubpassDescription2-None-09456");
}
TEST_F(NegativeRenderPass, BeginRenderArea) {
TEST_DESCRIPTION("Generate INVALID_RENDER_AREA error by beginning renderpass with extent outside of framebuffer");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_DEVICE_GROUP_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
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 = "VUID-VkRenderPassBeginInfo-pNext-02852";
CreateRenderPassBeginTest(m_command_buffer, &m_renderPassBeginInfo, rp2Supported, vuid, vuid);
m_renderPassBeginInfo.renderArea.offset.x = 1;
m_renderPassBeginInfo.renderArea.extent.width = vvl::kU32Max - 1;
CreateRenderPassBeginTest(m_command_buffer, &m_renderPassBeginInfo, rp2Supported, vuid, vuid);
m_renderPassBeginInfo.renderArea.offset.x = vvl::kI32Max;
m_renderPassBeginInfo.renderArea.extent.width = vvl::kU32Max;
CreateRenderPassBeginTest(m_command_buffer, &m_renderPassBeginInfo, rp2Supported, vuid, vuid);
m_renderPassBeginInfo.renderArea.offset.x = 0;
m_renderPassBeginInfo.renderArea.extent.width = 256;
m_renderPassBeginInfo.renderArea.offset.y = 1;
m_renderPassBeginInfo.renderArea.extent.height = vvl::kU32Max - 1;
CreateRenderPassBeginTest(m_command_buffer, &m_renderPassBeginInfo, rp2Supported, "VUID-VkRenderPassBeginInfo-pNext-02853",
"VUID-VkRenderPassBeginInfo-pNext-02853");
}
TEST_F(NegativeRenderPass, BeginWithinRenderPass) {
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
InitRenderTarget();
// Bind a BeginRenderPass within an active RenderPass
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
// Just use a dummy Renderpass
m_errorMonitor->SetDesiredError("VUID-vkCmdBeginRenderPass-renderpass");
vk::CmdBeginRenderPass(m_command_buffer, &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
m_errorMonitor->VerifyFound();
if (rp2Supported) {
auto subpassBeginInfo = vku::InitStruct<VkSubpassBeginInfo>(nullptr, VK_SUBPASS_CONTENTS_INLINE);
m_errorMonitor->SetDesiredError("VUID-vkCmdBeginRenderPass2-renderpass");
vk::CmdBeginRenderPass2KHR(m_command_buffer, &m_renderPassBeginInfo, &subpassBeginInfo);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeRenderPass, BeginIncompatibleFramebuffer) {
TEST_DESCRIPTION("Test that renderpass begin is compatible with the framebuffer renderpass ");
RETURN_IF_SKIP(Init());
// Create a depth stencil image view
vkt::Image image(*m_device, 128, 128, VK_FORMAT_D16_UNORM, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
vkt::ImageView dsv = image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT);
// 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};
auto rpci = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, 1u, &description, 1u, &subpass, 0u, nullptr);
vkt::RenderPass rp1(*m_device, rpci);
subpass.pDepthStencilAttachment = nullptr;
vkt::RenderPass rp2(*m_device, rpci);
vkt::Framebuffer fb(*m_device, rp1, 1u, &dsv.handle(), 128, 128);
auto rp_begin =
vku::InitStruct<VkRenderPassBeginInfo>(nullptr, rp2.handle(), fb.handle(), VkRect2D{{0, 0}, {128u, 128u}}, 0u, nullptr);
CreateRenderPassBeginTest(m_command_buffer, &rp_begin, false, "VUID-VkRenderPassBeginInfo-renderPass-00904", nullptr);
}
TEST_F(NegativeRenderPass, BeginLayoutsFramebufferImageUsageMismatches) {
TEST_DESCRIPTION(
"Test that renderpass initial/final layouts match up with the usage bits set for each attachment of the framebuffer");
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddOptionalExtensions(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
const bool feedback_loop_layout = IsExtensionsEnabled(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME);
const bool maintenance2Supported = IsExtensionsEnabled(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
if (feedback_loop_layout) {
VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT attachment_feedback_loop_layout_features = vku::InitStructHelper();
auto features2 = GetPhysicalDeviceFeatures2(attachment_feedback_loop_layout_features);
attachment_feedback_loop_layout_features.attachmentFeedbackLoopLayout = true;
RETURN_IF_SKIP(InitState(nullptr, &features2));
} else {
RETURN_IF_SKIP(InitState());
}
// Create an input attachment view
vkt::Image iai(*m_device, 128, 128, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
vkt::ImageView iav = iai.CreateView();
// Create an input depth attachment view
VkFormat dformat = FindSupportedDepthStencilFormat(Gpu());
vkt::Image iadi(*m_device, 128, 128, dformat, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
vkt::ImageView iadv = iadi.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
// Create a color attachment view
vkt::Image cai(*m_device, 128, 128, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView cav = cai.CreateView();
// 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};
auto rpci = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, 2u, descriptions, 1u, &subpass, 0u, nullptr);
// Create a framebuffer
VkImageView views[] = {iav, cav};
auto fbci = vku::InitStruct<VkFramebufferCreateInfo>(nullptr, 0u, VK_NULL_HANDLE, 2u, views, 128u, 128u, 1u);
VkClearValue clearValues[2];
clearValues[0].color = {{0, 0, 0, 0}};
clearValues[1].color = {{0, 0, 0, 0}};
auto rp_begin = vku::InitStruct<VkRenderPassBeginInfo>(nullptr, VK_NULL_HANDLE, VK_NULL_HANDLE, VkRect2D{{0, 0}, {128u, 128u}},
2u, clearValues);
auto test_layout_helper = [this, &rpci, &rp_begin, rp2Supported, &fbci](const char *rp1_vuid, const char *rp2_vuid) {
vkt::RenderPass rp_invalid(*m_device, rpci);
fbci.renderPass = rp_invalid;
vkt::Framebuffer fb_invalid(*m_device, fbci);
rp_begin.renderPass = rp_invalid;
rp_begin.framebuffer = fb_invalid;
CreateRenderPassBeginTest(m_command_buffer, &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");
// Change to depth views since we are changing format
descriptions[0].format = dformat;
views[0] = iadv;
// 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;
test_layout_helper("VUID-vkCmdBeginRenderPass-initialLayout-01758", "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("VUID-vkCmdBeginRenderPass-initialLayout-01758", "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");
}
if (feedback_loop_layout) {
// No VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT
vkt::Image no_fb_loop_attachment(
*m_device, 128, 128, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
auto image_view_ci = no_fb_loop_attachment.BasicViewCreatInfo();
vkt::ImageView image_view_no_fb_loop(*m_device, image_view_ci);
views[0] = image_view_no_fb_loop;
descriptions[0].format = VK_FORMAT_R8G8B8A8_UNORM;
descriptions[0].initialLayout = VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
test_layout_helper("VUID-vkCmdBeginRenderPass-initialLayout-07001", "VUID-vkCmdBeginRenderPass2-initialLayout-07003");
descriptions[0].initialLayout = VK_IMAGE_LAYOUT_GENERAL;
descriptions[0].format = dformat;
views[0] = iadv;
// No VK_IMAGE_USAGE_SAMPLED_BIT_EXT or VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
vkt::Image no_usage_sampled_attachment(
*m_device, 128, 128, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT);
image_view_ci.image = no_usage_sampled_attachment;
vkt::ImageView image_view_no_usage_sampled(*m_device, image_view_ci);
descriptions[1].initialLayout = VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
views[1] = image_view_no_usage_sampled;
test_layout_helper("VUID-vkCmdBeginRenderPass-initialLayout-07000", "VUID-vkCmdBeginRenderPass2-initialLayout-07002");
}
}
TEST_F(NegativeRenderPass, BeginLayoutsStencilBufferImageUsageMismatches) {
TEST_DESCRIPTION("Test that separate stencil initial/final layouts match up with the usage bits in framebuffer attachment");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); // Because CreateRenderPassBeginTest relies on it
AddRequiredFeature(vkt::Feature::separateDepthStencilLayouts);
RETURN_IF_SKIP(Init());
// Closure to create a render pass with just a depth/stencil image used as an input attachment (not a depth attachment!).
// This image purposely has not VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT.
// The layout of the depth and stencil aspects of this image can be defined separately, allowing to trigger different errors.
auto test = [this](VkImageLayout depth_initial_layout, VkImageLayout stencil_initial_layout, const char *rp1_vuid,
const char *rp2_vuid) {
// Create an input attachment with a depth stencil format, without VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
VkFormat depth_stencil_format = FindSupportedDepthStencilFormat(Gpu());
vkt::Image input_image(*m_device, 128, 128, depth_stencil_format, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
vkt::ImageView input_view = input_image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
VkAttachmentDescriptionStencilLayout stencil_layout = vku::InitStructHelper();
stencil_layout.stencilInitialLayout = stencil_initial_layout;
stencil_layout.stencilFinalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkAttachmentReferenceStencilLayout stencil_ref = vku::InitStructHelper();
stencil_ref.stencilLayout = VK_IMAGE_LAYOUT_GENERAL;
RenderPass2SingleSubpass rp(*this);
rp.AddAttachmentDescription(depth_stencil_format, depth_initial_layout, VK_IMAGE_LAYOUT_GENERAL);
rp.SetAttachmentDescriptionPNext(0, &stencil_layout);
rp.AddAttachmentReference(0, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
&stencil_ref);
rp.AddInputAttachment(0);
rp.CreateRenderPass();
const uint32_t fb_width = input_image.Width();
const uint32_t fb_height = input_image.Height();
vkt::Framebuffer fb(*m_device, rp, 1, &input_view.handle(), fb_width, fb_height);
// Begin render pass and trigger errors
VkRenderPassBeginInfo rp_begin = vku::InitStructHelper();
rp_begin.renderPass = rp;
rp_begin.framebuffer = fb;
rp_begin.renderArea.extent = {fb_width, fb_height};
CreateRenderPassBeginTest(m_command_buffer, &rp_begin, true, rp1_vuid, rp2_vuid);
};
test(VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, "VUID-vkCmdBeginRenderPass-initialLayout-02842",
"VUID-vkCmdBeginRenderPass2-initialLayout-02844");
test(VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, "VUID-vkCmdBeginRenderPass-stencilInitialLayout-02843",
"VUID-vkCmdBeginRenderPass2-stencilInitialLayout-02845");
}
TEST_F(NegativeRenderPass, BeginStencilFormat) {
TEST_DESCRIPTION("Test that separate stencil initial/final layouts match up with the usage bits in framebuffer attachment");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredFeature(vkt::Feature::separateDepthStencilLayouts);
RETURN_IF_SKIP(Init());
// Closure to create a render pass with just a depth/stencil image with specified format.
// The layout is set to have more or less components than what this format has, triggering an error.
auto test = [this](VkFormat depth_stencil_format, VkImageLayout depth_stencil_attachment_ref_layout, const char *vuid) {
VkImageFormatProperties imageFormatProperties;
VkResult res;
res = vk::GetPhysicalDeviceImageFormatProperties(gpu_, depth_stencil_format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0u, &imageFormatProperties);
if (res != VK_SUCCESS) {
return;
}
// Create an input attachment with a depth stencil format, without VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
vkt::Image depth_stencil_image(*m_device, 128, 128, depth_stencil_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
// Create the render pass attachment...
VkAttachmentDescription2 depth_stencil_attachment_desc = vku::InitStructHelper();
depth_stencil_attachment_desc.format = depth_stencil_format;
depth_stencil_attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT;
depth_stencil_attachment_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL; // This will trigger errors
depth_stencil_attachment_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
// ... and a reference to it...
VkAttachmentReference2 depth_stencil_attachment_ref = vku::InitStructHelper();
depth_stencil_attachment_ref.attachment = 0;
depth_stencil_attachment_ref.layout = depth_stencil_attachment_ref_layout;
depth_stencil_attachment_ref.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
// ... which is used in the one subpass.
VkSubpassDescription2 subpass_desc = vku::InitStructHelper();
subpass_desc.pDepthStencilAttachment = &depth_stencil_attachment_ref;
// Create render pass
VkRenderPassCreateInfo2 rpci = vku::InitStructHelper();
rpci.attachmentCount = 1;
rpci.pAttachments = &depth_stencil_attachment_desc;
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass_desc;
m_errorMonitor->SetDesiredError(vuid);
vkt::RenderPass rp(*m_device, rpci);
m_errorMonitor->VerifyFound();
};
test(FindSupportedDepthStencilFormat(Gpu()), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
"VUID-VkRenderPassCreateInfo2-attachment-06244");
test(FindSupportedDepthStencilFormat(Gpu()), VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL,
"VUID-VkRenderPassCreateInfo2-attachment-06245");
test(VK_FORMAT_S8_UINT, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, "VUID-VkRenderPassCreateInfo2-attachment-06246");
}
TEST_F(NegativeRenderPass, BeginClearOpMismatch) {
TEST_DESCRIPTION(
"Begin a renderPass where clearValueCount is less than the number of renderPass attachments that use "
"loadOp VK_ATTACHMENT_LOAD_OP_CLEAR.");
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
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 = vku::InitStructHelper();
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;
vkt::RenderPass rp(*m_device, rpci);
VkRenderPassBeginInfo rp_begin = vku::InitStructHelper();
rp_begin.renderPass = RenderPass();
rp_begin.framebuffer = Framebuffer();
rp_begin.renderArea.extent = {1, 1};
rp_begin.clearValueCount = 0; // Should be 1
CreateRenderPassBeginTest(m_command_buffer, &rp_begin, rp2Supported, "VUID-VkRenderPassBeginInfo-clearValueCount-00902",
"VUID-VkRenderPassBeginInfo-clearValueCount-00902");
}
TEST_F(NegativeRenderPass, BeginSampleLocationsIndicesEXT) {
TEST_DESCRIPTION("Test that attachment indices and subpass indices specifed by sample locations structures are valid");
AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceSampleLocationsPropertiesEXT sample_locations_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(sample_locations_props);
if ((sample_locations_props.sampleLocationSampleCounts & VK_SAMPLE_COUNT_1_BIT) == 0) {
GTEST_SKIP() << "VK_SAMPLE_COUNT_1_BIT sampleLocationSampleCounts is not supported";
}
// Create a depth stencil image view
vkt::Image image(*m_device, 128, 128, VK_FORMAT_D16_UNORM, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
vkt::ImageView dsv = image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT);
// 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};
auto rpci = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, 1u, &description, 1u, &subpass, 0u, nullptr);
vkt::RenderPass rp(*m_device, rpci);
vkt::Framebuffer fb(*m_device, rp, 1u, &dsv.handle(), 128, 128);
VkSampleLocationEXT sample_location = {0.5, 0.5};
auto sample_locations_info =
vku::InitStruct<VkSampleLocationsInfoEXT>(nullptr, VK_SAMPLE_COUNT_1_BIT, VkExtent2D{1u, 1u}, 1u, &sample_location);
VkAttachmentSampleLocationsEXT attachment_sample_locations = {0, sample_locations_info};
VkSubpassSampleLocationsEXT subpass_sample_locations = {0, sample_locations_info};
auto rp_sl_begin = vku::InitStruct<VkRenderPassSampleLocationsBeginInfoEXT>(nullptr, 1u, &attachment_sample_locations, 1u,
&subpass_sample_locations);
auto rp_begin =
vku::InitStruct<VkRenderPassBeginInfo>(&rp_sl_begin, rp.handle(), fb.handle(), VkRect2D{{0, 0}, {128u, 128u}}, 0u, nullptr);
attachment_sample_locations.attachmentIndex = 1;
CreateRenderPassBeginTest(m_command_buffer, &rp_begin, false, "VUID-VkAttachmentSampleLocationsEXT-attachmentIndex-01531",
nullptr);
attachment_sample_locations.attachmentIndex = 0;
subpass_sample_locations.subpassIndex = 1;
CreateRenderPassBeginTest(m_command_buffer, &rp_begin, false, "VUID-VkSubpassSampleLocationsEXT-subpassIndex-01532", nullptr);
}
TEST_F(NegativeRenderPass, DestroyWhileInUse) {
TEST_DESCRIPTION("Delete in-use renderPass.");
RETURN_IF_SKIP(Init());
InitRenderTarget();
// Create simple renderpass
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL});
rp.AddColorAttachment(0);
rp.CreateRenderPass();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp, Framebuffer());
m_command_buffer.EndRenderPass();
m_command_buffer.End();
m_default_queue->Submit(m_command_buffer);
m_errorMonitor->SetDesiredError("VUID-vkDestroyRenderPass-renderPass-00873");
vk::DestroyRenderPass(device(), rp, nullptr);
m_errorMonitor->VerifyFound();
// Wait for queue to complete so we can safely destroy rp
m_default_queue->Wait();
m_errorMonitor->SetUnexpectedError("If renderPass is not VK_NULL_HANDLE, renderPass must be a valid VkRenderPass handle");
m_errorMonitor->SetUnexpectedError("Was it created? Has it already been destroyed?");
}
TEST_F(NegativeRenderPass, FramebufferDepthStencilResolveAttachment) {
TEST_DESCRIPTION("Create a framebuffer against a render pass using depth stencil resolve, with mismatched information");
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkResolveModeFlagBits depth_resolve_mode = FindSupportedDepthResolveMode();
if (depth_resolve_mode == VK_RESOLVE_MODE_NONE) {
GTEST_SKIP() << "Could not find a supported depth resolve mode.";
}
const VkResolveModeFlagBits stencil_resolve_mode = FindSupportedStencilResolveMode();
if (stencil_resolve_mode == VK_RESOLVE_MODE_NONE) {
GTEST_SKIP() << "Could not find a supported stencil resolve mode.";
}
uint32_t attachment_width = 512;
uint32_t attachment_height = 512;
VkFormat attachment_format = FindSupportedDepthStencilFormat(Gpu());
RenderPass2SingleSubpass rp(*this);
rp.AddAttachmentDescription(attachment_format, VK_SAMPLE_COUNT_4_BIT); // Depth/stencil
rp.AddAttachmentDescription(attachment_format, VK_SAMPLE_COUNT_1_BIT); // Depth/stencil resolve
rp.AddAttachmentReference(0, VK_IMAGE_LAYOUT_GENERAL);
rp.AddAttachmentReference(1, VK_IMAGE_LAYOUT_GENERAL);
rp.AddDepthStencilAttachment(0);
rp.AddDepthStencilResolveAttachment(1, depth_resolve_mode, stencil_resolve_mode);
rp.CreateRenderPass();
// Depth resolve attachment, mismatched image usage
// Try creating Framebuffer with images, but with invalid image create usage flags
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.format = attachment_format;
image_create_info.extent = {attachment_width, attachment_height, 1};
image_create_info.mipLevels = 1;
image_create_info.arrayLayers = 1;
image_create_info.samples = VK_SAMPLE_COUNT_4_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
image_create_info.flags = 0;
vkt::Image ds_image(*m_device, image_create_info, vkt::set_layout);
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM;
image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
vkt::Image ds_resolve_image(*m_device, image_create_info, vkt::set_layout);
vkt::ImageView depth_view = ds_image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT);
vkt::ImageView resolve_view = ds_resolve_image.CreateView();
VkImageView image_views[2];
image_views[0] = depth_view;
image_views[1] = resolve_view;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-pAttachments-00880");
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-pAttachments-02634");
vkt::Framebuffer framebuffer(*m_device, rp, 2, image_views, attachment_width, attachment_height);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, FramebufferIncompatible) {
TEST_DESCRIPTION(
"Bind a secondary command buffer with a framebuffer that does not match the framebuffer for the active renderpass.");
RETURN_IF_SKIP(Init());
InitRenderTarget();
// A renderpass with one color attachment.
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL});
rp.AddColorAttachment(0);
rp.CreateRenderPass();
// A compatible framebuffer.
vkt::Image image(*m_device, 32, 32, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView view = image.CreateView();
vkt::Framebuffer fb(*m_device, rp, 1u, &view.handle());
VkCommandBufferAllocateInfo cbai = vku::InitStructHelper();
cbai.commandPool = m_command_pool;
cbai.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
cbai.commandBufferCount = 1;
vkt::CommandBuffer sec_cb(*m_device, cbai);
VkCommandBufferBeginInfo cbbi = vku::InitStructHelper();
VkCommandBufferInheritanceInfo cbii = vku::InitStructHelper();
cbii.renderPass = RenderPass();
cbii.framebuffer = fb;
cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
cbbi.pInheritanceInfo = &cbii;
sec_cb.Begin(&cbbi);
sec_cb.End();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
m_errorMonitor->SetDesiredError("VUID-vkCmdExecuteCommands-pCommandBuffers-00099");
vk::CmdExecuteCommands(m_command_buffer, 1, &sec_cb.handle());
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, FramebufferIncompatibleNoHandle) {
TEST_DESCRIPTION(
"Bind a secondary command buffer with a framebuffer that does not match the framebuffer for the active renderpass.");
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkCommandBufferAllocateInfo cbai = vku::InitStructHelper();
cbai.commandPool = m_command_pool;
cbai.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
cbai.commandBufferCount = 1;
vkt::CommandBuffer sec_cb(*m_device, cbai);
VkCommandBufferBeginInfo cbbi = vku::InitStructHelper();
VkCommandBufferInheritanceInfo cbii = vku::InitStructHelper();
cbii.renderPass = RenderPass();
cbii.framebuffer = CastFromUint64<VkFramebuffer>(0xFFFFEEEE);
cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
cbbi.pInheritanceInfo = &cbii;
m_errorMonitor->SetDesiredError("VUID-VkCommandBufferBeginInfo-flags-00055");
vk::BeginCommandBuffer(sec_cb, &cbbi);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, NullRenderPass) {
// Bind a NULL RenderPass
m_errorMonitor->SetDesiredError("VUID-vkCmdBeginRenderPass-pRenderPassBegin-parameter");
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
// Don't care about RenderPass handle b/c error should be flagged before
// that
vk::CmdBeginRenderPass(m_command_buffer, nullptr, VK_SUBPASS_CONTENTS_INLINE);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, FramebufferAttachmentPointers) {
TEST_DESCRIPTION("pAttachments points to valid objects for the Framebuffer creation");
RETURN_IF_SKIP(Init());
InitRenderTarget(2);
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_GENERAL);
rp.AddAttachmentDescription(VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_GENERAL);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL});
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL});
rp.AddColorAttachment(0);
rp.AddColorAttachment(1);
rp.CreateRenderPass();
VkFramebufferCreateInfo fb_ci = vku::InitStructHelper();
fb_ci.width = 100;
fb_ci.height = 100;
fb_ci.layers = 1;
fb_ci.renderPass = rp;
fb_ci.attachmentCount = 2;
fb_ci.pAttachments = nullptr;
VkFramebuffer framebuffer;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-flags-02778");
vk::CreateFramebuffer(device(), &fb_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
vkt::ImageView render_target_view = m_renderTargets[0]->CreateView();
VkImageView image_views[2] = {render_target_view, CastToHandle<VkImageView, uintptr_t>(0xbaadbeef)};
fb_ci.pAttachments = image_views;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-flags-02778");
vk::CreateFramebuffer(device(), &fb_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, NullFramebufferCreateInfo) {
RETURN_IF_SKIP(Init());
VkFramebuffer framebuffer;
m_errorMonitor->SetDesiredError("VUID-vkCreateFramebuffer-pCreateInfo-parameter");
vk::CreateFramebuffer(device(), nullptr, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, EndCommandBufferWithinRenderPass) {
TEST_DESCRIPTION("End a command buffer with an active render pass");
m_errorMonitor->SetDesiredError("VUID-vkEndCommandBuffer-commandBuffer-00060");
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::EndCommandBuffer(m_command_buffer);
m_errorMonitor->VerifyFound();
// End command buffer properly to avoid driver issues. This is safe -- the
// previous vk::EndCommandBuffer should not have reached the driver.
m_command_buffer.EndRenderPass();
m_command_buffer.End();
// TODO: Add test for VK_COMMAND_BUFFER_LEVEL_SECONDARY
// TODO: Add test for VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT
}
TEST_F(NegativeRenderPass, DrawWithPipelineIncompatibleWithRenderPass) {
TEST_DESCRIPTION(
"Hit RenderPass incompatible cases. Initial case is drawing with an active renderpass that's not compatible with the bound "
"pipeline state object's creation renderpass");
RETURN_IF_SKIP(Init());
InitRenderTarget();
OneOffDescriptorSet descriptor_set(m_device, {
{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
});
const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_});
// Create a renderpass that will be incompatible with default renderpass
RenderPassSingleSubpass rp(*this);
// Format incompatible with PSO RP color attach format B8G8R8A8_UNORM
rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL});
rp.AddColorAttachment(0);
rp.CreateRenderPass();
CreatePipelineHelper pipe(*this);
pipe.gp_ci_.layout = pipeline_layout;
pipe.gp_ci_.renderPass = rp;
pipe.CreateGraphicsPipeline();
VkCommandBufferInheritanceInfo cbii = vku::InitStructHelper();
cbii.renderPass = rp;
cbii.subpass = 0;
VkCommandBufferBeginInfo cbbi = vku::InitStructHelper();
cbbi.pInheritanceInfo = &cbii;
vk::BeginCommandBuffer(m_command_buffer, &cbbi);
vk::CmdBeginRenderPass(m_command_buffer, &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-renderPass-02684");
// Render triangle (the error should trigger on the attempt to draw).
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
// Finalize recording of the command buffer
m_command_buffer.EndRenderPass();
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, DrawWithPipelineIncompatibleWithRenderPassFragmentDensityMap) {
TEST_DESCRIPTION(
"Hit RenderPass incompatible case: drawing with an active renderpass that's not compatible with the bound pipeline state "
"object's creation renderpass since only the former uses a Fragment Density Map.");
AddRequiredExtensions(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
OneOffDescriptorSet descriptor_set(m_device, {
{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
});
const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_});
VkAttachmentDescription attach = {};
attach.format = VK_FORMAT_B8G8R8A8_UNORM;
attach.samples = VK_SAMPLE_COUNT_1_BIT;
attach.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attach.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
VkAttachmentReference ref = {};
ref.attachment = 0;
ref.layout = VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT;
VkRenderPassFragmentDensityMapCreateInfoEXT rpfdmi = vku::InitStructHelper();
rpfdmi.fragmentDensityMapAttachment = ref;
VkRenderPassCreateInfo rpci = vku::InitStructHelper(&rpfdmi);
rpci.attachmentCount = 1;
rpci.pAttachments = &attach;
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
// Create rp1 with FDM pNext and rp2 without FDM pNext
vkt::RenderPass rp1(*m_device, rpci);
ASSERT_TRUE(rp1.initialized());
rpci.pNext = nullptr;
rpci.attachmentCount = 1;
vkt::RenderPass rp2(*m_device, rpci);
ASSERT_TRUE(rp2.initialized());
// Create image views
vkt::Image image(*m_device, 32, 32, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView iv = image.CreateView();
// Create a framebuffer with rp1
vkt::Framebuffer fb(*m_device, rp1, 1u, &iv.handle(), 128, 128);
CreatePipelineHelper pipe(*this);
pipe.gp_ci_.layout = pipeline_layout;
pipe.gp_ci_.renderPass = rp2;
pipe.CreateGraphicsPipeline();
// Begin renderpass and bind to pipeline
VkCommandBufferInheritanceInfo cbii = vku::InitStructHelper();
cbii.renderPass = rp1;
cbii.subpass = 0;
VkCommandBufferBeginInfo cbbi = vku::InitStructHelper();
cbbi.pInheritanceInfo = &cbii;
vk::BeginCommandBuffer(m_command_buffer, &cbbi);
m_command_buffer.BeginRenderPass(rp1, fb, 128, 128);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-renderPass-02684");
// Render triangle (the error should trigger on the attempt to draw).
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
// Finalize recording of the command buffer
m_command_buffer.EndRenderPass();
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, MissingAttachment) {
TEST_DESCRIPTION("Begin render pass with missing framebuffer attachment");
RETURN_IF_SKIP(Init());
InitRenderTarget();
// Create a renderPass with a single color attachment
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL});
rp.AddColorAttachment(0);
rp.CreateRenderPass();
vkt::ImageView iv = m_renderTargets[0]->CreateView();
// Create the framebuffer then destroy the view it uses.
vkt::Framebuffer fb(*m_device, rp, 1, &iv.handle(), 100, 100);
iv.Destroy();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-framebuffer-parameter");
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp, fb, 32, 32);
// Don't call vk::CmdEndRenderPass; as the begin has been "skipped" based on the error condition
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
class RenderPassCreatePotentialFormatFeaturesTest : public NegativeRenderPass {
public:
void Test(bool const useLinearColorAttachment);
};
void RenderPassCreatePotentialFormatFeaturesTest::Test(bool const useLinearColorAttachment) {
// Check for VK_KHR_get_physical_device_properties2
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
if (useLinearColorAttachment) {
AddRequiredExtensions(VK_NV_LINEAR_COLOR_ATTACHMENT_EXTENSION_NAME);
}
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
if (useLinearColorAttachment) {
VkPhysicalDeviceLinearColorAttachmentFeaturesNV linear_color_attachment = vku::InitStructHelper();
VkPhysicalDeviceFeatures2 features2 = GetPhysicalDeviceFeatures2(linear_color_attachment);
if (useLinearColorAttachment && !linear_color_attachment.linearColorAttachment) {
GTEST_SKIP() << "Test requires linearColorAttachment";
}
RETURN_IF_SKIP(InitState(nullptr, &features2));
} else {
RETURN_IF_SKIP(InitState());
}
PFN_vkSetPhysicalDeviceFormatPropertiesEXT fpvkSetPhysicalDeviceFormatPropertiesEXT = nullptr;
PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT = nullptr;
if (!LoadDeviceProfileLayer(fpvkSetPhysicalDeviceFormatPropertiesEXT, fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)) {
GTEST_SKIP() << "Failed to load device profile layer.";
}
// Set format features from being found
const VkFormat validColorFormat = VK_FORMAT_R8G8B8A8_UNORM; // guaranteed to be valid everywhere
const VkFormat invalidColorFormat = VK_FORMAT_B8G8R8A8_UNORM;
const VkFormat depthFormat = VK_FORMAT_D16_UNORM;
VkFormatProperties formatProps;
fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(Gpu(), invalidColorFormat, &formatProps);
formatProps.linearTilingFeatures = 0;
formatProps.optimalTilingFeatures = 0;
fpvkSetPhysicalDeviceFormatPropertiesEXT(Gpu(), invalidColorFormat, formatProps);
fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(Gpu(), depthFormat, &formatProps);
formatProps.linearTilingFeatures = 0;
formatProps.optimalTilingFeatures = 0;
fpvkSetPhysicalDeviceFormatPropertiesEXT(Gpu(), depthFormat, formatProps);
VkAttachmentDescription attachments[4] = {
{0, validColorFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL},
{0, invalidColorFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL},
{0, validColorFormat, 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_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL},
{0, depthFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL}};
VkAttachmentReference references[4] = {
{0, VK_IMAGE_LAYOUT_GENERAL}, // valid color
{1, VK_IMAGE_LAYOUT_GENERAL}, // invalid color
{2, VK_IMAGE_LAYOUT_GENERAL}, // valid color multisample
{3, VK_IMAGE_LAYOUT_GENERAL} // invalid depth stencil
};
VkSubpassDescription subpass = {};
subpass.flags = 0;
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.inputAttachmentCount = 0;
subpass.pInputAttachments = nullptr;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &references[0]; // valid
subpass.pResolveAttachments = nullptr;
subpass.pDepthStencilAttachment = nullptr;
subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = nullptr;
VkSubpassDescription originalSubpass = subpass;
auto rpci = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, 4u, attachments, 1u, &subpass, 0u, nullptr);
// Color attachment
subpass.pColorAttachments = &references[1];
if (useLinearColorAttachment) {
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkSubpassDescription-linearColorAttachment-06497",
"VUID-VkSubpassDescription2-linearColorAttachment-06500");
} else {
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkSubpassDescription-pColorAttachments-02648",
"VUID-VkSubpassDescription2-pColorAttachments-02898");
}
subpass = originalSubpass;
// Input attachment
subpass.inputAttachmentCount = 1;
subpass.pInputAttachments = &references[1];
if (useLinearColorAttachment) {
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkSubpassDescription-linearColorAttachment-06496",
"VUID-VkSubpassDescription2-linearColorAttachment-06499");
} else {
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkSubpassDescription-pInputAttachments-02647",
"VUID-VkSubpassDescription2-pInputAttachments-02897");
}
subpass = originalSubpass;
// Depth Stencil attachment
subpass.pDepthStencilAttachment = &references[3];
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkSubpassDescription-pDepthStencilAttachment-02650",
"VUID-VkSubpassDescription2-pDepthStencilAttachment-02900");
subpass = originalSubpass;
// Resolve attachment
subpass.pResolveAttachments = &references[1];
subpass.pColorAttachments = &references[2]; // valid
// Can't use helper function due to need to set unexpected errors
{
VkRenderPass render_pass = VK_NULL_HANDLE;
if (useLinearColorAttachment) {
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription-linearColorAttachment-06498");
} else {
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription-pResolveAttachments-02649");
}
m_errorMonitor->SetUnexpectedError("VUID-VkSubpassDescription-pResolveAttachments-00850");
vk::CreateRenderPass(device(), &rpci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
if (rp2Supported) {
auto create_info2 = ConvertVkRenderPassCreateInfoToV2KHR(rpci);
if (useLinearColorAttachment) {
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription2-linearColorAttachment-06501");
} else {
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription2-pResolveAttachments-09343");
}
m_errorMonitor->SetUnexpectedError("VUID-VkSubpassDescription2-externalFormatResolve-09339");
vk::CreateRenderPass2KHR(device(), create_info2.ptr(), nullptr, &render_pass);
m_errorMonitor->VerifyFound();
}
}
}
TEST_F(RenderPassCreatePotentialFormatFeaturesTest, Core) {
TEST_DESCRIPTION("Validate PotentialFormatFeatures in renderpass create");
Test(false);
}
TEST_F(RenderPassCreatePotentialFormatFeaturesTest, LinearColorAttachment) {
TEST_DESCRIPTION("Validate PotentialFormatFeatures in renderpass create with linearColorAttachment");
Test(true);
}
TEST_F(NegativeRenderPass, DepthStencilResolveMode) {
TEST_DESCRIPTION("Test valid usage of the VkResolveModeFlagBits");
AddRequiredExtensions(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkFormat depthFormat = FindSupportedDepthOnlyFormat(Gpu());
VkFormat depthStencilFormat = FindSupportedDepthStencilFormat(Gpu());
VkFormat stencilFormat = FindSupportedStencilOnlyFormat(Gpu());
if (stencilFormat == VK_FORMAT_UNDEFINED) {
GTEST_SKIP() << "Couldn't find a stencil only image format";
}
const VkResolveModeFlagBits supported_depth_resolve_mode = FindSupportedDepthResolveMode();
if (supported_depth_resolve_mode == VK_RESOLVE_MODE_NONE) {
GTEST_SKIP() << "Could not find a supported depth resolve mode.";
}
const VkResolveModeFlagBits supported_stencil_resolve_mode = FindSupportedStencilResolveMode();
if (supported_stencil_resolve_mode == VK_RESOLVE_MODE_NONE) {
GTEST_SKIP() << "Could not find a supported stencil resolve mode.";
}
VkPhysicalDeviceDepthStencilResolveProperties ds_resolve_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(ds_resolve_props);
VkRenderPass renderPass;
VkAttachmentDescription2 attachmentDescriptions[2] = {};
// Depth/stencil attachment
attachmentDescriptions[0] = vku::InitStructHelper();
attachmentDescriptions[0].samples = VK_SAMPLE_COUNT_4_BIT;
attachmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
attachmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
attachmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
// Depth/stencil resolve attachment
attachmentDescriptions[1] = vku::InitStructHelper();
attachmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT;
attachmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
attachmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
attachmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
VkAttachmentReference2 depthStencilAttachmentReference = vku::InitStructHelper();
depthStencilAttachmentReference.layout = VK_IMAGE_LAYOUT_GENERAL;
depthStencilAttachmentReference.attachment = 0;
VkAttachmentReference2 depthStencilResolveAttachmentReference = vku::InitStructHelper();
depthStencilResolveAttachmentReference.layout = VK_IMAGE_LAYOUT_GENERAL;
depthStencilResolveAttachmentReference.attachment = 1;
VkSubpassDescriptionDepthStencilResolve subpassDescriptionDSR = vku::InitStructHelper();
subpassDescriptionDSR.pDepthStencilResolveAttachment = &depthStencilResolveAttachmentReference;
VkSubpassDescription2 subpassDescription = vku::InitStructHelper(&subpassDescriptionDSR);
subpassDescription.pDepthStencilAttachment = &depthStencilAttachmentReference;
VkRenderPassCreateInfo2 renderPassCreateInfo = vku::InitStructHelper();
renderPassCreateInfo.attachmentCount = 2;
renderPassCreateInfo.subpassCount = 1;
renderPassCreateInfo.pSubpasses = &subpassDescription;
renderPassCreateInfo.pAttachments = attachmentDescriptions;
// Both modes can't be none
attachmentDescriptions[0].format = depthStencilFormat;
attachmentDescriptions[1].format = depthStencilFormat;
subpassDescriptionDSR.depthResolveMode = VK_RESOLVE_MODE_NONE;
subpassDescriptionDSR.stencilResolveMode = VK_RESOLVE_MODE_NONE;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03178");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
// Stencil is used but resolve is set to none, depthResolveMode should be ignored
attachmentDescriptions[0].format = stencilFormat;
attachmentDescriptions[1].format = stencilFormat;
subpassDescriptionDSR.depthResolveMode = supported_depth_resolve_mode;
subpassDescriptionDSR.stencilResolveMode = VK_RESOLVE_MODE_NONE;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03178");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
subpassDescriptionDSR.stencilResolveMode = supported_stencil_resolve_mode;
// Invalid use of UNUSED
depthStencilAttachmentReference.attachment = VK_ATTACHMENT_UNUSED;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03177");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
depthStencilAttachmentReference.attachment = 0;
// attachmentCount == 2
depthStencilResolveAttachmentReference.attachment = 2;
m_errorMonitor->SetDesiredError("VUID-VkRenderPassCreateInfo2-pSubpasses-06473");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
depthStencilResolveAttachmentReference.attachment = 1;
// test invalid sample counts
attachmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03179");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
attachmentDescriptions[0].samples = VK_SAMPLE_COUNT_4_BIT;
attachmentDescriptions[1].samples = VK_SAMPLE_COUNT_4_BIT;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03180");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
attachmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT;
// test resolve and non-resolve formats are not same types
attachmentDescriptions[0].format = stencilFormat;
attachmentDescriptions[1].format = depthFormat;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03181");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
attachmentDescriptions[0].format = depthFormat;
attachmentDescriptions[1].format = stencilFormat;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03182");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
// test when independentResolve and independentResolve are false
attachmentDescriptions[0].format = depthStencilFormat;
attachmentDescriptions[1].format = depthStencilFormat;
if (ds_resolve_props.independentResolve == VK_FALSE) {
if (ds_resolve_props.independentResolveNone == VK_FALSE) {
subpassDescriptionDSR.depthResolveMode = VK_RESOLVE_MODE_NONE;
subpassDescriptionDSR.stencilResolveMode = supported_stencil_resolve_mode;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03185");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
} else {
if ((ds_resolve_props.supportedDepthResolveModes & VK_RESOLVE_MODE_AVERAGE_BIT) != 0 &&
(supported_stencil_resolve_mode != VK_RESOLVE_MODE_AVERAGE_BIT)) {
subpassDescriptionDSR.depthResolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
subpassDescriptionDSR.stencilResolveMode = supported_stencil_resolve_mode;
m_errorMonitor->SetDesiredError(
"VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03186");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
}
if ((ds_resolve_props.supportedStencilResolveModes & VK_RESOLVE_MODE_AVERAGE_BIT) != 0 &&
(supported_depth_resolve_mode != VK_RESOLVE_MODE_AVERAGE_BIT)) {
subpassDescriptionDSR.depthResolveMode = supported_depth_resolve_mode;
subpassDescriptionDSR.stencilResolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
m_errorMonitor->SetDesiredError(
"VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03186");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
}
}
} else {
// test using unsupported resolve mode, which currently can only be AVERAGE
// Need independentResolve to make easier to test
if ((ds_resolve_props.supportedDepthResolveModes & VK_RESOLVE_MODE_AVERAGE_BIT) == 0 &&
(supported_stencil_resolve_mode != VK_RESOLVE_MODE_AVERAGE_BIT)) {
subpassDescriptionDSR.depthResolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
subpassDescriptionDSR.stencilResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-depthResolveMode-03183");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
}
if ((ds_resolve_props.supportedStencilResolveModes & VK_RESOLVE_MODE_AVERAGE_BIT) == 0 &&
(supported_depth_resolve_mode != VK_RESOLVE_MODE_AVERAGE_BIT)) {
subpassDescriptionDSR.depthResolveMode = supported_stencil_resolve_mode;
subpassDescriptionDSR.stencilResolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-stencilResolveMode-03184");
vk::CreateRenderPass2KHR(device(), &renderPassCreateInfo, nullptr, &renderPass);
m_errorMonitor->VerifyFound();
}
}
}
TEST_F(NegativeRenderPass, RenderArea) {
TEST_DESCRIPTION("Begin render pass with render area that is not within the framebuffer.");
AddOptionalExtensions(VK_KHR_DEVICE_GROUP_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkRenderPassBeginInfo rpbinfo = vku::InitStructHelper();
rpbinfo.renderPass = m_renderPass;
rpbinfo.framebuffer = Framebuffer();
rpbinfo.renderArea.extent = {m_width, m_height};
rpbinfo.renderArea.offset = {-32, 0};
rpbinfo.clearValueCount = 1;
rpbinfo.pClearValues = m_renderPassClearValues.data();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-pNext-02850");
m_command_buffer.BeginRenderPass(rpbinfo);
m_errorMonitor->VerifyFound();
rpbinfo.renderArea.offset.x = 0;
rpbinfo.renderArea.offset.y = -128;
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-pNext-02851");
m_command_buffer.BeginRenderPass(rpbinfo);
m_errorMonitor->VerifyFound();
rpbinfo.renderArea.offset.y = 0;
rpbinfo.renderArea.extent.width = m_width + 128;
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-pNext-02852");
m_command_buffer.BeginRenderPass(rpbinfo);
m_errorMonitor->VerifyFound();
rpbinfo.renderArea.extent.width = m_width;
rpbinfo.renderArea.extent.height = m_height + 1;
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-pNext-02853");
m_command_buffer.BeginRenderPass(rpbinfo);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, DeviceGroupRenderArea) {
TEST_DESCRIPTION("Begin render pass with device group render area that is not within the framebuffer.");
AddRequiredExtensions(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DEVICE_GROUP_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkRect2D renderArea = {};
renderArea.offset = {-1, -1};
renderArea.extent = {64, 64};
VkDeviceGroupRenderPassBeginInfo device_group_render_pass_begin_info = vku::InitStructHelper();
device_group_render_pass_begin_info.deviceMask = 0x1;
device_group_render_pass_begin_info.deviceRenderAreaCount = 1;
device_group_render_pass_begin_info.pDeviceRenderAreas = &renderArea;
VkRenderPassBeginInfo rpbinfo = vku::InitStructHelper(&device_group_render_pass_begin_info);
rpbinfo.renderPass = m_renderPass;
rpbinfo.framebuffer = Framebuffer();
rpbinfo.renderArea.extent = {m_width, m_height};
rpbinfo.renderArea.offset = {-32, 0};
rpbinfo.clearValueCount = 1;
rpbinfo.pClearValues = m_renderPassClearValues.data();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkDeviceGroupRenderPassBeginInfo-offset-06166");
m_errorMonitor->SetDesiredError("VUID-VkDeviceGroupRenderPassBeginInfo-offset-06167");
m_command_buffer.BeginRenderPass(rpbinfo);
m_errorMonitor->VerifyFound();
renderArea.offset = {0, 1};
renderArea.extent = {m_width + 1, m_height};
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-pNext-02856");
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-pNext-02857");
m_command_buffer.BeginRenderPass(rpbinfo);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, RenderPassBeginNullValues) {
TEST_DESCRIPTION("Test invalid null entries for clear color");
RETURN_IF_SKIP(Init());
InitRenderTarget();
auto rpbi = m_renderPassBeginInfo;
rpbi.clearValueCount = 1;
rpbi.pClearValues = nullptr; // clearValueCount != 0, but pClearValues = null, leads to 04962
CreateRenderPassBeginTest(m_command_buffer, &rpbi, false, "VUID-VkRenderPassBeginInfo-clearValueCount-04962", nullptr);
}
TEST_F(NegativeRenderPass, DepthStencilResolveAttachmentFormat) {
TEST_DESCRIPTION("Create subpass with VkSubpassDescriptionDepthStencilResolve that has an ");
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const VkFormat ds_format = FindSupportedDepthStencilFormat(Gpu());
RenderPass2SingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_R8_UNORM, VK_SAMPLE_COUNT_1_BIT); // Depth/stencil
rp.AddAttachmentDescription(ds_format, VK_SAMPLE_COUNT_4_BIT); // Depth/stencil resolve
rp.AddAttachmentReference(0, VK_IMAGE_LAYOUT_GENERAL);
rp.AddAttachmentReference(1, VK_IMAGE_LAYOUT_GENERAL);
rp.AddDepthStencilAttachment(1);
rp.AddDepthStencilResolveAttachment(0, VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, VK_RESOLVE_MODE_SAMPLE_ZERO_BIT);
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-02651");
rp.CreateRenderPass();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, RenderPassAttachmentFormat) {
TEST_DESCRIPTION("Test creating render pass with attachment format VK_FORMAT_UNDEFINED");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkAttachmentDescription attach_desc = {};
attach_desc.format = VK_FORMAT_UNDEFINED;
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_PRESENT_SRC_KHR;
VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr};
VkRenderPassCreateInfo render_pass_ci = vku::InitStructHelper();
render_pass_ci.attachmentCount = 1;
render_pass_ci.pAttachments = &attach_desc;
render_pass_ci.subpassCount = 1;
render_pass_ci.pSubpasses = &subpass;
VkRenderPass render_pass;
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription-format-06698");
vk::CreateRenderPass(device(), &render_pass_ci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
VkAttachmentDescription2 attach_desc_2 = vku::InitStructHelper();
attach_desc_2.format = VK_FORMAT_UNDEFINED;
attach_desc_2.samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc_2.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc_2.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkSubpassDescription2 subpass_2 = vku::InitStructHelper();
VkRenderPassCreateInfo2 render_pass_ci_2 = vku::InitStructHelper();
render_pass_ci_2.attachmentCount = 1;
render_pass_ci_2.pAttachments = &attach_desc_2;
render_pass_ci_2.subpassCount = 1;
render_pass_ci_2.pSubpasses = &subpass_2;
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription2-format-09332");
vk::CreateRenderPass2(device(), &render_pass_ci_2, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, SamplingFromReadOnlyDepthStencilAttachment) {
TEST_DESCRIPTION("Use same image as depth stencil attachment in read only layer and as sampler");
RETURN_IF_SKIP(Init());
InitRenderTarget();
const uint32_t width = 32;
const uint32_t height = 32;
const VkFormat format = FindSupportedDepthStencilFormat(Gpu());
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(format, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL});
rp.AddDepthStencilAttachment(0);
rp.CreateRenderPass();
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.format = format;
image_create_info.extent = {width, height, 1};
image_create_info.mipLevels = 1;
image_create_info.arrayLayers = 1;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
image_create_info.flags = 0;
vkt::Image image(*m_device, image_create_info, vkt::set_layout);
vkt::ImageView image_view = image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT);
VkImageView image_view_handle = image_view;
vkt::Sampler sampler(*m_device, SafeSaneSamplerCreateInfo());
vkt::Framebuffer framebuffer(*m_device, rp, 1, &image_view_handle, width, height);
const char *fsSource = R"glsl(
#version 450
layout(set = 0, binding = 0) uniform sampler2D depth;
void main(){
vec4 color = texture(depth, ivec2(0));
}
)glsl";
VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT);
OneOffDescriptorSet descriptor_set(m_device,
{
{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr},
});
const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_, &descriptor_set.layout_});
descriptor_set.WriteDescriptorImageInfo(0, image_view, sampler, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
descriptor_set.UpdateDescriptorSets();
CreatePipelineHelper pipe(*this);
pipe.gp_ci_.layout = pipeline_layout;
pipe.gp_ci_.renderPass = rp;
pipe.ds_ci_ = vku::InitStruct<VkPipelineDepthStencilStateCreateInfo>();
pipe.ds_ci_.depthTestEnable = VK_TRUE;
pipe.ds_ci_.stencilTestEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp, framebuffer, width, height, 1, m_renderPassClearValues.data());
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set.set_, 0,
nullptr);
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, ColorAttachmentImageViewUsage) {
TEST_DESCRIPTION("Create image view with missing usage bits.");
AddRequiredExtensions(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
OneOffDescriptorSet descriptor_set(m_device,
{
{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr},
});
vkt::Image image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
VkImageViewUsageCreateInfo image_view_usage = vku::InitStructHelper();
image_view_usage.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
vkt::ImageView image_view = image.CreateView(VK_IMAGE_ASPECT_COLOR_BIT, &image_view_usage);
vkt::Sampler sampler(*m_device, SafeSaneSamplerCreateInfo());
VkDescriptorImageInfo image_info = {sampler, image_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
VkWriteDescriptorSet descriptor_write = vku::InitStructHelper();
descriptor_write.dstSet = descriptor_set.set_;
descriptor_write.dstBinding = 0;
descriptor_write.descriptorCount = 1;
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptor_write.pImageInfo = &image_info;
m_errorMonitor->SetDesiredError("VUID-VkWriteDescriptorSet-descriptorType-00337");
vk::UpdateDescriptorSets(device(), 1, &descriptor_write, 0, nullptr);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, StencilLoadOp) {
TEST_DESCRIPTION("Create render pass with invalid stencil load op.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const VkFormat stencil_format = FindSupportedStencilOnlyFormat(Gpu());
if (stencil_format == VK_FORMAT_UNDEFINED) {
GTEST_SKIP() << "Couldn't find a stencil only image format";
}
VkAttachmentDescription2 attach_desc = vku::InitStructHelper();
attach_desc.format = stencil_format;
attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
VkSubpassDescription2 subpass = vku::InitStructHelper();
VkRenderPassCreateInfo2 render_pass_ci = vku::InitStructHelper();
render_pass_ci.subpassCount = 1;
render_pass_ci.pSubpasses = &subpass;
render_pass_ci.attachmentCount = 1;
render_pass_ci.pAttachments = &attach_desc;
VkRenderPass render_pass;
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription2-pNext-06704");
vk::CreateRenderPass2KHR(device(), &render_pass_ci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
VkAttachmentDescriptionStencilLayout attach_desc_stencil_layout = vku::InitStructHelper();
attach_desc_stencil_layout.stencilInitialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc_stencil_layout.stencilFinalLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.pNext = &attach_desc_stencil_layout;
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription2-pNext-06705");
vk::CreateRenderPass2KHR(device(), &render_pass_ci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, ViewMask) {
TEST_DESCRIPTION("Create render pass with view mask, but multiview feature disabled.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkAttachmentDescription2 attach_desc = vku::InitStructHelper();
attach_desc.format = VK_FORMAT_R8G8B8A8_UNORM;
attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkSubpassDescription2 subpass = vku::InitStructHelper();
subpass.viewMask = 0x1;
VkRenderPassCreateInfo2 render_pass_ci = vku::InitStructHelper();
render_pass_ci.subpassCount = 1;
render_pass_ci.pSubpasses = &subpass;
render_pass_ci.attachmentCount = 1;
render_pass_ci.pAttachments = &attach_desc;
VkRenderPass render_pass;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription2-multiview-06558");
vk::CreateRenderPass2KHR(device(), &render_pass_ci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, AllViewMasksZero) {
TEST_DESCRIPTION("Test VkRenderPassMultiviewCreateInfo with all view mask elements being 0.");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
VkSubpassDescription subpass_description = {};
subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
VkSubpassDependency dependency = {};
dependency.dependencyFlags = VK_DEPENDENCY_VIEW_LOCAL_BIT;
dependency.srcSubpass = 0;
dependency.dstSubpass = VK_SUBPASS_EXTERNAL;
dependency.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
dependency.dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkRenderPassMultiviewCreateInfo render_pass_multiview_ci = vku::InitStructHelper();
VkRenderPassCreateInfo render_pass_ci = vku::InitStructHelper(&render_pass_multiview_ci);
render_pass_ci.subpassCount = 1;
render_pass_ci.pSubpasses = &subpass_description;
render_pass_ci.dependencyCount = 1;
render_pass_ci.pDependencies = &dependency;
VkRenderPass render_pass;
m_errorMonitor->SetDesiredError("VUID-VkRenderPassCreateInfo-pNext-02514");
vk::CreateRenderPass(device(), &render_pass_ci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
uint32_t correlation_mask = 0x1;
render_pass_ci.dependencyCount = 0;
render_pass_multiview_ci.correlationMaskCount = 1;
render_pass_multiview_ci.pCorrelationMasks = &correlation_mask;
m_errorMonitor->SetDesiredError("VUID-VkRenderPassCreateInfo-pNext-02515");
vk::CreateRenderPass(device(), &render_pass_ci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, AttachmentUndefinedLayout) {
TEST_DESCRIPTION("Create render pass with invalid attachment undefined layout.");
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2Supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
const VkFormat ds_format = FindSupportedDepthStencilFormat(Gpu());
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
VkAttachmentDescription attach_desc = {};
attach_desc.format = ds_format;
attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
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_GENERAL;
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
CreateRenderPassTest(rpci, rp2Supported, "VUID-VkAttachmentDescription-format-06699",
"VUID-VkAttachmentDescription2-format-06699");
attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription-format-06700");
VkRenderPass render_pass;
vk::CreateRenderPass(device(), &rpci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, MultisampledRenderToSingleSampled) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::imagelessFramebuffer);
AddRequiredFeature(vkt::Feature::multisampledRenderToSingleSampled);
AddRequiredFeature(vkt::Feature::dynamicRendering);
RETURN_IF_SKIP(Init());
VkAttachmentDescription2 attach_desc[2] = {};
attach_desc[0] = vku::InitStructHelper();
attach_desc[0].format = VK_FORMAT_B8G8R8A8_UNORM;
attach_desc[0].samples = VK_SAMPLE_COUNT_4_BIT;
attach_desc[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc[1] = vku::InitStructHelper();
attach_desc[1].format = VK_FORMAT_D32_SFLOAT;
attach_desc[1].samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkAttachmentReference2 attachment_ref = vku::InitStructHelper();
attachment_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
attachment_ref.attachment = 0;
VkAttachmentReference2 depth_ref = vku::InitStructHelper();
depth_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
depth_ref.attachment = 1;
VkMultisampledRenderToSingleSampledInfoEXT ms_render_to_ss = vku::InitStructHelper();
ms_render_to_ss.multisampledRenderToSingleSampledEnable = VK_TRUE;
ms_render_to_ss.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT;
VkSubpassDescription2 subpass = vku::InitStructHelper(&ms_render_to_ss);
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attachment_ref;
VkRenderPassCreateInfo2 rpci = vku::InitStructHelper();
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.attachmentCount = 2;
rpci.pAttachments = attach_desc;
VkRenderPass rp;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription2-pNext-06870");
vk::CreateRenderPass2(device(), &rpci, nullptr, &rp);
m_errorMonitor->VerifyFound();
attach_desc[0].samples = VK_SAMPLE_COUNT_2_BIT;
subpass.pDepthStencilAttachment = &depth_ref;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription2-pNext-06871");
vk::CreateRenderPass2(device(), &rpci, nullptr, &rp);
m_errorMonitor->VerifyFound();
VkSubpassDescriptionDepthStencilResolve depth_stencil_resolve = vku::InitStructHelper();
ms_render_to_ss.pNext = &depth_stencil_resolve;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pNext-06873");
vk::CreateRenderPass2(device(), &rpci, nullptr, &rp);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, MultisampledRenderToSingleSampled2) {
TEST_DESCRIPTION("Test VK_EXT_multisampled_render_to_single_sampled");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::imagelessFramebuffer);
AddRequiredFeature(vkt::Feature::multisampledRenderToSingleSampled);
AddRequiredFeature(vkt::Feature::dynamicRendering);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceVulkan12Properties vulkan_12_features = vku::InitStructHelper();
GetPhysicalDeviceProperties2(vulkan_12_features);
VkAttachmentDescription2 attach_desc[2] = {};
attach_desc[0] = vku::InitStructHelper();
attach_desc[0].format = VK_FORMAT_B8G8R8A8_UNORM;
attach_desc[0].samples = VK_SAMPLE_COUNT_2_BIT;
attach_desc[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc[1] = vku::InitStructHelper();
attach_desc[1].format = VK_FORMAT_D32_SFLOAT;
attach_desc[1].samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkAttachmentReference2 attachment_ref = vku::InitStructHelper();
attachment_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
attachment_ref.attachment = 0;
VkAttachmentReference2 depth_ref = vku::InitStructHelper();
depth_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
depth_ref.attachment = 1;
VkSubpassDescriptionDepthStencilResolve depth_stencil_resolve = vku::InitStructHelper();
VkMultisampledRenderToSingleSampledInfoEXT ms_render_to_ss = vku::InitStructHelper(&depth_stencil_resolve);
ms_render_to_ss.multisampledRenderToSingleSampledEnable = VK_TRUE;
ms_render_to_ss.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT;
VkSubpassDescription2 subpass = vku::InitStructHelper(&ms_render_to_ss);
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attachment_ref;
subpass.pDepthStencilAttachment = &depth_ref;
VkRenderPassCreateInfo2 rpci = vku::InitStructHelper();
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.attachmentCount = 2;
rpci.pAttachments = attach_desc;
VkResolveModeFlagBits unsupported_depth = VK_RESOLVE_MODE_NONE;
VkResolveModeFlagBits supported_depth = VK_RESOLVE_MODE_NONE;
VkResolveModeFlagBits unsupported_stencil = VK_RESOLVE_MODE_NONE;
VkResolveModeFlagBits supported_stencil = VK_RESOLVE_MODE_NONE;
for (VkResolveModeFlagBits i = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT; i <= VK_RESOLVE_MODE_MAX_BIT;
i = VkResolveModeFlagBits(i << 1)) {
if ((unsupported_depth == VK_RESOLVE_MODE_NONE) && !(i & vulkan_12_features.supportedDepthResolveModes)) {
unsupported_depth = i;
}
if ((unsupported_stencil == VK_RESOLVE_MODE_NONE) && !(i & vulkan_12_features.supportedStencilResolveModes)) {
unsupported_stencil = i;
}
if (supported_stencil == VK_RESOLVE_MODE_NONE) {
if (i & vulkan_12_features.supportedDepthResolveModes) {
supported_stencil = i;
}
} else if (supported_depth == VK_RESOLVE_MODE_NONE) {
// Want supported depth different than supported stencil
if (i & vulkan_12_features.supportedDepthResolveModes) {
supported_depth = i;
}
}
}
VkRenderPass rp;
if (unsupported_depth != VK_RESOLVE_MODE_NONE) {
depth_stencil_resolve.depthResolveMode = unsupported_depth;
// depthResolveMode unsupported
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pNext-06874");
vk::CreateRenderPass2(device(), &rpci, nullptr, &rp);
m_errorMonitor->VerifyFound();
depth_stencil_resolve.depthResolveMode = VK_RESOLVE_MODE_NONE;
}
if (unsupported_stencil != VK_RESOLVE_MODE_NONE) {
attach_desc[1].format = VK_FORMAT_S8_UINT;
depth_stencil_resolve.stencilResolveMode = unsupported_stencil;
// stencilResolveMode unsupported
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pNext-06875");
vk::CreateRenderPass2(device(), &rpci, nullptr, &rp);
m_errorMonitor->VerifyFound();
depth_stencil_resolve.stencilResolveMode = VK_RESOLVE_MODE_NONE;
attach_desc[1].format = VK_FORMAT_D32_SFLOAT;
}
if (!(vulkan_12_features.independentResolve) && !(vulkan_12_features.independentResolveNone) &&
(supported_depth != VK_RESOLVE_MODE_NONE) && (supported_stencil != VK_RESOLVE_MODE_NONE)) {
depth_stencil_resolve.depthResolveMode = supported_depth;
depth_stencil_resolve.stencilResolveMode = supported_stencil;
attach_desc[1].format = VK_FORMAT_D32_SFLOAT_S8_UINT;
// Stencil and depth resolve modes must be the same
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pNext-06876");
vk::CreateRenderPass2(device(), &rpci, nullptr, &rp);
m_errorMonitor->VerifyFound();
}
if (!(vulkan_12_features.independentResolve) && vulkan_12_features.independentResolveNone &&
(supported_depth != VK_RESOLVE_MODE_NONE) && (supported_stencil != VK_RESOLVE_MODE_NONE)) {
depth_stencil_resolve.depthResolveMode = supported_depth;
depth_stencil_resolve.stencilResolveMode = supported_stencil;
attach_desc[1].format = VK_FORMAT_D32_SFLOAT_S8_UINT;
// Stencil and depth resolve modes must be the same or one of them must be VK_RESOLVE_MODE_NONE
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescriptionDepthStencilResolve-pNext-06877");
vk::CreateRenderPass2(device(), &rpci, nullptr, &rp);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeRenderPass, MultisampledRenderToSingleSampled3) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::imagelessFramebuffer);
AddRequiredFeature(vkt::Feature::multisampledRenderToSingleSampled);
AddRequiredFeature(vkt::Feature::dynamicRendering);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceVulkan12Properties vulkan_12_features = vku::InitStructHelper();
GetPhysicalDeviceProperties2(vulkan_12_features);
InitRenderTarget();
VkAttachmentReference2 attachment_ref = vku::InitStructHelper();
attachment_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
attachment_ref.attachment = 0;
VkAttachmentReference2 depth_ref = vku::InitStructHelper();
depth_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
depth_ref.attachment = 1;
VkMultisampledRenderToSingleSampledInfoEXT ms_render_to_ss = vku::InitStructHelper();
ms_render_to_ss.multisampledRenderToSingleSampledEnable = VK_TRUE;
ms_render_to_ss.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT;
VkSubpassDescription2 subpass = vku::InitStructHelper(&ms_render_to_ss);
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attachment_ref;
VkRenderPassCreateInfo2 rpci = vku::InitStructHelper();
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.attachmentCount = 2;
VkAttachmentDescription2 attach_desc[2] = {};
attach_desc[0] = vku::InitStructHelper();
attach_desc[0].format = VK_FORMAT_B8G8R8A8_UNORM;
attach_desc[0].samples = VK_SAMPLE_COUNT_4_BIT;
attach_desc[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc[1] = vku::InitStructHelper();
attach_desc[1].format = VK_FORMAT_D32_SFLOAT;
attach_desc[1].samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
rpci.pAttachments = attach_desc;
VkRenderPass rp;
attach_desc[0].samples = VK_SAMPLE_COUNT_2_BIT;
subpass.pDepthStencilAttachment = &depth_ref;
VkSubpassDescriptionDepthStencilResolve depth_stencil_resolve = vku::InitStructHelper();
ms_render_to_ss.pNext = &depth_stencil_resolve;
ms_render_to_ss.pNext = nullptr;
subpass.pDepthStencilAttachment = nullptr;
ms_render_to_ss.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
attach_desc[0].samples = VK_SAMPLE_COUNT_1_BIT;
m_errorMonitor->SetDesiredError("VUID-VkMultisampledRenderToSingleSampledInfoEXT-rasterizationSamples-06878");
vk::CreateRenderPass2(device(), &rpci, nullptr, &rp);
m_errorMonitor->VerifyFound();
attach_desc[0].samples = VK_SAMPLE_COUNT_2_BIT;
ms_render_to_ss.pNext = nullptr;
ms_render_to_ss.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT;
subpass.pDepthStencilAttachment = nullptr;
rpci.attachmentCount = 1;
// Create a usable renderpass
vkt::RenderPass test_rp(*m_device, rpci);
VkPipelineMultisampleStateCreateInfo ms_state = vku::InitStructHelper();
ms_state.flags = 0;
ms_state.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT;
ms_state.sampleShadingEnable = VK_FALSE;
ms_state.minSampleShading = 0.0f;
ms_state.pSampleMask = nullptr;
ms_state.alphaToCoverageEnable = VK_FALSE;
ms_state.alphaToOneEnable = VK_FALSE;
CreatePipelineHelper pipe_helper(*this);
pipe_helper.gp_ci_.renderPass = test_rp;
pipe_helper.ms_ci_ = ms_state;
// ms_render_to_ss.rasterizationSamples != ms_state.rasterizationSamples
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-06854");
pipe_helper.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
// Actually create a usable pipeline
pipe_helper.ms_ci_.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT;
pipe_helper.CreateGraphicsPipeline();
VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper();
color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
ms_render_to_ss.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT;
VkRenderingInfo begin_rendering_info = vku::InitStructHelper(&ms_render_to_ss);
begin_rendering_info.layerCount = 1;
begin_rendering_info.colorAttachmentCount = 1;
begin_rendering_info.pColorAttachments = &color_attachment;
begin_rendering_info.renderArea = {{0, 0}, {1, 1}};
VkImageFormatProperties2 image_format_prop = vku::InitStructHelper();
VkPhysicalDeviceImageFormatInfo2 image_format_info = vku::InitStructHelper();
image_format_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_format_info.type = VK_IMAGE_TYPE_2D;
image_format_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_format_info.format = VK_FORMAT_B8G8R8A8_UNORM;
VkResult result = vk::GetPhysicalDeviceImageFormatProperties2(m_device->Physical(), &image_format_info, &image_format_prop);
if ((result != VK_SUCCESS) || !(image_format_prop.imageFormatProperties.sampleCounts & VK_SAMPLE_COUNT_2_BIT)) {
GTEST_SKIP() << "Cannot create an image with format VK_FORMAT_B8G8R8A8_UNORM and sample count VK_SAMPLE_COUNT_2_BIT. "
"Skipping remainder of the test";
}
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.flags = 0;
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM;
image_create_info.extent = {64, 64, 1};
image_create_info.mipLevels = 1;
image_create_info.arrayLayers = 1;
image_create_info.samples = VK_SAMPLE_COUNT_2_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
vkt::Image two_count_image(*m_device, image_create_info, vkt::set_layout);
auto image_view_ci = two_count_image.BasicViewCreatInfo();
vkt::ImageView two_count_image_view(*m_device, image_view_ci);
color_attachment.imageView = two_count_image_view;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderingInfo-imageView-06858");
m_command_buffer.BeginRendering(begin_rendering_info);
m_errorMonitor->VerifyFound();
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
vkt::Image one_count_image(*m_device, image_create_info, vkt::set_layout);
auto one_count_image_view_ci = one_count_image.BasicViewCreatInfo();
vkt::ImageView one_count_image_view(*m_device, one_count_image_view_ci);
color_attachment.imageView = one_count_image_view;
m_errorMonitor->SetDesiredError("VUID-VkRenderingAttachmentInfo-None-12256");
m_errorMonitor->SetDesiredError("VUID-VkRenderingInfo-imageView-06859");
m_command_buffer.BeginRendering(begin_rendering_info);
m_errorMonitor->VerifyFound();
color_attachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
image_create_info.flags = VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
vkt::Image good_one_count_image(*m_device, image_create_info, vkt::set_layout);
auto good_one_count_image_view_ci = good_one_count_image.BasicViewCreatInfo();
vkt::ImageView good_one_count_image_view(*m_device, good_one_count_image_view_ci);
color_attachment.imageView = good_one_count_image_view;
color_attachment.resolveImageView = good_one_count_image_view;
color_attachment.resolveImageLayout = VK_IMAGE_LAYOUT_GENERAL;
begin_rendering_info.pNext = nullptr;
color_attachment.imageView = good_one_count_image_view;
m_errorMonitor->SetDesiredError("VUID-VkRenderingAttachmentInfo-imageView-06861");
m_command_buffer.BeginRendering(begin_rendering_info);
m_errorMonitor->VerifyFound();
color_attachment.imageView = two_count_image_view;
color_attachment.resolveImageView = VK_NULL_HANDLE;
m_errorMonitor->SetDesiredError("VUID-VkRenderingAttachmentInfo-imageView-06862");
m_command_buffer.BeginRendering(begin_rendering_info);
m_errorMonitor->VerifyFound();
begin_rendering_info.pNext = &ms_render_to_ss;
color_attachment.imageView = good_one_count_image_view;
color_attachment.resolveImageView = good_one_count_image_view;
m_errorMonitor->SetDesiredError("VUID-VkRenderingAttachmentInfo-imageView-06863");
m_command_buffer.BeginRendering(begin_rendering_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, MultisampledRenderToSingleSampled4) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::imagelessFramebuffer);
AddRequiredFeature(vkt::Feature::multisampledRenderToSingleSampled);
AddRequiredFeature(vkt::Feature::dynamicRendering);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkAttachmentReference2 attachment_ref = vku::InitStructHelper();
attachment_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
attachment_ref.attachment = 0;
VkMultisampledRenderToSingleSampledInfoEXT ms_render_to_ss = vku::InitStructHelper();
ms_render_to_ss.multisampledRenderToSingleSampledEnable = VK_TRUE;
ms_render_to_ss.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT;
VkSubpassDescription2 subpass = vku::InitStructHelper(&ms_render_to_ss);
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attachment_ref;
VkAttachmentDescription2 attach_desc = vku::InitStructHelper();
attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM;
attach_desc.samples = VK_SAMPLE_COUNT_2_BIT;
attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkRenderPassCreateInfo2 rpci = vku::InitStructHelper();
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
vkt::RenderPass test_rp(*m_device, rpci);
attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
VkImageFormatProperties2 image_format_prop = vku::InitStructHelper();
VkPhysicalDeviceImageFormatInfo2 image_format_info = vku::InitStructHelper();
image_format_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_format_info.type = VK_IMAGE_TYPE_2D;
image_format_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_format_info.format = VK_FORMAT_B8G8R8A8_UNORM;
VkResult result = vk::GetPhysicalDeviceImageFormatProperties2(m_device->Physical(), &image_format_info, &image_format_prop);
if ((result != VK_SUCCESS) || !(image_format_prop.imageFormatProperties.sampleCounts & VK_SAMPLE_COUNT_2_BIT)) {
GTEST_SKIP() << "Cannot create an image with format VK_FORMAT_B8G8R8A8_UNORM and sample count VK_SAMPLE_COUNT_2_BIT. "
"Skipping remainder of the test";
}
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.flags = 0;
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM;
image_create_info.extent = {64, 64, 1};
image_create_info.mipLevels = 1;
image_create_info.arrayLayers = 1;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
vkt::Image one_count_image(*m_device, image_create_info, vkt::set_layout);
auto one_count_image_view_ci = one_count_image.BasicViewCreatInfo();
vkt::ImageView one_count_image_view(*m_device, one_count_image_view_ci);
vkt::RenderPass test_rp2(*m_device, rpci);
auto fbci =
vku::InitStruct<VkFramebufferCreateInfo>(nullptr, 0u, test_rp2.handle(), 1u, &one_count_image_view.handle(), 64u, 64u, 1u);
VkFramebuffer fb;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-samples-06881");
vk::CreateFramebuffer(device(), &fbci, nullptr, &fb);
m_errorMonitor->VerifyFound();
image_create_info.samples = VK_SAMPLE_COUNT_2_BIT;
image_create_info.flags = VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM;
VkImage bad_flag_image;
m_errorMonitor->SetDesiredError("VUID-VkImageCreateInfo-flags-06883");
vk::CreateImage(device(), &image_create_info, nullptr, &bad_flag_image);
m_errorMonitor->VerifyFound();
vkt::QueueCreateInfoArray queue_info(m_device->Physical().queue_properties_);
VkDeviceCreateInfo device_create_info = vku::InitStructHelper();
device_create_info.queueCreateInfoCount = queue_info.Size();
device_create_info.pQueueCreateInfos = queue_info.Data();
device_create_info.pEnabledFeatures = nullptr;
device_create_info.enabledExtensionCount = m_device_extension_names.size();
device_create_info.ppEnabledExtensionNames = m_device_extension_names.data();
VkDevice second_device;
ASSERT_EQ(VK_SUCCESS, vk::CreateDevice(Gpu(), &device_create_info, nullptr, &second_device));
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
bad_flag_image = VK_NULL_HANDLE;
m_errorMonitor->SetDesiredError("VUID-VkImageCreateInfo-multisampledRenderToSingleSampled-06882");
vk::CreateImage(second_device, &image_create_info, nullptr, &bad_flag_image);
m_errorMonitor->VerifyFound();
vk::DestroyDevice(second_device, nullptr);
}
TEST_F(NegativeRenderPass, MultisampledRenderToSingleSampled5) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::imagelessFramebuffer);
AddRequiredFeature(vkt::Feature::multisampledRenderToSingleSampled);
AddRequiredFeature(vkt::Feature::dynamicRendering);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkAttachmentReference2 attachment_ref = vku::InitStructHelper();
attachment_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
attachment_ref.attachment = 0;
VkMultisampledRenderToSingleSampledInfoEXT ms_render_to_ss = vku::InitStructHelper();
ms_render_to_ss.multisampledRenderToSingleSampledEnable = VK_TRUE;
ms_render_to_ss.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT;
VkSubpassDescription2 subpass = vku::InitStructHelper(&ms_render_to_ss);
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attachment_ref;
subpass.pDepthStencilAttachment = nullptr;
VkAttachmentDescription2 attach_desc = vku::InitStructHelper();
attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM;
attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkRenderPassCreateInfo2 rpci = vku::InitStructHelper();
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
VkImageFormatProperties2 image_format_prop = vku::InitStructHelper();
VkPhysicalDeviceImageFormatInfo2 image_format_info = vku::InitStructHelper();
image_format_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_format_info.type = VK_IMAGE_TYPE_2D;
image_format_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_format_info.format = VK_FORMAT_B8G8R8A8_UNORM;
VkResult result = vk::GetPhysicalDeviceImageFormatProperties2(m_device->Physical(), &image_format_info, &image_format_prop);
if ((result != VK_SUCCESS) || !(image_format_prop.imageFormatProperties.sampleCounts & VK_SAMPLE_COUNT_2_BIT)) {
GTEST_SKIP() << "Cannot create an image with format VK_FORMAT_B8G8R8A8_UNORM and sample count VK_SAMPLE_COUNT_2_BIT. "
"Skipping remainder of the test";
}
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.flags = VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.format = VK_FORMAT_B8G8R8A8_UNORM;
image_create_info.extent = {64, 64, 1};
image_create_info.mipLevels = 1;
image_create_info.arrayLayers = 1;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
vkt::Image ms_ss_image(*m_device, image_create_info, vkt::set_layout);
auto ms_ss_image_view_ci = ms_ss_image.BasicViewCreatInfo();
vkt::ImageView ms_ss_image_view(*m_device, ms_ss_image_view_ci);
// Find an image format that can't be sampled
image_format_prop = vku::InitStructHelper();
image_format_info = vku::InitStructHelper();
image_format_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_format_info.type = VK_IMAGE_TYPE_3D;
image_format_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
VkFormat unsampleable_format = VK_FORMAT_UNDEFINED;
VkSampleCountFlagBits unsampleable_count = VK_SAMPLE_COUNT_1_BIT;
for (VkFormat format = VK_FORMAT_UNDEFINED; format <= VK_FORMAT_ASTC_12x12_SRGB_BLOCK; format = VkFormat(format + 1)) {
image_format_info.format = format;
result = vk::GetPhysicalDeviceImageFormatProperties2(m_device->Physical(), &image_format_info, &image_format_prop);
if (result == VK_SUCCESS) {
if (image_format_prop.imageFormatProperties.sampleCounts != 0x7f) {
unsampleable_format = format;
for (VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; samples <= VK_SAMPLE_COUNT_64_BIT;
samples = VkSampleCountFlagBits(samples << 1)) {
if (!(image_format_prop.imageFormatProperties.sampleCounts & samples)) {
unsampleable_count = samples;
break;
}
}
break;
}
}
}
if (unsampleable_format == VK_FORMAT_UNDEFINED) {
GTEST_SKIP() << "Can't find format that has no sampling";
}
VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper();
color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkRenderingInfo begin_rendering_info = vku::InitStructHelper(&ms_render_to_ss);
begin_rendering_info.layerCount = 1;
begin_rendering_info.colorAttachmentCount = 1;
begin_rendering_info.pColorAttachments = &color_attachment;
begin_rendering_info.renderArea = {{0, 0}, {1, 1}};
color_attachment.imageView = ms_ss_image_view;
color_attachment.resolveImageView = VK_NULL_HANDLE;
color_attachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
color_attachment.resolveImageLayout = VK_IMAGE_LAYOUT_GENERAL;
image_create_info.imageType = VK_IMAGE_TYPE_3D;
image_create_info.format = unsampleable_format;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; // Can't use unsupported sample count or can't create image view
image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.flags =
VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT | VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
vkt::Image unsampleable_image(*m_device, image_create_info, vkt::set_layout);
auto unsampleable_image_view_ci = unsampleable_image.BasicViewCreatInfo();
vkt::ImageView unsampleable_image_view(*m_device, unsampleable_image_view_ci);
if (!unsampleable_image_view.initialized()) {
// This extension was written before we were more strict on the working group.
// There is a chance these VUs in this test really can't be reached.
GTEST_SKIP() << "can't create a image view with the unsampleable format";
}
ms_render_to_ss.rasterizationSamples = unsampleable_count;
color_attachment.resolveImageView = VK_NULL_HANDLE;
color_attachment.imageView = unsampleable_image_view;
m_errorMonitor->SetDesiredError("VUID-VkMultisampledRenderToSingleSampledInfoEXT-pNext-06880");
m_command_buffer.Begin();
m_command_buffer.BeginRendering(begin_rendering_info);
m_errorMonitor->VerifyFound();
attach_desc.format = unsampleable_format;
vkt::RenderPass unsampleable_rp(*m_device, rpci);
auto unsampleable_fbci = vku::InitStruct<VkFramebufferCreateInfo>(nullptr, 0u, unsampleable_rp.handle(), 1u,
&unsampleable_image_view.handle(), 64u, 64u, 1u);
VkFramebuffer unsampleable_fb;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-samples-07009");
vk::CreateFramebuffer(device(), &unsampleable_fbci, nullptr, &unsampleable_fb);
m_errorMonitor->VerifyFound();
attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM;
VkFormat framebuffer_attachment_formats[1] = {unsampleable_format};
VkFramebufferAttachmentImageInfo framebuffer_attachment_image_info = vku::InitStructHelper();
framebuffer_attachment_image_info.flags = image_create_info.flags;
framebuffer_attachment_image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
framebuffer_attachment_image_info.width = 64;
framebuffer_attachment_image_info.height = 64;
framebuffer_attachment_image_info.layerCount = 1;
framebuffer_attachment_image_info.viewFormatCount = 1;
framebuffer_attachment_image_info.pViewFormats = framebuffer_attachment_formats;
VkFramebufferAttachmentsCreateInfo framebuffer_attachment_ci = vku::InitStructHelper();
framebuffer_attachment_ci.attachmentImageInfoCount = 1;
framebuffer_attachment_ci.pAttachmentImageInfos = &framebuffer_attachment_image_info;
attach_desc.format = unsampleable_format;
vkt::RenderPass imageless_rp(*m_device, rpci);
auto imageless_fbci = vku::InitStruct<VkFramebufferCreateInfo>(nullptr, 0u, imageless_rp.handle(), 1u, nullptr, 64u, 64u, 1u);
imageless_fbci.pNext = &framebuffer_attachment_ci;
imageless_fbci.flags = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
vkt::Framebuffer imageless_fb(*m_device, imageless_fbci);
VkRenderPassAttachmentBeginInfo rp_attachment_begin_info = vku::InitStructHelper();
rp_attachment_begin_info.attachmentCount = 1;
rp_attachment_begin_info.pAttachments = &unsampleable_image_view.handle();
VkRenderPassBeginInfo rp_begin_info = vku::InitStructHelper(&rp_attachment_begin_info);
rp_begin_info.renderPass = imageless_rp;
rp_begin_info.renderArea.extent = {64, 64};
rp_begin_info.framebuffer = imageless_fb;
m_errorMonitor->SetDesiredError("VUID-VkRenderPassAttachmentBeginInfo-pAttachments-07010");
m_command_buffer.BeginRenderPass(rp_begin_info);
m_errorMonitor->VerifyFound();
attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM;
}
TEST_F(NegativeRenderPass, AttachmentDescriptionUndefinedFormat) {
TEST_DESCRIPTION("Create a render pass with an attachment description format set to VK_FORMAT_UNDEFINED");
RETURN_IF_SKIP(Init());
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_UNDEFINED, VK_IMAGE_LAYOUT_UNDEFINED);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL});
rp.AddColorAttachment(0);
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription-format-06698");
rp.CreateRenderPass();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, IncompatibleRenderPass) {
TEST_DESCRIPTION("Validate if attachments in render pass and descriptor set use the same image subresources");
RETURN_IF_SKIP(Init());
const uint32_t width = 32;
const uint32_t height = 32;
const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
VkAttachmentReference attach_ref = {};
attach_ref.attachment = 0;
attach_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attach_ref;
VkAttachmentDescription attach_desc = {};
attach_desc.format = format;
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_GENERAL;
VkSubpassDependency dependency = {0,
0,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_DEPENDENCY_BY_REGION_BIT};
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
rpci.dependencyCount = 1;
rpci.pDependencies = &dependency;
vkt::RenderPass render_pass1(*m_device, rpci);
rpci.dependencyCount = 0;
vkt::RenderPass render_pass2(*m_device, rpci);
rpci.dependencyCount = 1;
dependency.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
dependency.srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
vkt::RenderPass render_pass3(*m_device, rpci);
vkt::Image image(*m_device, width, height, format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView imageView = image.CreateView();
vkt::Framebuffer framebuffer(*m_device, render_pass1, 1, &imageView.handle(), width, height);
VkClearValue clear_values[2] = {};
clear_values[0].color = {{0, 0, 0, 0}};
clear_values[1].color = {{0, 0, 0, 0}};
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-renderPass-00904");
m_command_buffer.BeginRenderPass(render_pass2, framebuffer, width, height, 2, clear_values);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-renderPass-00904");
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-renderPass-00904");
m_command_buffer.BeginRenderPass(render_pass3, framebuffer, width, height, 2, clear_values);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, IncompatibleRenderPass2) {
TEST_DESCRIPTION("Validate if attachments in render pass and descriptor set use the same image subresources");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredFeature(vkt::Feature::multiview);
RETURN_IF_SKIP(Init());
const uint32_t width = 32;
const uint32_t height = 32;
const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
VkAttachmentReference2 attach_ref = vku::InitStructHelper();
attach_ref.attachment = 0;
attach_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
VkSubpassDescription2 subpass = vku::InitStructHelper();
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attach_ref;
subpass.viewMask = 0x1;
VkAttachmentDescription2 attach_desc = vku::InitStructHelper();
attach_desc.format = format;
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_GENERAL;
VkSubpassDependency2 dependency = {VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
nullptr,
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};
uint32_t correlated_view_mask = 0x1;
VkRenderPassCreateInfo2 rpci = vku::InitStructHelper();
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
rpci.dependencyCount = 1;
rpci.pDependencies = &dependency;
rpci.correlatedViewMaskCount = 1;
rpci.pCorrelatedViewMasks = &correlated_view_mask;
vkt::RenderPass render_pass1(*m_device, rpci);
rpci.correlatedViewMaskCount = 0;
vkt::RenderPass render_pass2(*m_device, rpci);
rpci.correlatedViewMaskCount = 1;
correlated_view_mask = 0x2;
vkt::RenderPass render_pass3(*m_device, rpci);
vkt::Image image(*m_device, width, height, format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView imageView = image.CreateView();
vkt::Framebuffer framebuffer(*m_device, render_pass1, 1, &imageView.handle(), width, height);
VkClearValue clear_values[2] = {};
clear_values[0].color = {{0, 0, 0, 0}};
clear_values[1].color = {{0, 0, 0, 0}};
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-renderPass-00904");
m_command_buffer.BeginRenderPass(render_pass2, framebuffer, width, height, 2, clear_values);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-renderPass-00904");
m_command_buffer.BeginRenderPass(render_pass3, framebuffer, width, height, 2, clear_values);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, IncompatibleRenderPassSubpassFlags) {
TEST_DESCRIPTION("Two renderpasses with different VkSubpassDescriptionFlagBits");
AddRequiredExtensions(VK_EXT_LEGACY_DITHERING_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::legacyDithering);
RETURN_IF_SKIP(Init());
VkAttachmentReference attach_ref = {};
attach_ref.attachment = 0;
attach_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attach_ref;
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_GENERAL;
VkSubpassDependency dependency = {0,
0,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_DEPENDENCY_BY_REGION_BIT};
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
rpci.dependencyCount = 1;
rpci.pDependencies = &dependency;
vkt::RenderPass render_pass1(*m_device, rpci);
subpass.flags = VK_SUBPASS_DESCRIPTION_ENABLE_LEGACY_DITHERING_BIT_EXT;
vkt::RenderPass render_pass2(*m_device, rpci);
vkt::Image image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView imageView = image.CreateView();
vkt::Framebuffer framebuffer(*m_device, render_pass1, 1, &imageView.handle());
VkClearValue clear_values[2] = {};
clear_values[0].color = {{0, 0, 0, 0}};
clear_values[1].color = {{0, 0, 0, 0}};
CreatePipelineHelper pipe(*this);
pipe.gp_ci_.renderPass = render_pass2;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-renderPass-00904");
m_command_buffer.BeginRenderPass(render_pass2, framebuffer, 32, 32, 2, clear_values);
m_errorMonitor->VerifyFound();
m_command_buffer.BeginRenderPass(render_pass1, framebuffer, 32, 32, 2, clear_values);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-renderPass-02684");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdEndRenderPass(m_command_buffer);
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, SubpassAttachmentImageLayout) {
TEST_DESCRIPTION("Invalid attachment reference layout");
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2_supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
std::array<VkAttachmentDescription, 3> attachments = {{
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL},
// This attachment is used as a color attachment when using the above one as a resolve attachment
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_2_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL},
// Depth stencil attachment
{0, FindSupportedDepthStencilFormat(m_device->Physical()), VK_SAMPLE_COUNT_2_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL},
}};
VkSubpassDescription subpass{};
auto reset_subpass = [&]() {
subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
nullptr,
0,
static_cast<uint32_t>(attachments.size()),
attachments.data(),
1,
&subpass,
0,
nullptr};
VkAttachmentReference ref{};
ref.attachment = 0;
ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
subpass.inputAttachmentCount = 1;
subpass.pInputAttachments = &ref;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06912",
"VUID-VkSubpassDescription2-attachment-06912");
ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06912",
"VUID-VkSubpassDescription2-attachment-06912");
reset_subpass();
ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &ref;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06913",
"VUID-VkSubpassDescription2-attachment-06913");
ref.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06913",
"VUID-VkSubpassDescription2-attachment-06913");
reset_subpass();
{
VkAttachmentReference color_ref = {1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_ref;
ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
subpass.pResolveAttachments = &ref;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06914",
"VUID-VkSubpassDescription2-attachment-06914");
ref.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06914",
"VUID-VkSubpassDescription2-attachment-06914");
}
reset_subpass();
ref.attachment = 2;
ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
subpass.pDepthStencilAttachment = &ref;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06915",
"VUID-VkSubpassDescription2-attachment-06915");
ref.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06915",
"VUID-VkSubpassDescription2-attachment-06915");
}
TEST_F(NegativeRenderPass, SubpassAttachmentImageLayoutMaintenance2) {
TEST_DESCRIPTION("Invalid attachment reference layout, Maintenance2 enabled");
AddRequiredExtensions(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const bool rp2_supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
constexpr std::array<VkAttachmentDescription, 2> attachments = {{
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL},
// This attachment is used as a color attachment when using the above one as a resolve attachment
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_2_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL},
}};
VkSubpassDescription subpass{};
auto reset_subpass = [&]() {
subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
nullptr,
0,
static_cast<uint32_t>(attachments.size()),
attachments.data(),
1,
&subpass,
0,
nullptr};
VkAttachmentReference ref{};
ref.attachment = 0;
ref.layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &ref;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06916",
"VUID-VkSubpassDescription2-attachment-06916");
ref.layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06916",
"VUID-VkSubpassDescription2-attachment-06916");
reset_subpass();
{
VkAttachmentReference color_ref = {1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_ref;
ref.layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
subpass.pResolveAttachments = &ref;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06917",
"VUID-VkSubpassDescription2-attachment-06917");
ref.layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06917",
"VUID-VkSubpassDescription2-attachment-06917");
}
}
TEST_F(NegativeRenderPass, SubpassAttachmentImageLayoutSynchronization2) {
TEST_DESCRIPTION("Invalid attachment reference layout, Synchronization2 enabled");
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
RETURN_IF_SKIP(Init());
const bool rp2_supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
constexpr std::array<VkAttachmentDescription, 2> attachments = {{
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL},
// This attachment is used as a color attachment when using the above one as a resolve attachment
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_2_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL},
}};
VkSubpassDescription subpass{};
auto reset_subpass = [&]() {
subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
nullptr,
0,
static_cast<uint32_t>(attachments.size()),
attachments.data(),
1,
&subpass,
0,
nullptr};
VkAttachmentReference ref{};
ref.attachment = 0;
ref.layout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL;
subpass.inputAttachmentCount = 1;
subpass.pInputAttachments = &ref;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06921",
"VUID-VkSubpassDescription2-attachment-06921");
reset_subpass();
ref.layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &ref;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06922",
"VUID-VkSubpassDescription2-attachment-06922");
reset_subpass();
{
VkAttachmentReference color_ref = {1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_ref;
ref.layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL;
subpass.pResolveAttachments = &ref;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06923",
"VUID-VkSubpassDescription2-attachment-06923");
}
}
TEST_F(NegativeRenderPass, SubpassAttachmentImageLayoutSeparateDepthStencil) {
TEST_DESCRIPTION("Invalid attachment reference layout, separate depth stencil enabled");
AddRequiredExtensions(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::separateDepthStencilLayouts);
RETURN_IF_SKIP(Init());
const bool rp2_supported = IsExtensionsEnabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
std::array<VkAttachmentDescription, 3> attachments = {{
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL},
// This attachment is used as a color attachment when using the above one as a resolve attachment
{0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_2_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL},
// Depth stencil attachment
{0, FindSupportedDepthStencilFormat(m_device->Physical()), VK_SAMPLE_COUNT_2_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL},
}};
VkSubpassDescription subpass{};
auto reset_subpass = [&]() {
subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
nullptr,
0,
static_cast<uint32_t>(attachments.size()),
attachments.data(),
1,
&subpass,
0,
nullptr};
VkAttachmentReference ref{};
ref.attachment = 0;
ref.layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
subpass.inputAttachmentCount = 1;
subpass.pInputAttachments = &ref;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06918",
"VUID-VkSubpassDescription2-attachment-06918");
ref.layout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06918",
"VUID-VkSubpassDescription2-attachment-06918");
reset_subpass();
ref.layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &ref;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06919",
"VUID-VkSubpassDescription2-attachment-06919");
ref.layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06919",
"VUID-VkSubpassDescription2-attachment-06919");
ref.layout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06919",
"VUID-VkSubpassDescription2-attachment-06919");
ref.layout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06919",
"VUID-VkSubpassDescription2-attachment-06919");
reset_subpass();
{
VkAttachmentReference color_ref = {1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_ref;
ref.layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
subpass.pResolveAttachments = &ref;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06920",
"VUID-VkSubpassDescription2-attachment-06920");
ref.layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06920",
"VUID-VkSubpassDescription2-attachment-06920");
ref.layout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06920",
"VUID-VkSubpassDescription2-attachment-06920");
ref.layout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL;
CreateRenderPassTest(rpci, rp2_supported, "VUID-VkSubpassDescription-attachment-06920",
"VUID-VkSubpassDescription2-attachment-06920");
}
auto depth_stencil_attachment = vku::InitStruct<VkAttachmentDescription2>(
nullptr, static_cast<VkAttachmentDescriptionFlags>(0), VK_FORMAT_S8_UINT, VK_SAMPLE_COUNT_2_BIT,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
VkImageFormatProperties imageFormatProperties;
VkResult res;
res =
vk::GetPhysicalDeviceImageFormatProperties(gpu_, depth_stencil_attachment.format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0u, &imageFormatProperties);
if (rp2_supported && res == VK_SUCCESS) {
VkRenderPassCreateInfo2 rpci2 = vku::InitStructHelper();
rpci2.attachmentCount = 1;
rpci2.pAttachments = &depth_stencil_attachment;
VkAttachmentReferenceStencilLayout stencil_ref = vku::InitStructHelper();
stencil_ref.stencilLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference2 depth_stencil_ref = vku::InitStructHelper(&stencil_ref);
depth_stencil_ref.attachment = 0;
VkSubpassDescription2 subpass2 = vku::InitStructHelper();
subpass2.pDepthStencilAttachment = &depth_stencil_ref;
rpci2.subpassCount = 1;
rpci2.pSubpasses = &subpass2;
{
depth_stencil_ref.layout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription2-attachment-06251");
vkt::RenderPass rp2(*m_device, rpci2);
m_errorMonitor->VerifyFound();
}
{
depth_stencil_ref.layout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription2-attachment-06251");
vkt::RenderPass rp2(*m_device, rpci2);
m_errorMonitor->VerifyFound();
}
}
}
TEST_F(NegativeRenderPass, BeginInfoWithoutRenderPass) {
TEST_DESCRIPTION("call VkRenderPassBeginInfo with invalid renderpass");
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-renderPass-parameter");
m_renderPassBeginInfo.renderPass = CastFromUint64<VkRenderPass>(0xFFFFEEEE);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("UNASSIGNED-GeneralParameterError-RequiredHandle");
m_renderPassBeginInfo.renderPass = VK_NULL_HANDLE;
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, BeginInfoWithoutFramebuffer) {
TEST_DESCRIPTION("call VkRenderPassBeginInfo with invalid framebuffer");
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-framebuffer-parameter");
m_renderPassBeginInfo.framebuffer = CastFromUint64<VkFramebuffer>(0xFFFFEEEE);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, EndWithoutRenderPass) {
TEST_DESCRIPTION("call vkCmdEndRenderPass never starting a renderpass");
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdEndRenderPass-renderpass");
m_command_buffer.EndRenderPass();
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, RenderPassBegin) {
TEST_DESCRIPTION("have an invalid pRenderPassBegin");
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBeginRenderPass-pRenderPassBegin-parameter");
vk::CmdBeginRenderPass(m_command_buffer, nullptr, VK_SUBPASS_CONTENTS_INLINE);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, IncompatibleFramebuffer) {
TEST_DESCRIPTION("Incompatible framebuffer in command buffer inheritance info");
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
VkRenderPassCreateInfo render_pass_ci = vku::InitStructHelper();
render_pass_ci.subpassCount = 1u;
render_pass_ci.pSubpasses = &subpass;
vkt::RenderPass render_pass(*m_device, render_pass_ci);
vkt::Framebuffer framebuffer(*m_device, render_pass, 0, nullptr);
VkCommandBufferInheritanceInfo inheritance_info = vku::InitStructHelper();
inheritance_info.renderPass = m_renderPass;
inheritance_info.subpass = 0u;
inheritance_info.framebuffer = framebuffer;
VkCommandBufferBeginInfo cmd_buffer_begin_info = vku::InitStructHelper();
cmd_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
cmd_buffer_begin_info.pInheritanceInfo = &inheritance_info;
vkt::CommandBuffer secondary_cmd_buffer(*m_device, m_command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
m_errorMonitor->SetDesiredError("VUID-VkCommandBufferBeginInfo-flags-00055");
vk::BeginCommandBuffer(secondary_cmd_buffer, &cmd_buffer_begin_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, ZeroRenderArea) {
TEST_DESCRIPTION("renderArea set to zero");
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-None-08996");
m_renderPassBeginInfo.renderArea.extent = {0, 64};
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-None-08997");
m_renderPassBeginInfo.renderArea.extent = {64, 0};
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, InvalidAttachmentDescriptionDSLayout) {
TEST_DESCRIPTION("Invalid final layout for ds attachment");
AddRequiredExtensions(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::separateDepthStencilLayouts);
RETURN_IF_SKIP(Init());
const VkFormat ds_format = FindSupportedDepthStencilFormat(Gpu());
VkAttachmentDescription description = {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_DEPTH_ATTACHMENT_OPTIMAL};
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};
auto rpci = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, 1u, &description, 1u, &subpass, 0u, nullptr);
VkRenderPass render_pass;
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription-format-06243");
vk::CreateRenderPass(device(), &rpci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
description.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription-format-06242");
vk::CreateRenderPass(device(), &rpci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, InvalidAttachmentDescriptionColorLayout) {
TEST_DESCRIPTION("Invalid final layout for color attachment");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkAttachmentDescription description = {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_GENERAL,
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL};
VkAttachmentReference color_ref = {0, VK_IMAGE_LAYOUT_GENERAL};
VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1u, &color_ref, nullptr, nullptr, 0, nullptr};
auto rpci = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, 1u, &description, 1u, &subpass, 0u, nullptr);
VkRenderPass render_pass;
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription-format-06488");
vk::CreateRenderPass(device(), &rpci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
description.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription-format-06487");
vk::CreateRenderPass(device(), &rpci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, InvalidFramebufferAttachmentImageUsage) {
TEST_DESCRIPTION("Use image at framebuffer attachment without VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT");
RETURN_IF_SKIP(Init());
vkt::Image image(*m_device, m_width, m_height, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_STORAGE_BIT);
vkt::ImageView image_view = image.CreateView();
VkAttachmentDescription description = {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_GENERAL,
VK_IMAGE_LAYOUT_GENERAL};
VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_GENERAL};
VkSubpassDescription subpass = {
0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, &ref, 1, &ref, nullptr, nullptr, 0, nullptr,
};
VkRenderPassCreateInfo rp_ci =
vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, 1u, &description, 1u, &subpass, 0u, nullptr);
vkt::RenderPass render_pass(*m_device, rp_ci);
subpass.colorAttachmentCount = 0u;
subpass.inputAttachmentCount = 1u;
vkt::RenderPass input_attachment_render_pass(*m_device, rp_ci);
VkFramebufferCreateInfo framebuffer_ci = vku::InitStructHelper();
framebuffer_ci.renderPass = render_pass;
framebuffer_ci.attachmentCount = 1u;
framebuffer_ci.pAttachments = &image_view.handle();
framebuffer_ci.width = m_width;
framebuffer_ci.height = m_height;
framebuffer_ci.layers = 1u;
VkFramebuffer framebuffer;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-pAttachments-00877");
vk::CreateFramebuffer(*m_device, &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
framebuffer_ci.renderPass = input_attachment_render_pass;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-pAttachments-00879");
vk::CreateFramebuffer(*m_device, &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, ViewMaskWithoutFeature) {
TEST_DESCRIPTION("Create render pass using view masks with multiview disabled");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
VkAttachmentReference attachment_reference = {};
attachment_reference.attachment = 0u;
attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass_description = {};
subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass_description.colorAttachmentCount = 1u;
subpass_description.pColorAttachments = &attachment_reference;
VkAttachmentDescription attachment_description = {};
attachment_description.format = VK_FORMAT_R8G8B8A8_UNORM;
attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment_description.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachment_description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
uint32_t view_mask = 0x1;
VkRenderPassMultiviewCreateInfo render_pass_multiview_ci = vku::InitStructHelper();
render_pass_multiview_ci.subpassCount = 1u;
render_pass_multiview_ci.pViewMasks = &view_mask;
VkRenderPassCreateInfo render_pass_ci = vku::InitStructHelper(&render_pass_multiview_ci);
render_pass_ci.attachmentCount = 1u;
render_pass_ci.pAttachments = &attachment_description;
render_pass_ci.subpassCount = 1u;
render_pass_ci.pSubpasses = &subpass_description;
VkRenderPass render_pass;
m_errorMonitor->SetDesiredError("VUID-VkRenderPassMultiviewCreateInfo-multiview-06555");
vk::CreateRenderPass(*m_device, &render_pass_ci, nullptr, &render_pass);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, AttachmentLayout) {
TEST_DESCRIPTION("Test attachment descriptions with layouts other than undefined");
RETURN_IF_SKIP(Init());
vkt::Image image(*m_device, 32u, 32u, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView image_view = image.CreateView();
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL});
rp.AddColorAttachment(0);
rp.CreateRenderPass();
vkt::Framebuffer framebuffer(*m_device, rp, 1, &image_view.handle());
VkClearValue clear_value;
clear_value.color = {{0, 0, 0, 0}};
VkImageMemoryBarrier ImageMemoryBarrier = vku::InitStructHelper();
ImageMemoryBarrier.srcAccessMask = VK_ACCESS_NONE;
ImageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
ImageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
ImageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
ImageMemoryBarrier.image = image;
ImageMemoryBarrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u};
m_command_buffer.Begin();
vk::CmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
0u, nullptr, 0u, nullptr, 1u, &ImageMemoryBarrier);
m_errorMonitor->SetDesiredError("VUID-vkCmdBeginRenderPass-initialLayout-00900");
m_command_buffer.BeginRenderPass(rp, framebuffer, 32, 32, 1, &clear_value);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, ImageSubresourceOverlapBetweenCurrentRenderPassAndDescriptorSets) {
TEST_DESCRIPTION("Validate if attachments in render pass and descriptor set use the same image subresources");
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_errorMonitor->SetDesiredError("UNASSIGNED-CoreValidation-DrawState-InvalidRenderpass");
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-renderPass-00904");
const uint32_t width = 16;
const uint32_t height = 16;
const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
VkAttachmentReference attach_ref = {};
attach_ref.attachment = 0;
attach_ref.layout = VK_IMAGE_LAYOUT_GENERAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attach_ref;
VkAttachmentDescription attach_desc = {};
attach_desc.format = format;
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_GENERAL;
VkAttachmentDescription attach_desc2[] = {attach_desc, attach_desc};
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.subpassCount = 1;
rpci.pSubpasses = &subpass;
rpci.attachmentCount = 2;
rpci.pAttachments = attach_desc2;
vkt::RenderPass render_pass(*m_device, rpci);
VkClearValue clear_values[2] = {m_renderPassClearValues[0], m_renderPassClearValues[0]};
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(render_pass, Framebuffer(), width, height, 2, clear_values);
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, BeginRenderPassWithRenderPassStriped) {
TEST_DESCRIPTION("Various tests to validate begin renderpass begininfo with VK_ARM_render_pass_striped.");
AddRequiredExtensions(VK_ARM_RENDER_PASS_STRIPED_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::renderPassStriped);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceRenderPassStripedPropertiesARM rp_striped_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(rp_striped_props);
const uint32_t stripe_width = rp_striped_props.renderPassStripeGranularity.width;
const uint32_t stripe_height = rp_striped_props.renderPassStripeGranularity.height;
uint32_t stripe_count = rp_striped_props.maxRenderPassStripes + 1;
std::vector<VkRenderPassStripeInfoARM> stripe_infos(rp_striped_props.maxRenderPassStripes + 1);
for (uint32_t i = 0; i < stripe_count; ++i) {
stripe_infos[i] = vku::InitStructHelper();
stripe_infos[i].stripeArea.offset.x = stripe_width * i;
stripe_infos[i].stripeArea.offset.y = 0;
stripe_infos[i].stripeArea.extent = {stripe_width, stripe_height};
}
VkRenderPassStripeBeginInfoARM rp_stripe_info = vku::InitStructHelper();
rp_stripe_info.stripeInfoCount = stripe_count;
rp_stripe_info.pStripeInfos = stripe_infos.data();
m_renderPassBeginInfo.pNext = &rp_stripe_info;
m_renderPassBeginInfo.renderArea = {{0, 0}, {stripe_width * stripe_count, stripe_height}};
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeBeginInfoARM-stripeInfoCount-09450");
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
stripe_count = 8;
stripe_infos.resize(stripe_count);
rp_stripe_info.pStripeInfos = stripe_infos.data();
rp_stripe_info.stripeInfoCount = stripe_count;
m_renderPassBeginInfo.renderArea.extent = {stripe_width * stripe_count, stripe_height};
for (uint32_t i = 0; i < stripe_count; ++i) {
stripe_infos[i].stripeArea.offset.x = i > 1 && i <= 4 ? (stripe_width * (i - 1) / 2) : stripe_width * i;
stripe_infos[i].stripeArea.offset.y = 0;
stripe_infos[i].stripeArea.extent = {stripe_width, stripe_height};
}
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeInfoARM-stripeArea-09452");
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeInfoARM-stripeArea-09452");
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeBeginInfoARM-stripeArea-09451");
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
const uint32_t half_stripe_width = stripe_width / 2;
for (uint32_t i = 0; i < stripe_count; ++i) {
stripe_infos[i].stripeArea.offset.x = (i == 1 ? half_stripe_width : stripe_width) * i;
stripe_infos[i].stripeArea.offset.y = 0;
stripe_infos[i].stripeArea.extent.width = i == 2 ? half_stripe_width : stripe_width;
stripe_infos[i].stripeArea.extent.height = stripe_height;
}
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeBeginInfoARM-stripeArea-09451");
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeInfoARM-stripeArea-09452");
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeInfoARM-stripeArea-09453");
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
const uint32_t non_align_stripe_width = stripe_width - 12;
m_renderPassBeginInfo.renderArea.extent.width = (stripe_width * (stripe_count - 1)) + non_align_stripe_width + 4;
for (uint32_t i = 0; i < stripe_count; ++i) {
stripe_infos[i].stripeArea.offset.x = stripe_width * i;
stripe_infos[i].stripeArea.offset.y = 0;
stripe_infos[i].stripeArea.extent.width = i == 7 ? non_align_stripe_width : stripe_width;
stripe_infos[i].stripeArea.extent.height = stripe_height;
}
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeInfoARM-stripeArea-09453");
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-pNext-09539");
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
m_renderPassBeginInfo.renderArea.extent = {stripe_width, stripe_height * stripe_count};
const uint32_t half_stripe_height = stripe_height / 2;
for (uint32_t i = 0; i < stripe_count; ++i) {
stripe_infos[i].stripeArea.offset.x = 0;
stripe_infos[i].stripeArea.offset.y = (i == 1 ? half_stripe_height : stripe_height) * i;
stripe_infos[i].stripeArea.extent.width = stripe_width;
stripe_infos[i].stripeArea.extent.height = i == 2 ? half_stripe_height : stripe_height;
}
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeBeginInfoARM-stripeArea-09451");
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeInfoARM-stripeArea-09454");
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeInfoARM-stripeArea-09455");
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
const uint32_t non_align_stripe_height = stripe_height - 12;
m_renderPassBeginInfo.renderArea.extent.height = (stripe_height * (stripe_count - 1)) + non_align_stripe_height + 4;
for (uint32_t i = 0; i < stripe_count; ++i) {
stripe_infos[i].stripeArea.offset.x = 0;
stripe_infos[i].stripeArea.offset.y = stripe_height * i;
stripe_infos[i].stripeArea.extent.width = stripe_width;
stripe_infos[i].stripeArea.extent.height = i == 7 ? non_align_stripe_height : stripe_height;
}
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeInfoARM-stripeArea-09455");
m_errorMonitor->SetDesiredError("VUID-VkRenderPassBeginInfo-pNext-09539");
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, RenderPassWithRenderPassStripedQueueSubmit2) {
TEST_DESCRIPTION("Test to validate VK_ARM_render_pass_striped with QueueSubmit2.");
AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::synchronization2);
AddRequiredExtensions(VK_ARM_RENDER_PASS_STRIPED_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::renderPassStriped);
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceRenderPassStripedPropertiesARM rp_striped_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(rp_striped_props);
const uint32_t stripe_width = rp_striped_props.renderPassStripeGranularity.width;
const uint32_t stripe_height = rp_striped_props.renderPassStripeGranularity.height;
const uint32_t stripe_count = 4;
std::vector<VkRenderPassStripeInfoARM> stripe_infos(stripe_count);
for (uint32_t i = 0; i < stripe_count; ++i) {
stripe_infos[i] = vku::InitStructHelper();
stripe_infos[i].stripeArea.offset.x = stripe_width * i;
stripe_infos[i].stripeArea.offset.y = 0;
stripe_infos[i].stripeArea.extent = {stripe_width, stripe_height};
}
VkRenderPassStripeBeginInfoARM rp_stripe_info = vku::InitStructHelper();
rp_stripe_info.stripeInfoCount = stripe_count;
rp_stripe_info.pStripeInfos = stripe_infos.data();
m_renderPassBeginInfo.pNext = &rp_stripe_info;
m_renderPassBeginInfo.renderArea = {{0, 0}, {stripe_width * stripe_count, stripe_height}};
vkt::CommandPool command_pool(*m_device, m_device->graphics_queue_node_index_);
vkt::CommandBuffer cmd_buffer(*m_device, command_pool);
VkCommandBufferBeginInfo cmd_begin = vku::InitStructHelper();
cmd_buffer.Begin(&cmd_begin);
cmd_buffer.BeginRenderPass(m_renderPassBeginInfo);
cmd_buffer.EndRenderPass();
cmd_buffer.End();
VkCommandBufferSubmitInfo cb_submit_info = vku::InitStructHelper();
cb_submit_info.commandBuffer = cmd_buffer;
m_errorMonitor->SetDesiredError("VUID-VkCommandBufferSubmitInfo-commandBuffer-09445");
VkSubmitInfo2 submit_info = vku::InitStructHelper();
submit_info.commandBufferInfoCount = 1;
submit_info.pCommandBufferInfos = &cb_submit_info;
vk::QueueSubmit2KHR(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_default_queue->Wait();
m_errorMonitor->VerifyFound();
VkSemaphoreCreateInfo semaphore_create_info = vku::InitStructHelper();
VkSemaphoreTypeCreateInfo semaphore_type_create_info = vku::InitStructHelper();
semaphore_type_create_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
VkSemaphoreCreateInfo semaphore_timeline_create_info = vku::InitStructHelper(&semaphore_type_create_info);
vkt::Semaphore semaphore[stripe_count + 1];
VkSemaphoreSubmitInfo semaphore_submit_infos[stripe_count + 1];
for (uint32_t i = 0; i < stripe_count + 1; ++i) {
VkSemaphoreCreateInfo create_info = i == 4 ? semaphore_timeline_create_info : semaphore_create_info;
semaphore[i].Init(*m_device, create_info);
semaphore_submit_infos[i] = vku::InitStructHelper();
semaphore_submit_infos[i].semaphore = semaphore[i];
}
VkRenderPassStripeSubmitInfoARM rp_stripe_submit_info = vku::InitStructHelper();
rp_stripe_submit_info.stripeSemaphoreInfoCount = stripe_count + 1;
rp_stripe_submit_info.pStripeSemaphoreInfos = semaphore_submit_infos;
cb_submit_info.pNext = &rp_stripe_submit_info;
m_errorMonitor->SetDesiredError("VUID-VkCommandBufferSubmitInfo-pNext-09446");
m_errorMonitor->SetDesiredError("VUID-VkRenderPassStripeSubmitInfoARM-semaphore-09447");
vk::QueueSubmit2KHR(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
m_default_queue->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, MissingNestedCommandBuffersFeature) {
TEST_DESCRIPTION("Use VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_KHR when nextedCommandBuffers is not enabled");
AddRequiredExtensions(VK_EXT_NESTED_COMMAND_BUFFER_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBeginRenderPass-contents-09640");
vk::CmdBeginRenderPass(m_command_buffer, &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_KHR);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, MissingNestedCommandBuffersFeature2) {
TEST_DESCRIPTION("Use VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_KHR when nextedCommandBuffers is not enabled");
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_NESTED_COMMAND_BUFFER_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
auto subpassBeginInfo =
vku::InitStruct<VkSubpassBeginInfo>(nullptr, VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_KHR);
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkSubpassBeginInfo-contents-09382");
vk::CmdBeginRenderPass2KHR(m_command_buffer, &m_renderPassBeginInfo, &subpassBeginInfo);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeRenderPass, FramebufferMismatchedAttachmentCount) {
TEST_DESCRIPTION("Create framebuffer with different attachment count than render pass has");
RETURN_IF_SKIP(Init());
InitRenderTarget();
vkt::ImageView rt_view0 = m_renderTargets[0]->CreateView();
vkt::ImageView rt_view1 = m_renderTargets[0]->CreateView();
VkImageView ivs[2] = {rt_view0, rt_view1};
VkFramebufferCreateInfo fb_info = vku::InitStructHelper();
fb_info.pAttachments = ivs;
fb_info.width = 32u;
fb_info.height = 32u;
fb_info.layers = 1u;
fb_info.renderPass = m_renderPass;
// Set mis-matching attachmentCount
fb_info.attachmentCount = 2u;
VkFramebuffer fb;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-attachmentCount-00876");
vk::CreateFramebuffer(device(), &fb_info, nullptr, &fb);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, FramebufferDepthAttachmentInvalidUsage) {
TEST_DESCRIPTION("Create framebuffer with depth/stencil attachment that doesn't have depth stencil usage");
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkFormat depth_stencil_format = FindSupportedDepthStencilFormat(Gpu());
vkt::Image image(*m_device, 32u, 32u, depth_stencil_format, VK_IMAGE_USAGE_SAMPLED_BIT);
vkt::ImageView image_view = image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
VkAttachmentReference attach = {};
attach.layout = VK_IMAGE_LAYOUT_GENERAL;
VkSubpassDescription subpass = {};
subpass.pDepthStencilAttachment = &attach;
VkAttachmentDescription attach_desc = {};
attach_desc.format = depth_stencil_format;
attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.attachmentCount = 1u;
rpci.pAttachments = &attach_desc;
rpci.subpassCount = 1u;
rpci.pSubpasses = &subpass;
vkt::RenderPass rp_ds(*m_device, rpci);
VkFramebufferCreateInfo fb_info = vku::InitStructHelper();
fb_info.renderPass = rp_ds;
fb_info.attachmentCount = 1u;
fb_info.pAttachments = &image_view.handle();
fb_info.width = 32u;
fb_info.height = 32u;
fb_info.layers = 1u;
VkFramebuffer framebuffer;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-pAttachments-02633");
vk::CreateFramebuffer(device(), &fb_info, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, Framebuffer2DViewDsFormat) {
TEST_DESCRIPTION("Create a 2D depth/stencil view from 3D image to use as a framebuffer attachment");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkFormat depth_format = FindSupportedDepthOnlyFormat(Gpu());
VkImageFormatProperties2 image_format_prop = vku::InitStructHelper();
VkPhysicalDeviceImageFormatInfo2 image_format_info = vku::InitStructHelper();
image_format_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_format_info.type = VK_IMAGE_TYPE_3D;
image_format_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
image_format_info.format = depth_format;
VkResult result = vk::GetPhysicalDeviceImageFormatProperties2(m_device->Physical(), &image_format_info, &image_format_prop);
if (result != VK_SUCCESS) {
GTEST_SKIP() << "Required image parameters are unsupported";
}
VkAttachmentDescription attachment_description = {};
attachment_description.format = depth_format;
attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment_description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachment_description.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkAttachmentReference attachment_reference;
attachment_reference.attachment = 0u;
attachment_reference.layout = VK_IMAGE_LAYOUT_GENERAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.pDepthStencilAttachment = &attachment_reference;
VkRenderPassCreateInfo rp_ci = vku::InitStructHelper();
rp_ci.attachmentCount = 1u;
rp_ci.pAttachments = &attachment_description;
rp_ci.subpassCount = 1u;
rp_ci.pSubpasses = &subpass;
vkt::RenderPass render_pass(*m_device, rp_ci);
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.flags = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
image_ci.imageType = VK_IMAGE_TYPE_3D;
image_ci.format = depth_format;
image_ci.extent = {32u, 32u, 1u};
image_ci.mipLevels = 1u;
image_ci.arrayLayers = 1u;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
image_ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
vkt::Image image(*m_device, image_ci);
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.image = image;
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.format = depth_format;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1};
vkt::ImageView view(*m_device, image_view_ci);
VkFramebufferCreateInfo framebuffer_ci = vku::InitStructHelper();
framebuffer_ci.renderPass = render_pass;
framebuffer_ci.attachmentCount = 1u;
framebuffer_ci.pAttachments = &view.handle();
framebuffer_ci.width = 32u;
framebuffer_ci.height = 32u;
framebuffer_ci.layers = 1u;
VkFramebuffer framebuffer;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-pAttachments-00891");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, FramebufferMismatchedFormat) {
TEST_DESCRIPTION("Create a framebuffer where its attachment format doesn't match render pass attachemnt reference format");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkImageFormatProperties2 image_format_prop = vku::InitStructHelper();
VkPhysicalDeviceImageFormatInfo2 image_format_info = vku::InitStructHelper();
image_format_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_format_info.type = VK_IMAGE_TYPE_2D;
image_format_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_format_info.format = VK_FORMAT_B8G8R8A8_UNORM;
VkResult result = vk::GetPhysicalDeviceImageFormatProperties2(m_device->Physical(), &image_format_info, &image_format_prop);
if (result != VK_SUCCESS || (image_format_prop.imageFormatProperties.sampleCounts & VK_SAMPLE_COUNT_2_BIT) == 0) {
GTEST_SKIP() << "Required image parameters are unsupported";
}
VkAttachmentDescription attachment_description = {};
attachment_description.format = VK_FORMAT_B8G8R8A8_UNORM;
attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment_description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachment_description.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkAttachmentReference attachment_reference;
attachment_reference.attachment = 0u;
attachment_reference.layout = VK_IMAGE_LAYOUT_GENERAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1u;
subpass.pColorAttachments = &attachment_reference;
VkRenderPassCreateInfo rp_ci = vku::InitStructHelper();
rp_ci.attachmentCount = 1u;
rp_ci.pAttachments = &attachment_description;
rp_ci.subpassCount = 1u;
rp_ci.pSubpasses = &subpass;
vkt::RenderPass render_pass(*m_device, rp_ci);
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.imageType = VK_IMAGE_TYPE_2D;
image_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_ci.extent = {32u, 32u, 1u};
image_ci.mipLevels = 1u;
image_ci.arrayLayers = 1u;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
vkt::Image image(*m_device, image_ci);
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.image = image;
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
vkt::ImageView view(*m_device, image_view_ci);
VkFramebufferCreateInfo framebuffer_ci = vku::InitStructHelper();
framebuffer_ci.renderPass = render_pass;
framebuffer_ci.attachmentCount = 1u;
framebuffer_ci.pAttachments = &view.handle();
framebuffer_ci.width = 32u;
framebuffer_ci.height = 32u;
framebuffer_ci.layers = 1u;
VkFramebuffer framebuffer;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-pAttachments-00880");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
image_ci.format = attachment_description.format;
image_ci.samples = VK_SAMPLE_COUNT_2_BIT;
vkt::Image image2(*m_device, image_ci);
image_view_ci.format = attachment_description.format;
image_view_ci.image = image2;
vkt::ImageView view2(*m_device, image_view_ci);
framebuffer_ci.pAttachments = &view2.handle();
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-pAttachments-00881");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
image_ci.mipLevels = 2u;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
vkt::Image image3(*m_device, image_ci);
image_view_ci.image = image3;
image_view_ci.subresourceRange.levelCount = 2u;
vkt::ImageView view3(*m_device, image_view_ci);
framebuffer_ci.pAttachments = &view3.handle();
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-pAttachments-00883");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, FramebufferCreateWithInvalidExtent) {
TEST_DESCRIPTION("Create a framebuffer with extent greater than attachments extent");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
InitRenderTarget();
vkt::ImageView view = m_renderTargets[0]->CreateView();
VkFramebufferCreateInfo framebuffer_ci = vku::InitStructHelper();
framebuffer_ci.renderPass = m_renderPass;
framebuffer_ci.attachmentCount = 1u;
framebuffer_ci.pAttachments = &view.handle();
framebuffer_ci.width = m_renderPassBeginInfo.renderArea.extent.width + 1;
framebuffer_ci.height = m_renderPassBeginInfo.renderArea.extent.height;
framebuffer_ci.layers = 1u;
VkFramebuffer framebuffer;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-flags-04533");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
framebuffer_ci.width = m_renderPassBeginInfo.renderArea.extent.width;
framebuffer_ci.height = m_renderPassBeginInfo.renderArea.extent.height + 1;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-flags-04534");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
framebuffer_ci.height = m_renderPassBeginInfo.renderArea.extent.height;
framebuffer_ci.layers = 2u;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-flags-04535");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, FramebufferCreateWithInvalidSwizzle) {
TEST_DESCRIPTION("Create a framebuffer with image view that does not have identity swizzle");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.image = m_renderTargets[0]->handle();
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_ci.format = m_render_target_fmt;
image_view_ci.components.r = VK_COMPONENT_SWIZZLE_B;
image_view_ci.components.g = VK_COMPONENT_SWIZZLE_G;
image_view_ci.components.b = VK_COMPONENT_SWIZZLE_R;
image_view_ci.components.a = VK_COMPONENT_SWIZZLE_A;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
vkt::ImageView view(*m_device, image_view_ci);
VkFramebufferCreateInfo framebuffer_ci = vku::InitStructHelper();
framebuffer_ci.renderPass = m_renderPass;
framebuffer_ci.attachmentCount = 1u;
framebuffer_ci.pAttachments = &view.handle();
framebuffer_ci.width = m_renderPassBeginInfo.renderArea.extent.width;
framebuffer_ci.height = m_renderPassBeginInfo.renderArea.extent.height;
framebuffer_ci.layers = 1u;
VkFramebuffer framebuffer;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-pAttachments-00884");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, FramebufferMultiviewWithLayers) {
TEST_DESCRIPTION("Create a framebuffer with multiple layers when renderpass has non-zero view masks");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredFeature(vkt::Feature::multiview);
RETURN_IF_SKIP(Init());
VkAttachmentDescription attachment_description = {};
attachment_description.format = VK_FORMAT_R8G8B8A8_UNORM;
attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment_description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachment_description.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkAttachmentReference attachment_reference;
attachment_reference.attachment = 0u;
attachment_reference.layout = VK_IMAGE_LAYOUT_GENERAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1u;
subpass.pColorAttachments = &attachment_reference;
uint32_t view_mask = 0x3u;
VkRenderPassMultiviewCreateInfo render_pass_multiview_ci = vku::InitStructHelper();
render_pass_multiview_ci.subpassCount = 1u;
render_pass_multiview_ci.pViewMasks = &view_mask;
VkRenderPassCreateInfo rp_ci = vku::InitStructHelper(&render_pass_multiview_ci);
rp_ci.attachmentCount = 1u;
rp_ci.pAttachments = &attachment_description;
rp_ci.subpassCount = 1u;
rp_ci.pSubpasses = &subpass;
vkt::RenderPass render_pass(*m_device, rp_ci);
view_mask = 0x8u;
vkt::RenderPass render_pass2(*m_device, rp_ci);
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.imageType = VK_IMAGE_TYPE_2D;
image_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_ci.extent = {32u, 32u, 1u};
image_ci.mipLevels = 1u;
image_ci.arrayLayers = 2u;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
vkt::Image image(*m_device, image_ci);
VkImageViewCreateInfo image_view_ci = vku::InitStructHelper();
image_view_ci.image = image;
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
image_view_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_view_ci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 2};
vkt::ImageView view(*m_device, image_view_ci);
VkFramebufferCreateInfo framebuffer_ci = vku::InitStructHelper();
framebuffer_ci.renderPass = render_pass;
framebuffer_ci.attachmentCount = 1u;
framebuffer_ci.pAttachments = &view.handle();
framebuffer_ci.width = 32u;
framebuffer_ci.height = 32u;
framebuffer_ci.layers = 2u;
VkFramebuffer framebuffer;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-renderPass-02531");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
framebuffer_ci.renderPass = render_pass2;
framebuffer_ci.layers = 1u;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-renderPass-04536");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, FramebufferLimits) {
TEST_DESCRIPTION("Test creating framebuffer outside of limits");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
VkSubpassDescription subpass = {};
VkRenderPassCreateInfo rp_ci = vku::InitStructHelper();
rp_ci.subpassCount = 1u;
rp_ci.pSubpasses = &subpass;
vkt::RenderPass render_pass(*m_device, rp_ci);
VkFramebufferCreateInfo framebuffer_ci = vku::InitStructHelper();
framebuffer_ci.renderPass = render_pass;
framebuffer_ci.width = m_device->Physical().limits_.maxFramebufferWidth + 1u;
framebuffer_ci.height = 32u;
framebuffer_ci.layers = 1u;
VkFramebuffer framebuffer;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-width-00886");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
framebuffer_ci.width = 0u;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-width-00885");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
framebuffer_ci.width = 32u;
framebuffer_ci.height = m_device->Physical().limits_.maxFramebufferHeight + 1u;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-height-00888");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
framebuffer_ci.height = 0u;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-height-00887");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
framebuffer_ci.height = 32u;
framebuffer_ci.layers = m_device->Physical().limits_.maxFramebufferLayers + 1u;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-layers-00890");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
framebuffer_ci.layers = 0u;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-layers-00889");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, CreateFramebufferWithNullHandleView) {
RETURN_IF_SKIP(Init());
VkAttachmentDescription description = {0,
VK_FORMAT_R8G8B8A8_UNORM,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL};
VkAttachmentReference attachment_ref = {0, VK_IMAGE_LAYOUT_GENERAL};
VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1u, &attachment_ref, nullptr, nullptr, 0,
nullptr};
auto rp_ci = vku::InitStruct<VkRenderPassCreateInfo>(nullptr, 0u, 1u, &description, 1u, &subpass, 0u, nullptr);
vkt::RenderPass render_pass(*m_device, rp_ci);
VkImageView view = VK_NULL_HANDLE;
VkFramebufferCreateInfo framebuffer_ci = vku::InitStructHelper();
framebuffer_ci.renderPass = render_pass;
framebuffer_ci.attachmentCount = 1u;
framebuffer_ci.pAttachments = &view;
framebuffer_ci.width = 32u;
framebuffer_ci.height = 32u;
framebuffer_ci.layers = 1u;
VkFramebuffer framebuffer;
m_errorMonitor->SetDesiredError("VUID-VkFramebufferCreateInfo-flags-02778");
vk::CreateFramebuffer(device(), &framebuffer_ci, nullptr, &framebuffer);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, RenderPassAttachmentFlagsMaintenance10Enabled) {
AddRequiredExtensions(VK_KHR_MAINTENANCE_10_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::maintenance10);
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceMaintenance10PropertiesKHR maintenance10_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(maintenance10_props);
auto depth_format = FindSupportedDepthStencilFormat(Gpu());
// A renderpass with one color attachment.
VkAttachmentDescription attachment = {0,
depth_format,
VK_SAMPLE_COUNT_4_BIT,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL};
attachment.flags = VK_ATTACHMENT_DESCRIPTION_RESOLVE_SKIP_TRANSFER_FUNCTION_BIT_KHR |
VK_ATTACHMENT_DESCRIPTION_RESOLVE_ENABLE_TRANSFER_FUNCTION_BIT_KHR;
VkAttachmentReference att_ref_depth_stencil = {0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL};
VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, 0, nullptr,
nullptr, &att_ref_depth_stencil, 0, nullptr};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &attachment, 1, &subpass, 0, nullptr};
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription-flags-11773");
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription-flags-11776");
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription-flags-11777");
if (!maintenance10_props.resolveSrgbFormatSupportsTransferFunctionControl) {
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription-flags-11774");
}
vkt::RenderPass rp(*m_device, rpci);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, RenderPassAttachmentFlagsMaintenance10Disabled) {
AddRequiredExtensions(VK_KHR_MAINTENANCE_10_EXTENSION_NAME);
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
// A renderpass with one color attachment.
VkAttachmentDescription attachment = {0,
VK_FORMAT_R8_SRGB,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
attachment.flags = VK_ATTACHMENT_DESCRIPTION_RESOLVE_SKIP_TRANSFER_FUNCTION_BIT_KHR;
VkAttachmentReference att_ref_depth_stencil = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, 0, nullptr,
nullptr, &att_ref_depth_stencil, 0, nullptr};
VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &attachment, 1, &subpass, 0, nullptr};
m_errorMonitor->SetDesiredError("VUID-VkAttachmentDescription-flags-11775");
vkt::RenderPass rp(*m_device, rpci);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeRenderPass, MaxPerStageDescriptorInputAttachments) {
RETURN_IF_SKIP(Init());
const uint32_t max_attachments = m_device->Physical().limits_.maxPerStageDescriptorInputAttachments;
if (max_attachments == vvl::kU32Max) {
GTEST_SKIP() << "maxPerStageDescriptorInputAttachments is uint32_t max";
}
std::vector<VkAttachmentReference> references;
for (uint32_t i = 0; i <= max_attachments; i++) {
references.emplace_back(VkAttachmentReference{0, VK_IMAGE_LAYOUT_GENERAL});
}
VkSubpassDescription subpasses = {
0, VK_PIPELINE_BIND_POINT_GRAPHICS, (uint32_t)references.size(), references.data(), 0, nullptr, nullptr, nullptr, 0,
nullptr};
VkAttachmentDescription attach_desc = {};
attach_desc.format = VK_FORMAT_R8G8B8A8_UNORM;
attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
rpci.subpassCount = 1;
rpci.pSubpasses = &subpasses;
m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription-inputAttachmentCount-12293");
vkt::RenderPass rp(*m_device, rpci);
m_errorMonitor->VerifyFound();
}