blob: 59b50048a5b7b667c1fb243f7bab571c8a946ec5 [file] [log] [blame]
/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2019 The Khronos Group Inc.
* Copyright (c) 2019 Valve Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief Tests vkCmdClearAttachments with unused attachments.
*//*--------------------------------------------------------------------*/
#include "vktRenderPassUnusedClearAttachmentTests.hpp"
#include "pipeline/vktPipelineImageUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkRefUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkImageUtil.hpp"
#include "tcuTextureUtil.hpp"
#include <sstream>
#include <functional>
#include <vector>
#include <string>
#include <memory>
namespace vkt
{
namespace renderpass
{
namespace
{
constexpr size_t COLOR_ATTACHMENTS_NUMBER = 4; // maxColorAttachments is guaranteed to be at least 4.
constexpr VkFormat FORMAT_COLOR = VK_FORMAT_R8G8B8A8_UNORM;
constexpr VkFormat FORMAT_DEPTH = VK_FORMAT_D32_SFLOAT;
constexpr VkFormat FORMAT_STENCIL = VK_FORMAT_S8_UINT;
constexpr VkFormat FORMAT_DEPTH_STENCIL = VK_FORMAT_D32_SFLOAT_S8_UINT;
const deBool DE_BOOL_VALUES[] = { DE_FALSE, DE_TRUE };
enum DepthStencilType
{
DEPTH_STENCIL_NONE = 0,
DEPTH_STENCIL_DEPTH_ONLY = 1,
DEPTH_STENCIL_STENCIL_ONLY = 2,
DEPTH_STENCIL_BOTH = 3,
DEPTH_STENCIL_MAX_ENUM = 4
};
std::string getFormatBriefName (VkFormat format)
{
switch (format)
{
case VK_FORMAT_D32_SFLOAT: return "d32";
case VK_FORMAT_S8_UINT: return "s8";
case VK_FORMAT_D32_SFLOAT_S8_UINT: return "d32s8";
default: break;
}
return "";
}
std::string depthStencilTypeName (DepthStencilType type, VkFormat format)
{
DE_ASSERT(type >= DEPTH_STENCIL_NONE && type < DEPTH_STENCIL_MAX_ENUM);
const std::string formatName = getFormatBriefName(format);
switch (type)
{
case DEPTH_STENCIL_NONE: return "nods";
case DEPTH_STENCIL_DEPTH_ONLY: return "depthonly_" + formatName;
case DEPTH_STENCIL_STENCIL_ONLY: return "stencilonly_" + formatName;
case DEPTH_STENCIL_BOTH: return "depthstencil_" + formatName;
default: return "UNKNOWN"; // Unreachable.
}
return "UNKNOWN"; // Unreachable.
}
VkImageAspectFlags getClearAspectMask (DepthStencilType type)
{
VkImageAspectFlags aspectMask = 0u;
if (type == DEPTH_STENCIL_DEPTH_ONLY || type == DEPTH_STENCIL_BOTH)
aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
if (type == DEPTH_STENCIL_STENCIL_ONLY || type == DEPTH_STENCIL_BOTH)
aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
return aspectMask;
}
VkImageAspectFlags getFormatAspectMask (VkFormat format)
{
const auto order = mapVkFormat(format).order;
VkImageAspectFlags aspectMask = 0u;
if (tcu::hasDepthComponent(order))
aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
if (tcu::hasStencilComponent(order))
aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
if (!aspectMask)
aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
return aspectMask;
}
std::vector<VkFormat> getFormats (DepthStencilType type)
{
DE_ASSERT(type >= DEPTH_STENCIL_NONE && type < DEPTH_STENCIL_MAX_ENUM);
std::vector<VkFormat> formats;
if (type != DEPTH_STENCIL_NONE)
formats.push_back(FORMAT_DEPTH_STENCIL);
else
formats.push_back(VK_FORMAT_UNDEFINED);
if (type == DEPTH_STENCIL_DEPTH_ONLY)
formats.push_back(FORMAT_DEPTH);
else if (type == DEPTH_STENCIL_STENCIL_ONLY)
formats.push_back(FORMAT_STENCIL);
return formats;
}
bool isDepthOnly(DepthStencilType type)
{
return (type == DEPTH_STENCIL_DEPTH_ONLY);
}
bool isStencilOnly(DepthStencilType type)
{
return (type == DEPTH_STENCIL_STENCIL_ONLY);
}
bool hasDepthStencil(DepthStencilType type)
{
return (type != DEPTH_STENCIL_NONE);
}
struct TestParams
{
TestParams(size_t numColorAttachments, DepthStencilType depthStencilType_, deBool depthStencilUsed_, VkFormat depthStencilFormat_, RenderPassType renderPassType_)
: colorUsed(numColorAttachments, DE_FALSE)
, depthStencilType(depthStencilType_)
, depthStencilUsed(depthStencilUsed_)
, depthStencilFormat(depthStencilFormat_)
, renderPassType(renderPassType_)
{}
std::vector<deBool> colorUsed;
DepthStencilType depthStencilType;
deBool depthStencilUsed;
VkFormat depthStencilFormat;
RenderPassType renderPassType;
};
class UnusedClearAttachmentTestInstance : public vkt::TestInstance
{
public:
UnusedClearAttachmentTestInstance (Context& context,
const TestParams& testParams);
virtual ~UnusedClearAttachmentTestInstance (void) {}
virtual tcu::TestStatus iterate (void);
template<typename RenderpassSubpass>
void createCommandBuffer (const DeviceInterface& vk,
VkDevice vkDevice);
private:
static constexpr deUint32 kImageWidth = 32;
static constexpr deUint32 kImageHeight = 32;
const tcu::UVec2 m_renderSize = { kImageWidth, kImageHeight };
VkClearValue m_initialColor;
VkClearValue m_initialColorDepth;
VkClearValue m_clearColor;
VkClearValue m_clearColorDepth;
const TestParams m_testParams;
std::vector<Move<VkImage>> m_colorImages;
std::vector<de::MovePtr<Allocation>> m_colorImageAllocs;
std::vector<Move<VkImageView>> m_colorAttachmentViews;
Move<VkImage> m_depthImage;
de::MovePtr<Allocation> m_depthImageAlloc;
Move<VkImageView> m_depthAttachmentView;
Move<VkRenderPass> m_renderPass;
Move<VkFramebuffer> m_framebuffer;
Move<VkShaderModule> m_vertexShaderModule;
Move<VkShaderModule> m_fragmentShaderModule;
Move<VkDescriptorSetLayout> m_descriptorSetLayout;
Move<VkPipelineLayout> m_pipelineLayout;
Move<VkPipeline> m_graphicsPipeline;
Move<VkCommandPool> m_cmdPool;
Move<VkCommandBuffer> m_cmdBuffer;
};
class UnusedClearAttachmentTest : public vkt::TestCase
{
public:
UnusedClearAttachmentTest (tcu::TestContext& testContext,
const std::string& name,
const std::string& description,
const TestParams& testParams)
: vkt::TestCase(testContext, name, description)
, m_testParams(testParams)
{}
virtual ~UnusedClearAttachmentTest (void) {}
virtual void initPrograms (SourceCollections& sourceCollections) const;
virtual TestInstance* createInstance (Context& context) const;
virtual void checkSupport (Context& context) const;
private:
const TestParams m_testParams;
};
void checkFormatSupported(Context& context, VkFormat format, VkImageUsageFlags usage)
{
VkResult result;
VkImageFormatProperties properties;
result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(
context.getPhysicalDevice(), format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, 0, &properties);
if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
{
std::ostringstream msg;
msg << "Format " << format << " not supported for usage flags 0x" << std::hex << usage;
TCU_THROW(NotSupportedError, msg.str());
}
VK_CHECK(result);
}
void UnusedClearAttachmentTest::checkSupport (Context& context) const
{
// Check for renderpass2 extension if used
if (m_testParams.renderPassType == RENDERPASS_TYPE_RENDERPASS2)
context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
// Check support for the needed color, depth and stencil formats.
if (!m_testParams.colorUsed.empty())
checkFormatSupported(context, FORMAT_COLOR, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
if (hasDepthStencil(m_testParams.depthStencilType))
checkFormatSupported(context, m_testParams.depthStencilFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
}
TestInstance* UnusedClearAttachmentTest::createInstance (Context& context) const
{
return new UnusedClearAttachmentTestInstance(context, m_testParams);
}
// These shaders are needed to create the graphics pipeline, but they will not be actually used because we will not draw anything.
void UnusedClearAttachmentTest::initPrograms (SourceCollections& sourceCollections) const
{
// Vertex shader.
sourceCollections.glslSources.add("vert_shader") << glu::VertexSource(
"#version 450\n"
"precision highp float;\n"
"layout(location = 0) in vec4 position;\n"
"layout(location = 0) out vec4 vtxColor;\n"
"void main (void)\n"
"{\n"
"\tgl_Position = position;\n"
"\tvtxColor = vec4(0.5, 0.5, 0.5, 1.0);\n"
"}\n");
// Fragment shader.
std::ostringstream fragmentSource;
fragmentSource << "#version 450\n"
<< "precision highp float;\n"
<< "layout(location = 0) in vec4 vtxColor;\n";
for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
{
if (m_testParams.colorUsed[i])
fragmentSource << "layout(location = " << i << ") out vec4 fragColor" << i << ";\n";
}
fragmentSource << "void main (void)\n"
<< "{\n";
for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
{
if (m_testParams.colorUsed[i])
fragmentSource << "\tfragColor" << i << " = vtxColor;\n";
}
fragmentSource << "}\n";
sourceCollections.glslSources.add("frag_shader") << glu::FragmentSource(fragmentSource.str());
}
// Create a render pass for this use case.
template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
Move<VkRenderPass> createRenderPass (const DeviceInterface& vk,
VkDevice vkDevice,
const TestParams testParams)
{
const VkImageAspectFlags colorAspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
const VkImageAspectFlags dsClearAspectMask = getClearAspectMask(testParams.depthStencilType);
const bool isDepthStencil = hasDepthStencil(testParams.depthStencilType);
// Create attachment descriptions.
const AttachmentDesc attachmentDescription (
DE_NULL, // const void* pNext
(VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
FORMAT_COLOR, // VkFormat format
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
);
std::vector<AttachmentDesc> attachmentDescriptions (testParams.colorUsed.size(), attachmentDescription);
if (isDepthStencil)
{
const bool depthOnly = isDepthOnly(testParams.depthStencilType);
const bool stencilOnly = isStencilOnly(testParams.depthStencilType);
const VkAttachmentLoadOp depthLoadOp = (stencilOnly ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_LOAD);
const VkAttachmentStoreOp depthStoreOp = (stencilOnly ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE);
const VkAttachmentLoadOp stencilLoadOp = (depthOnly ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_LOAD);
const VkAttachmentStoreOp stencilStoreOp = (depthOnly ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE);
attachmentDescriptions.emplace_back(
nullptr, // const void* pNext
(VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
testParams.depthStencilFormat, // VkFormat format
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
depthLoadOp, // VkAttachmentLoadOp loadOp
depthStoreOp, // VkAttachmentStoreOp storeOp
stencilLoadOp, // VkAttachmentLoadOp stencilLoadOp
stencilStoreOp, // VkAttachmentStoreOp stencilStoreOp
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
);
}
// Mark attachments as used or not depending on the test parameters.
std::vector<AttachmentRef> attachmentReferences;
for (size_t i = 0; i < testParams.colorUsed.size(); ++i)
{
attachmentReferences.push_back(AttachmentRef(
DE_NULL, // const void* pNext
(testParams.colorUsed[i] ? static_cast<deUint32>(i) : VK_ATTACHMENT_UNUSED), // deUint32 attachment
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
colorAspectMask // VkImageAspectFlags aspectMask
));
}
std::unique_ptr<AttachmentRef> depthAttachmentRef;
if (isDepthStencil)
{
depthAttachmentRef.reset(new AttachmentRef(
DE_NULL,
(testParams.depthStencilUsed ? static_cast<deUint32>(testParams.colorUsed.size()) : VK_ATTACHMENT_UNUSED),
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
dsClearAspectMask
));
}
// Create subpass description with the previous color attachment references.
const SubpassDesc subpassDescription (
DE_NULL,
(VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
0u, // deUint32 viewMask
0u, // deUint32 inputAttachmentCount
DE_NULL, // const VkAttachmentReference* pInputAttachments
static_cast<deUint32>(attachmentReferences.size()), // deUint32 colorAttachmentCount
(attachmentReferences.empty() ? DE_NULL : attachmentReferences.data()), // const VkAttachmentReference* pColorAttachments
DE_NULL, // const VkAttachmentReference* pResolveAttachments
(depthAttachmentRef ? depthAttachmentRef.get() : DE_NULL), // const VkAttachmentReference* pDepthStencilAttachment
0u, // deUint32 preserveAttachmentCount
DE_NULL // const deUint32* pPreserveAttachments
);
const RenderPassCreateInfo renderPassInfo (
DE_NULL, // const void* pNext
(VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount
(attachmentDescriptions.empty() ? DE_NULL : attachmentDescriptions.data()), // const VkAttachmentDescription* pAttachments
1u, // deUint32 subpassCount
&subpassDescription, // const VkSubpassDescription* pSubpasses
0u, // deUint32 dependencyCount
DE_NULL, // const VkSubpassDependency* pDependencies
0u, // deUint32 correlatedViewMaskCount
DE_NULL // const deUint32* pCorrelatedViewMasks
);
return renderPassInfo.createRenderPass(vk, vkDevice);
}
UnusedClearAttachmentTestInstance::UnusedClearAttachmentTestInstance(Context& context,
const TestParams& testParams)
: vkt::TestInstance(context)
, m_testParams(testParams)
{
// Initial color for all images.
m_initialColor.color.float32[0] = 0.0f;
m_initialColor.color.float32[1] = 0.0f;
m_initialColor.color.float32[2] = 0.0f;
m_initialColor.color.float32[3] = 1.0f;
m_initialColorDepth.depthStencil.depth = 1.0f;
m_initialColorDepth.depthStencil.stencil = 0u;
// Clear color for used attachments.
m_clearColor.color.float32[0] = 1.0f;
m_clearColor.color.float32[1] = 1.0f;
m_clearColor.color.float32[2] = 1.0f;
m_clearColor.color.float32[3] = 1.0f;
m_clearColorDepth.depthStencil.depth = 0.0f;
m_clearColorDepth.depthStencil.stencil = 255u;
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice vkDevice = m_context.getDevice();
const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
const VkComponentMapping componentMapping = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
// Create color images.
{
const VkImageCreateInfo colorImageParams =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
FORMAT_COLOR, // VkFormat format;
{ kImageWidth, kImageHeight, 1u }, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyIndexCount;
&queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
};
const VkImageCreateInfo depthImageParams =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
m_testParams.depthStencilFormat, // VkFormat format;
{ kImageWidth, kImageHeight, 1u }, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyIndexCount;
&queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
};
for (size_t i = 0; i < testParams.colorUsed.size(); ++i)
{
// Create, allocate and bind image memory.
m_colorImages.emplace_back(createImage(vk, vkDevice, &colorImageParams));
m_colorImageAllocs.emplace_back(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImages.back()), MemoryRequirement::Any));
VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImages.back(), m_colorImageAllocs.back()->getMemory(), m_colorImageAllocs.back()->getOffset()));
// Create image view.
{
const VkImageViewCreateInfo colorAttachmentViewParams =
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageViewCreateFlags flags;
*m_colorImages.back(), // VkImage image;
VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
FORMAT_COLOR, // VkFormat format;
componentMapping, // VkChannelMapping channels;
{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
};
m_colorAttachmentViews.emplace_back(createImageView(vk, vkDevice, &colorAttachmentViewParams));
}
// Clear image and leave it prepared to be used as a color attachment.
{
const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Move<VkCommandPool> cmdPool;
Move<VkCommandBuffer> cmdBuffer;
// Create command pool and buffer
cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
// From undefined layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
const VkImageMemoryBarrier preImageBarrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkAccessFlags srcAccessMask;
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
*m_colorImages.back(), // VkImage image;
{ // VkImageSubresourceRange subresourceRange;
aspectMask, // VkImageAspect aspect;
0u, // deUint32 baseMipLevel;
1u, // deUint32 mipLevels;
0u, // deUint32 baseArraySlice;
1u // deUint32 arraySize;
}
};
// From VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
const VkImageMemoryBarrier postImageBarrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
DE_NULL, // const void* pNext;
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
*m_colorImages.back(), // VkImage image;
{ // VkImageSubresourceRange subresourceRange;
aspectMask, // VkImageAspect aspect;
0u, // deUint32 baseMipLevel;
1u, // deUint32 mipLevels;
0u, // deUint32 baseArraySlice;
1u // deUint32 arraySize;
}
};
const VkImageSubresourceRange clearRange =
{
aspectMask, // VkImageAspectFlags aspectMask;
0u, // deUint32 baseMipLevel;
1u, // deUint32 levelCount;
0u, // deUint32 baseArrayLayer;
1u // deUint32 layerCount;
};
// Clear image and transfer layout.
beginCommandBuffer(vk, *cmdBuffer);
vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
vk.cmdClearColorImage(*cmdBuffer, *m_colorImages.back(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_initialColor.color, 1, &clearRange);
vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
endCommandBuffer(vk, *cmdBuffer);
submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
}
}
if (hasDepthStencil(m_testParams.depthStencilType))
{
const VkImageAspectFlags clearAspectMask = getClearAspectMask(m_testParams.depthStencilType);
const VkImageAspectFlags formatAspectMask = getFormatAspectMask(m_testParams.depthStencilFormat);
// Create, allocate and bind image memory.
m_depthImage = createImage(vk, vkDevice, &depthImageParams);
m_depthImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_depthImage), MemoryRequirement::Any);
VK_CHECK(vk.bindImageMemory(vkDevice, *m_depthImage, m_depthImageAlloc->getMemory(), m_depthImageAlloc->getOffset()));
// Create image view.
{
const VkImageViewCreateInfo depthAttachmentViewParams =
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageViewCreateFlags flags;
*m_depthImage, // VkImage image;
VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
m_testParams.depthStencilFormat, // VkFormat format;
componentMapping, // VkChannelMapping channels;
{ clearAspectMask, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
};
m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams);
}
// Clear image and leave it prepared to be used as a depth/stencil attachment.
{
Move<VkCommandPool> cmdPool;
Move<VkCommandBuffer> cmdBuffer;
// Create command pool and buffer
cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
// From undefined layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
const VkImageMemoryBarrier preImageBarrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkAccessFlags srcAccessMask;
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
*m_depthImage, // VkImage image;
{ // VkImageSubresourceRange subresourceRange;
formatAspectMask, // VkImageAspect aspect;
0u, // deUint32 baseMipLevel;
1u, // deUint32 mipLevels;
0u, // deUint32 baseArraySlice;
1u // deUint32 arraySize;
}
};
// From VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL.
const VkImageMemoryBarrier postImageBarrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
DE_NULL, // const void* pNext;
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
*m_depthImage, // VkImage image;
{ // VkImageSubresourceRange subresourceRange;
formatAspectMask, // VkImageAspect aspect;
0u, // deUint32 baseMipLevel;
1u, // deUint32 mipLevels;
0u, // deUint32 baseArraySlice;
1u // deUint32 arraySize;
}
};
const VkImageSubresourceRange clearRange =
{
clearAspectMask, // VkImageAspectFlags aspectMask;
0u, // deUint32 baseMipLevel;
1u, // deUint32 levelCount;
0u, // deUint32 baseArrayLayer;
1u // deUint32 layerCount;
};
// Clear image and transfer layout.
beginCommandBuffer(vk, *cmdBuffer);
vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
vk.cmdClearDepthStencilImage(*cmdBuffer, *m_depthImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_initialColorDepth.depthStencil, 1, &clearRange);
vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
endCommandBuffer(vk, *cmdBuffer);
submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
}
}
}
// Create render pass.
if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, testParams);
else
m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, testParams);
// Create framebuffer
{
std::vector<VkImageView> imageViews;
for (auto& movePtr : m_colorAttachmentViews)
imageViews.push_back(movePtr.get());
if (hasDepthStencil(m_testParams.depthStencilType))
imageViews.push_back(m_depthAttachmentView.get());
const VkFramebufferCreateInfo framebufferParams =
{
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkFramebufferCreateFlags flags;
*m_renderPass, // VkRenderPass renderPass;
static_cast<deUint32>(imageViews.size()), // deUint32 attachmentCount;
(imageViews.empty() ? DE_NULL : imageViews.data()), // const VkImageView* pAttachments;
kImageWidth, // deUint32 width;
kImageHeight, // deUint32 height;
1u // deUint32 layers;
};
m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
}
// Create pipeline layout for subpass 0.
{
const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams =
{
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkDescriptorSetLayoutCreateFlags flags
0u, // deUint32 bindingCount
DE_NULL // const VkDescriptorSetLayoutBinding* pBindings
};
m_descriptorSetLayout = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
const VkPipelineLayoutCreateInfo pipelineLayoutParams =
{
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineLayoutCreateFlags flags;
1u, // deUint32 setLayoutCount;
&m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
0u, // deUint32 pushConstantRangeCount;
DE_NULL // const VkPushConstantRange* pPushConstantRanges;
};
m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
}
m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert_shader"), 0);
m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag_shader"), 0);
// Create pipeline.
{
const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize));
const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize));
const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
{
VK_FALSE, // VkBool32 blendEnable
VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor
VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor
VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor
VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask
| VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT
| VK_COLOR_COMPONENT_A_BIT
};
std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
for (size_t i = 0; i < testParams.colorUsed.size(); ++i)
colorBlendAttachmentStates.push_back(colorBlendAttachmentState);
const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkPipelineColorBlendStateCreateFlags flags
VK_FALSE, // VkBool32 logicOpEnable
VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp
static_cast<deUint32>(colorBlendAttachmentStates.size()), // deUint32 attachmentCount
(colorBlendAttachmentStates.empty() ? DE_NULL : colorBlendAttachmentStates.data()), // const VkPipelineColorBlendAttachmentState* pAttachments
{ 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
};
m_graphicsPipeline = makeGraphicsPipeline(vk, // const DeviceInterface& vk
vkDevice, // const VkDevice device
*m_pipelineLayout, // const VkPipelineLayout pipelineLayout
*m_vertexShaderModule, // const VkShaderModule vertexShaderModule
DE_NULL, // const VkShaderModule tessellationControlModule
DE_NULL, // const VkShaderModule tessellationEvalModule
DE_NULL, // const VkShaderModule geometryShaderModule
*m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule
*m_renderPass, // const VkRenderPass renderPass
viewports, // const std::vector<VkViewport>& viewports
scissors, // const std::vector<VkRect2D>& scissors
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
0u, // const deUint32 subpass
0u, // const deUint32 patchControlPoints
DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
&colorBlendStateCreateInfo); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
}
// Create command pool
m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
// Create command buffer
if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
else
createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
}
template <typename RenderpassSubpass>
void UnusedClearAttachmentTestInstance::createCommandBuffer (const DeviceInterface& vk,
VkDevice vkDevice)
{
const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo (DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo (DE_NULL);
const VkRenderPassBeginInfo renderPassBeginInfo =
{
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
*m_renderPass, // VkRenderPass renderPass;
*m_framebuffer, // VkFramebuffer framebuffer;
makeRect2D(m_renderSize), // VkRect2D renderArea;
0u, // uint32_t clearValueCount;
DE_NULL // const VkClearValue* pClearValues;
};
m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
const VkClearRect clearRect =
{
{ // VkRect2D rect;
{ 0, 0, }, // VkOffset2D offset;
{ kImageWidth, kImageHeight } // VkExtent2D extent;
},
0u, // uint32_t baseArrayLayer;
1u // uint32_t layerCount;
};
std::vector<VkClearAttachment> clearAttachments;
for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
{
const VkClearAttachment clearAttachment = {
VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
static_cast<deUint32>(i), // uint32_t colorAttachment;
m_clearColor // VkClearValue clearValue;
};
clearAttachments.push_back(clearAttachment);
}
if (hasDepthStencil(m_testParams.depthStencilType))
{
const VkClearAttachment clearAttachment = {
getClearAspectMask(m_testParams.depthStencilType), // VkImageAspectFlags aspectMask;
0u, // uint32_t colorAttachment;
m_clearColorDepth // VkClearValue clearValue;
};
clearAttachments.push_back(clearAttachment);
}
beginCommandBuffer(vk, *m_cmdBuffer, 0u);
RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
vk.cmdClearAttachments(*m_cmdBuffer, static_cast<deUint32>(clearAttachments.size()), (clearAttachments.empty() ? DE_NULL : clearAttachments.data()), 1u, &clearRect);
RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
endCommandBuffer(vk, *m_cmdBuffer);
}
tcu::TestStatus UnusedClearAttachmentTestInstance::iterate (void)
{
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice vkDevice = m_context.getDevice();
const VkQueue queue = m_context.getUniversalQueue();
const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
// Read result images.
std::vector<de::MovePtr<tcu::TextureLevel>> imagePixels;
for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
imagePixels.emplace_back(pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImages[i], FORMAT_COLOR, m_renderSize).release());
// Verify pixel colors match.
for (size_t i = 0; i < imagePixels.size(); ++i)
{
const tcu::ConstPixelBufferAccess& imageAccess = imagePixels[i]->getAccess();
const float* refColor = (m_testParams.colorUsed[i] ? m_clearColor.color.float32 : m_initialColor.color.float32);
for (int y = 0; y < imageAccess.getHeight(); ++y)
for (int x = 0; x < imageAccess.getWidth(); ++x)
{
const tcu::Vec4 color = imageAccess.getPixel(x, y);
for (deUint32 cpnt = 0; cpnt < 4; ++cpnt)
if (de::abs(color[cpnt] - refColor[cpnt]) > 0.01f)
{
std::ostringstream msg;
msg << "Attachment " << i << " with mismatched pixel (" << x << ", " << y << "): expecting pixel value [";
for (deUint32 j = 0; j < 4; ++j)
msg << ((j == 0) ? "" : ", ") << refColor[j];
msg << "] and found [";
for (deUint32 j = 0; j < 4; ++j)
msg << ((j == 0) ? "" : ", ") << color[j];
msg << "]";
return tcu::TestStatus::fail(msg.str());
}
}
}
if (hasDepthStencil(m_testParams.depthStencilType))
{
const bool depthOnly = isDepthOnly(m_testParams.depthStencilType);
const bool stencilOnly = isStencilOnly(m_testParams.depthStencilType);
if (!stencilOnly)
{
de::MovePtr<tcu::TextureLevel> depthPixels = pipeline::readDepthAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage, m_testParams.depthStencilFormat, m_renderSize);
const tcu::ConstPixelBufferAccess& depthAccess = depthPixels->getAccess();
const float refDepth = (m_testParams.depthStencilUsed ? m_clearColorDepth.depthStencil.depth : m_initialColorDepth.depthStencil.depth);
for (int y = 0; y < depthAccess.getHeight(); ++y)
for (int x = 0; x < depthAccess.getWidth(); ++x)
{
const float value = depthAccess.getPixDepth(x, y);
if (de::abs(value - refDepth) > 0.001f)
{
std::ostringstream msg;
msg << "Depth/stencil attachment with mismatched depth value at pixel ("
<< x << ", " << y << "): expected value " << refDepth << " and found " << value;
return tcu::TestStatus::fail(msg.str());
}
}
}
if (!depthOnly)
{
// Note read*Attachment leaves the attachment in the VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL layout, so the current layout
// depends on if we have previously read the depth aspect or not.
const VkImageLayout currentLayout = (stencilOnly ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
de::MovePtr<tcu::TextureLevel> stencilPixels = pipeline::readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage, m_testParams.depthStencilFormat, m_renderSize, currentLayout);
const tcu::ConstPixelBufferAccess& stencilAccess = stencilPixels->getAccess();
const deUint32 refStencil = (m_testParams.depthStencilUsed ? m_clearColorDepth.depthStencil.stencil : m_initialColorDepth.depthStencil.stencil);
for (int y = 0; y < stencilAccess.getHeight(); ++y)
for (int x = 0; x < stencilAccess.getWidth(); ++x)
{
const int value = stencilAccess.getPixStencil(x, y);
if (value < 0 || static_cast<deUint32>(value) != refStencil)
{
std::ostringstream msg;
msg << "Depth/stencil attachment with mismatched stencil value at pixel ("
<< x << ", " << y << "): expected value " << refStencil << " and found " << value;
return tcu::TestStatus::fail(msg.str());
}
}
}
}
return tcu::TestStatus::pass("Pass");
}
using CallbackFunction = std::function<void(const std::vector<deBool>&)>;
void runCallbackOnCombination(std::vector<deBool>& array, size_t current_index, CallbackFunction callback)
{
DE_ASSERT(current_index < array.size());
for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(DE_BOOL_VALUES); ++i)
{
array[current_index] = DE_BOOL_VALUES[i];
if (current_index == array.size() - 1)
callback(array);
else
runCallbackOnCombination(array, current_index + 1, callback);
}
}
void runCallbackOnCombination(std::vector<deBool>& array, CallbackFunction callback)
{
runCallbackOnCombination(array, 0, callback);
}
std::string getUsed(deBool value)
{
return (value ? "used" : "unused");
}
std::string getCombName(const std::vector<deBool>& array)
{
std::ostringstream name;
for (size_t i = 0; i < array.size(); ++i)
name << ((i == 0)? "" : "_") << "color" << getUsed(array[i]);
return name.str();
}
} // anonymous
tcu::TestCaseGroup* createRenderPassUnusedClearAttachmentTests (tcu::TestContext& testCtx, const RenderPassType renderPassType)
{
de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "unused_clear_attachments", "Unused attachments with vkCmdClearAttachments"));
for (int depthStencilType = 0; depthStencilType < DEPTH_STENCIL_MAX_ENUM; ++depthStencilType)
{
const DepthStencilType dsType = static_cast<DepthStencilType>(depthStencilType);
const auto dsFormats = getFormats(dsType);
for (const auto dsFormat : dsFormats)
{
for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(DE_BOOL_VALUES); ++i)
{
const deBool depthStencilUse = DE_BOOL_VALUES[i];
const std::string dsCase = depthStencilTypeName(dsType, dsFormat);
std::vector<TestParams> testTypes;
if (hasDepthStencil(dsType))
testTypes.emplace_back(0, dsType, depthStencilUse, dsFormat, renderPassType); // No color attachments.
testTypes.emplace_back(1, dsType, depthStencilUse, dsFormat, renderPassType); // Single color attachment.
testTypes.emplace_back(COLOR_ATTACHMENTS_NUMBER, dsType, depthStencilUse, dsFormat, renderPassType); // Multiple color attachments.
for (auto& params : testTypes)
{
if (!params.colorUsed.empty())
{
runCallbackOnCombination(params.colorUsed, [&](const std::vector<deBool>& array) {
std::string name = getCombName(array) + "_" + dsCase;
if (hasDepthStencil(dsType))
name += std::string("_") + getUsed(depthStencilUse);
testGroup->addChild(new UnusedClearAttachmentTest(testCtx, name, "", params));
});
}
else
{
std::string name = dsCase + "_" + getUsed(depthStencilUse);
testGroup->addChild(new UnusedClearAttachmentTest(testCtx, name, "", params));
}
}
if (!hasDepthStencil(dsType))
break;
}
}
}
return testGroup.release();
}
} // renderpass
} // vkt