blob: ccbae55e9e30abcfaf5285c1e38098d529651626 [file] [log] [blame]
/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2020 The Khronos Group Inc.
*
* 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 vktSynchronizationNoneStageTests.cpp
* \brief Tests for VK_PIPELINE_STAGE_NONE{_2}_KHR that iterate over each writable layout
and over each readable layout. Data to tested image is writen using method
appropriate for the writable layout and read via readable layout appropriate method.
Betwean read and write operation there are bariers that use none stage.
Implemented tests are also testing generalized layouts (VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR,
VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR) and access flags (MEMORY_ACCESS_READ|WRITE_BIT) to
test contextual synchronization introduced with VK_KHR_synchronization2 extension.
*//*--------------------------------------------------------------------*/
#include "vktSynchronizationNoneStageTests.hpp"
#include "vktSynchronizationOperation.hpp"
#include "vktSynchronizationUtil.hpp"
#include "vktTestCase.hpp"
#include "vkBuilderUtil.hpp"
#include "vkBarrierUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuTestLog.hpp"
#include "tcuStringTemplate.hpp"
#include "deUniquePtr.hpp"
#include <vector>
namespace vkt
{
namespace synchronization
{
using namespace vk;
using namespace de;
using namespace tcu;
namespace
{
static const deUint32 IMAGE_ASPECT_DEPTH_STENCIL = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
static const deUint32 IMAGE_ASPECT_ALL = 0u;
struct TestParams
{
SynchronizationType type;
bool useGenericAccessFlags;
VkImageLayout writeLayout;
VkImageAspectFlags writeAspect;
VkImageLayout readLayout;
VkImageAspectFlags readAspect;
};
// Helper class representing image
class ImageWrapper
{
public:
ImageWrapper () = default;
void create (Context& context, SimpleAllocator& alloc, VkFormat format, VkExtent3D extent, VkImageUsageFlags usage);
public:
Move<VkImage> handle;
MovePtr<Allocation> memory;
};
void ImageWrapper::create(Context& context, SimpleAllocator& alloc, VkFormat format, VkExtent3D extent, VkImageUsageFlags usage)
{
const DeviceInterface& vk = context.getDeviceInterface();
const VkDevice& device = context.getDevice();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const VkImageCreateInfo imageParams
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
DE_NULL, // pNext
0u, // flags
VK_IMAGE_TYPE_2D, // imageType
format, // format
extent, // extent
1u, // mipLevels
1u, // arraySize
VK_SAMPLE_COUNT_1_BIT, // samples
VK_IMAGE_TILING_OPTIMAL, // tiling
usage, // usage
VK_SHARING_MODE_EXCLUSIVE, // sharingMode
1u, // queueFamilyIndexCount
&queueFamilyIndex, // pQueueFamilyIndices
VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
};
handle = createImage(vk, device, &imageParams);
memory = alloc.allocate(getImageMemoryRequirements(vk, device, *handle), MemoryRequirement::Any);
vk.bindImageMemory(device, *handle, memory->getMemory(), memory->getOffset());
}
// Helper class representing buffer
class BufferWrapper
{
public:
BufferWrapper () = default;
void create (Context& context, SimpleAllocator& alloc, VkDeviceSize size, VkBufferUsageFlags usage);
public:
Move<VkBuffer> handle;
MovePtr<Allocation> memory;
};
void BufferWrapper::create(Context& context, SimpleAllocator& alloc, VkDeviceSize size, VkBufferUsageFlags usage)
{
const DeviceInterface& vk = context.getDeviceInterface();
const VkDevice& device = context.getDevice();
const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(size, usage);
handle = createBuffer(vk, device, &bufferCreateInfo);
memory = alloc.allocate(getBufferMemoryRequirements(vk, device, *handle), MemoryRequirement::HostVisible);
VK_CHECK(vk.bindBufferMemory(device, *handle, memory->getMemory(), memory->getOffset()));
}
class NoneStageTestInstance : public vkt::TestInstance
{
public:
NoneStageTestInstance (Context& context,
const TestParams& testParams);
virtual ~NoneStageTestInstance (void) = default;
tcu::TestStatus iterate (void) override;
protected:
VkAccessFlags2KHR getAccessFlag (VkAccessFlags2KHR access);
VkBufferImageCopy buildCopyRegion (VkExtent3D extent,
VkImageAspectFlags aspect);
void buildVertexBuffer (void);
Move<VkRenderPass> buildBasicRenderPass (VkFormat outputFormat,
VkImageLayout outputLayout,
VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE);
Move<VkRenderPass> buildComplexRenderPass (VkFormat intermediateFormat,
VkImageLayout intermediateLayout,
VkFormat outputFormat,
VkImageLayout outputLayout);
Move<VkImageView> buildImageView (VkImage image,
VkFormat format,
const VkImageSubresourceRange& subresourceRange);
Move<VkFramebuffer> buildFramebuffer (VkRenderPass renderPass,
const VkImageView* outView1,
const VkImageView* outView2 = DE_NULL);
Move<VkSampler> buildSampler (void);
Move<VkDescriptorSetLayout> buildDescriptorSetLayout (VkDescriptorType descriptorType);
Move<VkDescriptorPool> buildDescriptorPool (VkDescriptorType descriptorType);
Move<VkDescriptorSet> buildDescriptorSet (VkDescriptorPool descriptorPool,
VkDescriptorSetLayout descriptorSetLayout,
VkDescriptorType descriptorType,
VkImageView inputView,
VkImageLayout inputLayout,
const VkSampler* sampler = DE_NULL);
Move<VkPipeline> buildPipeline (deUint32 subpass,
VkImageAspectFlags resultAspect,
VkPipelineLayout pipelineLayout,
VkShaderModule vertShaderModule,
VkShaderModule fragShaderModule,
VkRenderPass renderPass);
bool verifyResult (const PixelBufferAccess& reference,
const PixelBufferAccess& result);
private:
const TestParams m_testParams;
VkFormat m_referenceImageFormat;
VkFormat m_transitionImageFormat;
VkFormat m_readImageFormat;
VkImageSubresourceRange m_referenceSubresourceRange;
VkImageSubresourceRange m_transitionSubresourceRange;
VkImageSubresourceRange m_readSubresourceRange;
VkImageAspectFlags m_transitionImageAspect;
VkExtent3D m_imageExtent;
VkImageLayout m_writeRenderPassOutputLayout;
// flag indicating that graphics pipeline is constructed to write data to tested image
bool m_usePipelineToWrite;
// flag indicating that graphics pipeline is constructed to read data from tested image
bool m_usePipelineToRead;
// flag indicating that write pipeline should be constructed in a special way to fill stencil buffer
bool m_useStencilDuringWrite;
// flag indicating that read pipeline should be constructed in a special way to use input attachment as a data source
bool m_useInputAttachmentToRead;
VkPipelineStageFlags2KHR m_srcStageToNoneStageMask;
VkAccessFlags2KHR m_srcAccessToNoneAccessMask;
VkPipelineStageFlags2KHR m_dstStageFromNoneStageMask;
VkAccessFlags2KHR m_dstAccessFromNoneAccessMask;
SimpleAllocator m_alloc;
ImageWrapper m_referenceImage;
VkImageUsageFlags m_referenceImageUsage;
// objects/variables initialized only when needed
ImageWrapper m_imageToWrite;
VkImageUsageFlags m_imageToWriteUsage;
ImageWrapper m_imageToRead;
BufferWrapper m_vertexBuffer;
std::vector<Move<VkImageView> > m_attachmentViews;
std::string m_writeFragShaderName;
Move<VkShaderModule> m_writeVertShaderModule;
Move<VkShaderModule> m_writeFragShaderModule;
Move<VkRenderPass> m_writeRenderPass;
Move<VkSampler> m_writeSampler;
Move<VkDescriptorSetLayout> m_writeDescriptorSetLayout;
Move<VkDescriptorPool> m_writeDescriptorPool;
Move<VkDescriptorSet> m_writeDescriptorSet;
Move<VkPipelineLayout> m_writePipelineLayout;
Move<VkPipeline> m_writePipeline;
Move<VkFramebuffer> m_writeFramebuffer;
std::string m_readFragShaderName;
Move<VkShaderModule> m_readVertShaderModule;
Move<VkShaderModule> m_readFragShaderModule;
Move<VkShaderModule> m_readFragShaderModule2;
Move<VkRenderPass> m_readRenderPass;
Move<VkSampler> m_readSampler;
Move<VkDescriptorSetLayout> m_readDescriptorSetLayout;
Move<VkDescriptorPool> m_readDescriptorPool;
Move<VkDescriptorSet> m_readDescriptorSet;
Move<VkPipelineLayout> m_readPipelineLayout;
Move<VkPipeline> m_readPipeline;
Move<VkFramebuffer> m_readFramebuffer;
};
NoneStageTestInstance::NoneStageTestInstance(Context& context, const TestParams& testParams)
: vkt::TestInstance(context)
, m_testParams (testParams)
, m_imageExtent { 32, 32, 1 }
, m_alloc (m_context.getDeviceInterface(),
m_context.getDevice(),
getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()))
{
// note: for clarity whole configuration of whats going on in iterate method was moved here
const auto writeLayout = m_testParams.writeLayout;
const auto writeAspect = m_testParams.writeAspect;
const auto readLayout = m_testParams.readLayout;
const auto readAspect = m_testParams.readAspect;
// select format that will be used for test
if ((writeAspect == VK_IMAGE_ASPECT_DEPTH_BIT) || (readAspect == VK_IMAGE_ASPECT_DEPTH_BIT))
{
m_transitionImageFormat = VK_FORMAT_D32_SFLOAT;
m_transitionImageAspect = VK_IMAGE_ASPECT_DEPTH_BIT;
m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
}
else if ((writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) || (readAspect == VK_IMAGE_ASPECT_STENCIL_BIT))
{
m_transitionImageFormat = VK_FORMAT_S8_UINT;
m_transitionImageAspect = VK_IMAGE_ASPECT_STENCIL_BIT;
m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
}
else if ((writeAspect == IMAGE_ASPECT_DEPTH_STENCIL) || (readAspect == IMAGE_ASPECT_DEPTH_STENCIL))
{
m_transitionImageFormat = VK_FORMAT_D24_UNORM_S8_UINT;
// note: in test we focus only on depth aspect; no need to check both in those cases
m_transitionImageAspect = VK_IMAGE_ASPECT_DEPTH_BIT;
m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
}
else
{
m_transitionImageFormat = VK_FORMAT_R8G8B8A8_UNORM;
m_transitionImageAspect = VK_IMAGE_ASPECT_COLOR_BIT;
m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
m_referenceSubresourceRange = { m_transitionImageAspect, 0u, 1u, 0u, 1u };
m_transitionSubresourceRange = { m_transitionImageAspect, 0u, 1u, 0u, 1u };
m_readSubresourceRange = { m_transitionImageAspect, 0u, 1u, 0u, 1u };
m_referenceImageFormat = m_transitionImageFormat;
m_readImageFormat = m_transitionImageFormat;
m_referenceImageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
m_imageToWriteUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
// pipeline is not created for transfer and general layouts (general layouts in tests follow same path as transfer layouts)
m_usePipelineToWrite = (writeLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) && (writeLayout != VK_IMAGE_LAYOUT_GENERAL);
m_usePipelineToRead = (readLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) && (readLayout != VK_IMAGE_LAYOUT_GENERAL);
m_useStencilDuringWrite = false;
m_srcStageToNoneStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
m_srcAccessToNoneAccessMask = getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR);
m_dstStageFromNoneStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
m_dstAccessFromNoneAccessMask = getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR);
// when graphics pipelines are not created only image with gradient is used for test
if (!m_usePipelineToWrite && !m_usePipelineToRead)
{
m_referenceImageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
return;
}
if (m_usePipelineToWrite)
{
// depth/stencil layouts need diferent configuration
if (writeAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
{
if (writeAspect & VK_IMAGE_ASPECT_DEPTH_BIT)
{
m_referenceImageFormat = VK_FORMAT_R32_SFLOAT;
m_referenceImageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
m_referenceSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
m_writeFragShaderName = "frag-color-to-depth";
}
else
{
m_referenceImageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
m_useStencilDuringWrite = true;
m_writeFragShaderName = "frag-color-to-stencil";
}
m_srcStageToNoneStageMask = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR;
m_srcAccessToNoneAccessMask = getAccessFlag(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR);
m_imageToWriteUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
}
else
{
m_referenceImageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
m_srcStageToNoneStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR;
m_srcAccessToNoneAccessMask = getAccessFlag(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR);
m_writeFragShaderName = "frag-color";
m_imageToWriteUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
}
if (m_usePipelineToRead)
{
m_dstStageFromNoneStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR;
m_dstAccessFromNoneAccessMask = getAccessFlag(VK_ACCESS_2_SHADER_READ_BIT_KHR);
m_readSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
if ((readAspect | writeAspect) & VK_IMAGE_ASPECT_DEPTH_BIT)
m_readImageFormat = VK_FORMAT_R32_SFLOAT;
else if ((readAspect | writeAspect) & VK_IMAGE_ASPECT_STENCIL_BIT)
m_readImageFormat = VK_FORMAT_R8_UINT;
// for layouts that operate on depth or stencil (not depth_stencil) use input attachment to read
if ((readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) && (readAspect != IMAGE_ASPECT_DEPTH_STENCIL))
{
m_useInputAttachmentToRead = true;
m_readFragShaderName = "frag-depth-or-stencil-to-color";
m_imageToWriteUsage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
m_dstAccessFromNoneAccessMask = getAccessFlag(VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR);
if (!m_usePipelineToWrite)
m_referenceImageUsage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
}
else // use image sampler for color and depth_stencil layouts
{
m_useInputAttachmentToRead = false;
m_readFragShaderName = "frag-color";
m_referenceImageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
m_imageToWriteUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
// for depth_stencil layouts we need to have depth_stencil_attachment usage
if (!m_usePipelineToWrite && (readAspect & VK_IMAGE_ASPECT_STENCIL_BIT))
m_referenceImageUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
// when we read stencil as color we need to use usampler2D
if (writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT)
m_readFragShaderName = "frag-stencil-to-color";
}
}
}
VkAccessFlags2KHR NoneStageTestInstance::getAccessFlag(VkAccessFlags2KHR access)
{
if (m_testParams.useGenericAccessFlags)
{
switch (access)
{
case VK_ACCESS_2_HOST_READ_BIT_KHR:
case VK_ACCESS_2_TRANSFER_READ_BIT_KHR:
case VK_ACCESS_2_SHADER_READ_BIT_KHR:
case VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR:
return VK_ACCESS_2_MEMORY_READ_BIT_KHR;
case VK_ACCESS_2_HOST_WRITE_BIT_KHR:
case VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR:
case VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR:
case VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR:
return VK_ACCESS_2_MEMORY_WRITE_BIT_KHR;
default:
TCU_THROW(TestError, "Unhandled access flag");
}
}
return access;
}
VkBufferImageCopy NoneStageTestInstance::buildCopyRegion(VkExtent3D extent, VkImageAspectFlags aspect)
{
return
{
0u, // VkDeviceSize bufferOffset
extent.width, // deUint32 bufferRowLength
extent.height, // deUint32 bufferImageHeight
{ aspect, 0u, 0u, 1u }, // VkImageSubresourceLayers imageSubresource
{ 0, 0, 0 }, // VkOffset3D imageOffset
extent // VkExtent3D imageExtent
};
}
void NoneStageTestInstance::buildVertexBuffer()
{
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice& device = m_context.getDevice();
std::vector<float> vertices
{
1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 1.0f,
};
m_vertexBuffer.create(m_context, m_alloc, sizeof(float) * vertices.size(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
deMemcpy(m_vertexBuffer.memory->getHostPtr(), vertices.data(), vertices.size() * sizeof(float));
flushAlloc(vk, device, *m_vertexBuffer.memory);
}
Move<VkRenderPass> NoneStageTestInstance::buildBasicRenderPass(VkFormat outputFormat, VkImageLayout outputLayout, VkAttachmentLoadOp loadOp)
{
// output color/depth attachment
VkAttachmentDescription2 attachmentDescription
{
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType
DE_NULL, // const void* pNext
(VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
outputFormat, // VkFormat format
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
loadOp, // VkAttachmentLoadOp loadOp
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
loadOp, // VkAttachmentLoadOp stencilLoadOp
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
outputLayout // VkImageLayout finalLayout
};
VkImageAspectFlags imageAspect = getImageAspectFlags(mapVkFormat(outputFormat));
VkAttachmentReference2 attachmentRef
{
VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, DE_NULL, 0u, outputLayout, imageAspect
};
VkAttachmentReference2* pColorAttachment = DE_NULL;
VkAttachmentReference2* pDepthStencilAttachment = DE_NULL;
if (imageAspect == VK_IMAGE_ASPECT_COLOR_BIT)
pColorAttachment = &attachmentRef;
else
pDepthStencilAttachment = &attachmentRef;
VkSubpassDescription2 subpassDescription
{
VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
DE_NULL,
(VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
0u, // deUint32 viewMask
0u, // deUint32 inputAttachmentCount
DE_NULL, // const VkAttachmentReference2* pInputAttachments
!!pColorAttachment, // deUint32 colorAttachmentCount
pColorAttachment, // const VkAttachmentReference2* pColorAttachments
DE_NULL, // const VkAttachmentReference2* pResolveAttachments
pDepthStencilAttachment, // const VkAttachmentReference2* pDepthStencilAttachment
0u, // deUint32 preserveAttachmentCount
DE_NULL // const deUint32* pPreserveAttachments
};
const VkRenderPassCreateInfo2 renderPassInfo
{
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
DE_NULL, // const void* pNext
(VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
1u, // deUint32 attachmentCount
&attachmentDescription, // 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 vk::createRenderPass2(m_context.getDeviceInterface(), m_context.getDevice(), &renderPassInfo);;
}
Move<VkRenderPass> NoneStageTestInstance::buildComplexRenderPass(VkFormat intermediateFormat, VkImageLayout intermediateLayout,
VkFormat outputFormat, VkImageLayout outputLayout)
{
std::vector<VkAttachmentDescription2> attachmentDescriptions
{
// depth/stencil attachment (when used in read pipeline it loads data filed in write pipeline)
{
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType
DE_NULL, // const void* pNext
(VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
intermediateFormat, // 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_STORE, // VkAttachmentStoreOp stencilStoreOp
intermediateLayout, // VkImageLayout initialLayout
intermediateLayout // VkImageLayout finalLayout
},
// color attachment
{
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType
DE_NULL, // const void* pNext
(VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
outputFormat, // VkFormat format
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // 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_UNDEFINED, // VkImageLayout initialLayout
outputLayout // VkImageLayout finalLayout
}
};
VkImageAspectFlags intermediateAspect = getImageAspectFlags(mapVkFormat(intermediateFormat));
VkImageAspectFlags outputAspect = getImageAspectFlags(mapVkFormat(outputFormat));
std::vector<VkAttachmentReference2> attachmentRefs
{
{ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, DE_NULL, 0u, intermediateLayout, intermediateAspect },
{ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, DE_NULL, 1u, outputLayout, outputAspect }
};
VkAttachmentReference2* pDepthStencilAttachment = &attachmentRefs[0];
VkAttachmentReference2* pColorAttachment = &attachmentRefs[1];
std::vector<VkSubpassDescription2> subpassDescriptions
{
{
VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
DE_NULL,
(VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
0u, // deUint32 viewMask
1u, // deUint32 inputAttachmentCount
pDepthStencilAttachment, // const VkAttachmentReference2* pInputAttachments
1u, // deUint32 colorAttachmentCount
pColorAttachment, // const VkAttachmentReference2* pColorAttachments
DE_NULL, // const VkAttachmentReference2* pResolveAttachments
DE_NULL, // const VkAttachmentReference2* pDepthStencilAttachment
0u, // deUint32 preserveAttachmentCount
DE_NULL // deUint32* pPreserveAttachments
}
};
const VkRenderPassCreateInfo2 renderPassInfo
{
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
DE_NULL, // const void* pNext
(VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
(deUint32)attachmentDescriptions.size(), // deUint32 attachmentCount
attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments
(deUint32)subpassDescriptions.size(), // deUint32 subpassCount
subpassDescriptions.data(), // const VkSubpassDescription* pSubpasses
0u, // deUint32 dependencyCount
DE_NULL, // const VkSubpassDependency* pDependencies
0u, // deUint32 correlatedViewMaskCount
DE_NULL // const deUint32* pCorrelatedViewMasks
};
return vk::createRenderPass2(m_context.getDeviceInterface(), m_context.getDevice(), &renderPassInfo);
}
Move<VkImageView> NoneStageTestInstance::buildImageView(VkImage image, VkFormat format, const VkImageSubresourceRange& subresourceRange)
{
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice& device = m_context.getDevice();
const VkImageViewCreateInfo imageViewParams
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkImageViewCreateFlags flags
image, // VkImage image
VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType
format, // VkFormat format
makeComponentMappingRGBA(), // VkComponentMapping components
subresourceRange, // VkImageSubresourceRange subresourceRange
};
return createImageView(vk, device, &imageViewParams);
}
Move<VkFramebuffer> NoneStageTestInstance::buildFramebuffer(VkRenderPass renderPass, const VkImageView* outView1, const VkImageView* outView2)
{
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice& device = m_context.getDevice();
std::vector<VkImageView> imageViews = { *outView1 };
if (outView2)
imageViews.push_back(*outView2);
const VkFramebufferCreateInfo framebufferParams
{
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkFramebufferCreateFlags flags
renderPass, // VkRenderPass renderPass
(deUint32)imageViews.size(), // deUint32 attachmentCount
imageViews.data(), // const VkImageView* pAttachments
m_imageExtent.width, // deUint32 width
m_imageExtent.height, // deUint32 height
1u, // deUint32 layers
};
return createFramebuffer(vk, device, &framebufferParams);
}
Move<VkSampler> NoneStageTestInstance::buildSampler()
{
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice& device = m_context.getDevice();
const VkSamplerCreateInfo samplerInfo
{
VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkSamplerCreateFlags flags
VK_FILTER_NEAREST, // VkFilter magFilter
VK_FILTER_NEAREST, // VkFilter minFilter
VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW
0.0f, // float mipLodBias
VK_FALSE, // VkBool32 anisotropyEnable
1.0f, // float maxAnisotropy
DE_FALSE, // VkBool32 compareEnable
VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp
0.0f, // float minLod
0.0f, // float maxLod
VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor
VK_FALSE, // VkBool32 unnormalizedCoords
};
return createSampler(vk, device, &samplerInfo);
}
Move<VkDescriptorSetLayout> NoneStageTestInstance::buildDescriptorSetLayout(VkDescriptorType descriptorType)
{
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice& device = m_context.getDevice();
return
DescriptorSetLayoutBuilder()
.addSingleSamplerBinding(descriptorType, VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL)
.build(vk, device);
}
Move<VkDescriptorPool> NoneStageTestInstance::buildDescriptorPool(VkDescriptorType descriptorType)
{
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice& device = m_context.getDevice();
return
DescriptorPoolBuilder()
.addType(descriptorType, 1u)
.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
}
Move<VkDescriptorSet> NoneStageTestInstance::buildDescriptorSet(VkDescriptorPool descriptorPool,
VkDescriptorSetLayout descriptorSetLayout,
VkDescriptorType descriptorType,
VkImageView inputView,
VkImageLayout inputLayout,
const VkSampler* sampler)
{
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice& device = m_context.getDevice();
const VkDescriptorImageInfo inputImageInfo = makeDescriptorImageInfo(sampler ? *sampler : 0u, inputView, inputLayout);
Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout);
DescriptorSetUpdateBuilder()
.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &inputImageInfo)
.update(vk, device);
return descriptorSet;
}
Move<VkPipeline> NoneStageTestInstance::buildPipeline(deUint32 subpass,
VkImageAspectFlags resultAspect,
VkPipelineLayout pipelineLayout,
VkShaderModule vertShaderModule,
VkShaderModule fragShaderModule,
VkRenderPass renderPass)
{
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice& device = m_context.getDevice();
const std::vector<VkViewport> viewports { makeViewport(m_imageExtent) };
const std::vector<VkRect2D> scissors { makeRect2D(m_imageExtent) };
const bool useDepth = resultAspect & VK_IMAGE_ASPECT_DEPTH_BIT;
const bool useStencil = resultAspect & VK_IMAGE_ASPECT_STENCIL_BIT;
const VkStencilOpState stencilOpState = makeStencilOpState(
VK_STENCIL_OP_REPLACE, // stencil fail
VK_STENCIL_OP_REPLACE, // depth & stencil pass
VK_STENCIL_OP_REPLACE, // depth only fail
VK_COMPARE_OP_ALWAYS, // compare op
1u, // compare mask
1u, // write mask
1u); // reference
const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo
{
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
(VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags
useDepth, // VkBool32 depthTestEnable
useDepth, // VkBool32 depthWriteEnable
VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp
VK_FALSE, // VkBool32 depthBoundsTestEnable
useStencil, // VkBool32 stencilTestEnable
stencilOpState, // VkStencilOpState front
stencilOpState, // VkStencilOpState back
0.0f, // float minDepthBounds
1.0f, // float maxDepthBounds
};
return makeGraphicsPipeline(
vk, // DeviceInterface& vk
device, // VkDevice device
pipelineLayout, // VkPipelineLayout pipelineLayout
vertShaderModule, // VkShaderModule vertexShaderModule
DE_NULL, // VkShaderModule tessellationControlModule
DE_NULL, // VkShaderModule tessellationEvalModule
DE_NULL, // VkShaderModule geometryShaderModule
fragShaderModule, // VkShaderModule fragmentShaderModule
renderPass, // VkRenderPass renderPass
viewports, // std::vector<VkViewport>& viewports
scissors, // std::vector<VkRect2D>& scissors
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology
subpass, // deUint32 subpass
0u, // deUint32 patchControlPoints
DE_NULL, // VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
DE_NULL, // VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
DE_NULL, // VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
&depthStencilStateCreateInfo); // VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
}
tcu::TestStatus NoneStageTestInstance::iterate(void)
{
const DeviceInterface& vk = m_context.getDeviceInterface();
const VkDevice& device = m_context.getDevice();
const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
VkQueue queue = m_context.getUniversalQueue();
Move<VkCommandPool> cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
Move<VkCommandBuffer> cmdBuffer = makeCommandBuffer(vk, device, *cmdPool);
const VkDeviceSize vertexBufferOffset = 0;
ImageWrapper* transitionImagePtr = &m_referenceImage;
ImageWrapper* imageToVerifyPtr = &m_referenceImage;
const deUint32 imageSizeInBytes = m_imageExtent.width * m_imageExtent.height * 4;
SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_testParams.type, vk, false);
const VkRect2D renderArea = makeRect2D(0, 0, m_imageExtent.width, m_imageExtent.height);
const VkBufferImageCopy transitionCopyRegion = buildCopyRegion(m_imageExtent, m_transitionImageAspect);
const VkBufferImageCopy colorCopyRegion = buildCopyRegion(m_imageExtent, VK_IMAGE_ASPECT_COLOR_BIT);
// create image that will have gradient (without data atm)
m_referenceImage.create(m_context, m_alloc, m_referenceImageFormat, m_imageExtent, m_referenceImageUsage);
// create buffer used for gradient data source
BufferWrapper srcBuffer;
srcBuffer.create(m_context, m_alloc, imageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
// generate gradient
std::vector<deUint32> referenceData (m_imageExtent.width * m_imageExtent.height);
tcu::TextureFormat referenceFormat (mapVkFormat(m_referenceImageFormat));
PixelBufferAccess referencePBA (referenceFormat, m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth, referenceData.data());
fillWithComponentGradients(referencePBA, tcu::Vec4(0.0f), tcu::Vec4(1.0f));
deMemcpy(srcBuffer.memory->getHostPtr(), referenceData.data(), static_cast<size_t>(imageSizeInBytes));
flushAlloc(vk, device, *srcBuffer.memory);
// create buffer for result transfer
BufferWrapper dstBuffer;
tcu::TextureFormat resultFormat (mapVkFormat(m_readImageFormat));
dstBuffer.create(m_context, m_alloc, imageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
if (m_usePipelineToWrite || m_usePipelineToRead)
{
buildVertexBuffer();
// create image view for reference image (its always at index 0)
m_attachmentViews.push_back(buildImageView(*m_referenceImage.handle, m_referenceImageFormat, m_referenceSubresourceRange));
// create graphics pipeline used to write image data
if (m_usePipelineToWrite)
{
// create image that will be used as attachment to write to
m_imageToWrite.create(m_context, m_alloc, m_transitionImageFormat, m_imageExtent, m_imageToWriteUsage);
m_attachmentViews.push_back(buildImageView(*m_imageToWrite.handle, m_transitionImageFormat, m_transitionSubresourceRange));
m_writeVertShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
m_writeFragShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get(m_writeFragShaderName), 0);
if (m_useStencilDuringWrite)
{
// this is used only for cases where writable layout is VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL
// in this case generated gradient is only used for verification
m_writeRenderPass = buildBasicRenderPass(m_transitionImageFormat, m_writeRenderPassOutputLayout, VK_ATTACHMENT_LOAD_OP_CLEAR);
m_writePipelineLayout = makePipelineLayout(vk, device, DE_NULL);
m_writePipeline = buildPipeline(0u, m_transitionImageAspect, *m_writePipelineLayout,
*m_writeVertShaderModule, *m_writeFragShaderModule, *m_writeRenderPass);
m_writeFramebuffer = buildFramebuffer(*m_writeRenderPass, &m_attachmentViews[1].get());
}
else
{
m_writeRenderPass = buildBasicRenderPass(m_transitionImageFormat, m_writeRenderPassOutputLayout);
m_writeSampler = buildSampler();
m_writeDescriptorSetLayout = buildDescriptorSetLayout(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
m_writeDescriptorPool = buildDescriptorPool(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
m_writeDescriptorSet = buildDescriptorSet(*m_writeDescriptorPool, *m_writeDescriptorSetLayout, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
*m_attachmentViews[0], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, &m_writeSampler.get());
m_writePipelineLayout = makePipelineLayout(vk, device, *m_writeDescriptorSetLayout);
m_writePipeline = buildPipeline(0u, m_transitionImageAspect, *m_writePipelineLayout,
*m_writeVertShaderModule, *m_writeFragShaderModule, *m_writeRenderPass);
m_writeFramebuffer = buildFramebuffer(*m_writeRenderPass, &m_attachmentViews[1].get());
}
transitionImagePtr = &m_imageToWrite;
imageToVerifyPtr = &m_imageToWrite;
}
// create graphics pipeline used to read image data
if (m_usePipelineToRead)
{
m_imageToRead.create(m_context, m_alloc, m_readImageFormat, m_imageExtent, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
m_attachmentViews.push_back(buildImageView(*m_imageToRead.handle, m_readImageFormat, m_readSubresourceRange));
imageToVerifyPtr = &m_imageToRead;
m_readVertShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
m_readFragShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get(m_readFragShaderName), 0);
if (m_useInputAttachmentToRead)
{
m_readDescriptorSetLayout = buildDescriptorSetLayout(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
m_readDescriptorPool = buildDescriptorPool(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
m_readDescriptorSet = buildDescriptorSet(*m_readDescriptorPool, *m_readDescriptorSetLayout, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
*m_attachmentViews[m_usePipelineToWrite], m_testParams.readLayout);
m_readRenderPass = buildComplexRenderPass(m_transitionImageFormat, m_testParams.readLayout,
m_readImageFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
m_readFramebuffer = buildFramebuffer(*m_readRenderPass, &m_attachmentViews[m_usePipelineToWrite].get(),
&m_attachmentViews[m_usePipelineToWrite+1].get());
m_readPipelineLayout = makePipelineLayout(vk, device, *m_readDescriptorSetLayout);
m_readPipeline = buildPipeline(0u, VK_IMAGE_ASPECT_COLOR_BIT, *m_readPipelineLayout,
*m_readVertShaderModule, *m_readFragShaderModule, *m_readRenderPass);
}
else
{
m_readSampler = buildSampler();
m_readDescriptorSetLayout = buildDescriptorSetLayout(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
m_readDescriptorPool = buildDescriptorPool(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
m_readDescriptorSet = buildDescriptorSet(*m_readDescriptorPool, *m_readDescriptorSetLayout, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
*m_attachmentViews[m_usePipelineToWrite], m_testParams.readLayout, &m_readSampler.get());
m_readRenderPass = buildBasicRenderPass(m_readImageFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
m_readFramebuffer = buildFramebuffer(*m_readRenderPass, &m_attachmentViews[m_usePipelineToWrite + 1].get());
m_readPipelineLayout = makePipelineLayout(vk, device, *m_readDescriptorSetLayout);
m_readPipeline = buildPipeline(0u, m_transitionImageAspect, *m_readPipelineLayout,
*m_readVertShaderModule, *m_readFragShaderModule, *m_readRenderPass);
}
}
}
beginCommandBuffer(vk, *cmdBuffer);
// write data from buffer with gradient to image (for stencil_attachment cases we dont need to do that)
if (!m_useStencilDuringWrite)
{
// wait for reference data to be in buffer
const VkBufferMemoryBarrier2KHR preBufferMemoryBarrier2 = makeBufferMemoryBarrier2(
VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
getAccessFlag(VK_ACCESS_2_HOST_WRITE_BIT_KHR), // VkAccessFlags2KHR srcAccessMask
VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
getAccessFlag(VK_ACCESS_2_TRANSFER_READ_BIT_KHR), // VkAccessFlags2KHR dstAccessMask
*srcBuffer.handle, // VkBuffer buffer
0u, // VkDeviceSize offset
imageSizeInBytes // VkDeviceSize size
);
VkImageLayout copyBufferToImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
if(m_testParams.writeLayout == VK_IMAGE_LAYOUT_GENERAL)
copyBufferToImageLayout = VK_IMAGE_LAYOUT_GENERAL;
// change image layout so that we can copy to it data from buffer
const VkImageMemoryBarrier2KHR preImageMemoryBarrier2 = makeImageMemoryBarrier2(
VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR srcAccessMask
VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR dstAccessMask
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
copyBufferToImageLayout, // VkImageLayout newLayout
*m_referenceImage.handle, // VkImage image
m_referenceSubresourceRange // VkImageSubresourceRange subresourceRange
);
VkDependencyInfoKHR buffDependencyInfo = makeCommonDependencyInfo(DE_NULL, &preBufferMemoryBarrier2, &preImageMemoryBarrier2);
synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &buffDependencyInfo);
const VkBufferImageCopy* copyRegion = m_usePipelineToWrite ? &colorCopyRegion : &transitionCopyRegion;
vk.cmdCopyBufferToImage(*cmdBuffer, *srcBuffer.handle, *m_referenceImage.handle, copyBufferToImageLayout, 1u, copyRegion);
}
if (m_usePipelineToWrite)
{
// wait till data is transfered to image (in all cases except when stencil_attachment is tested)
if (!m_useStencilDuringWrite)
{
const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR srcAccessMask
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
getAccessFlag(VK_ACCESS_2_SHADER_READ_BIT_KHR), // VkAccessFlags2KHR dstAccessMask
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout
*m_referenceImage.handle, // VkImage image
m_referenceSubresourceRange // VkImageSubresourceRange subresourceRange
);
VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo);
}
beginRenderPass(vk, *cmdBuffer, *m_writeRenderPass, *m_writeFramebuffer, renderArea, tcu::Vec4(0.0f ,0.0f, 0.0f, 1.0f));
vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_writePipeline);
vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &m_vertexBuffer.handle.get(), &vertexBufferOffset);
if (m_useStencilDuringWrite)
{
// when writing to stencil buffer draw single triangle (to simulate gradient over 1bit)
vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
}
else
{
vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_writePipelineLayout, 0, 1, &m_writeDescriptorSet.get(), 0, DE_NULL);
vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
}
endRenderPass(vk, *cmdBuffer);
}
// use none stage to wait till data is transfered to image
{
const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
m_srcStageToNoneStageMask, // VkPipelineStageFlags2KHR srcStageMask
m_srcAccessToNoneAccessMask, // VkAccessFlags2KHR srcAccessMask
VK_PIPELINE_STAGE_2_NONE_KHR, // VkPipelineStageFlags2KHR dstStageMask
VK_ACCESS_2_NONE_KHR, // VkAccessFlags2KHR dstAccessMask
m_testParams.writeLayout, // VkImageLayout oldLayout
m_testParams.writeLayout, // VkImageLayout newLayout
*transitionImagePtr->handle, // VkImage image
m_transitionSubresourceRange // VkImageSubresourceRange subresourceRange
);
VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo);
}
// use all commands stage to change image layout
{
const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
VK_ACCESS_2_NONE_KHR, // VkAccessFlags2KHR srcAccessMask
m_dstStageFromNoneStageMask, // VkPipelineStageFlags2KHR dstStageMask
m_dstAccessFromNoneAccessMask, // VkAccessFlags2KHR dstAccessMask
m_testParams.writeLayout, // VkImageLayout oldLayout
m_testParams.readLayout, // VkImageLayout newLayout
*transitionImagePtr->handle, // VkImage image
m_transitionSubresourceRange // VkImageSubresourceRange subresourceRange
);
VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo);
}
VkImageLayout copyImageToBufferLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
if (m_testParams.readLayout == VK_IMAGE_LAYOUT_GENERAL)
copyImageToBufferLayout = VK_IMAGE_LAYOUT_GENERAL;
if (m_usePipelineToRead)
{
beginRenderPass(vk, *cmdBuffer, *m_readRenderPass, *m_readFramebuffer, renderArea);
vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_readPipeline);
vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_readPipelineLayout, 0, 1, &m_readDescriptorSet.get(), 0, DE_NULL);
vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &m_vertexBuffer.handle.get(), &vertexBufferOffset);
vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
endRenderPass(vk, *cmdBuffer);
// wait till data is transfered to image
const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
getAccessFlag(VK_ACCESS_2_TRANSFER_READ_BIT_KHR), // VkAccessFlags2KHR dstAccessMask
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout
copyImageToBufferLayout, // VkImageLayout newLayout
*imageToVerifyPtr->handle, // VkImage image
m_readSubresourceRange // VkImageSubresourceRange subresourceRange
);
VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo);
}
// read back image
{
const VkBufferImageCopy* copyRegion = m_usePipelineToRead ? &colorCopyRegion : &transitionCopyRegion;
vk.cmdCopyImageToBuffer(*cmdBuffer, *imageToVerifyPtr->handle, copyImageToBufferLayout, *dstBuffer.handle, 1u, copyRegion);
const VkBufferMemoryBarrier2KHR postBufferMemoryBarrier2 = makeBufferMemoryBarrier2(
VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR srcAccessMask
VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
getAccessFlag(VK_ACCESS_2_HOST_READ_BIT_KHR), // VkAccessFlags2KHR dstAccessMask
*dstBuffer.handle, // VkBuffer buffer
0u, // VkDeviceSize offset
imageSizeInBytes // VkDeviceSize size
);
VkDependencyInfoKHR bufDependencyInfo = makeCommonDependencyInfo(DE_NULL, &postBufferMemoryBarrier2);
synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &bufDependencyInfo);
}
endCommandBuffer(vk, *cmdBuffer);
Move<VkFence> fence = createFence(vk, device);
VkCommandBufferSubmitInfoKHR cmdBuffersInfo = makeCommonCommandBufferSubmitInfo(*cmdBuffer);
synchronizationWrapper->addSubmitInfo(0u, DE_NULL, 1u, &cmdBuffersInfo, 0u, DE_NULL);
VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
VK_CHECK(vk.waitForFences(device, 1, &fence.get(), VK_TRUE, ~0ull));
// read image data
invalidateAlloc(vk, device, *dstBuffer.memory);
PixelBufferAccess resultPBA(resultFormat, m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth, dstBuffer.memory->getHostPtr());
// if result/reference is depth-stencil format then focus only on depth component
if (isCombinedDepthStencilType(referenceFormat.type))
referencePBA = getEffectiveDepthStencilAccess(referencePBA, tcu::Sampler::MODE_DEPTH);
if (isCombinedDepthStencilType(resultFormat.type))
resultPBA = getEffectiveDepthStencilAccess(resultPBA, tcu::Sampler::MODE_DEPTH);
if (verifyResult(referencePBA, resultPBA))
return TestStatus::pass("Pass");
return TestStatus::fail("Fail");
}
bool NoneStageTestInstance::verifyResult(const PixelBufferAccess& reference, const PixelBufferAccess& result)
{
TestLog& log = m_context.getTestContext().getLog();
if (isIntFormat(m_referenceImageFormat) || isUintFormat(m_referenceImageFormat))
{
// special case for stencil (1bit gradient - top-left of image is 0, bottom-right is 1)
bool isResultCorrect = true;
TextureLevel errorMaskStorage(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8),
m_imageExtent.width, m_imageExtent.height, 1);
PixelBufferAccess errorMask = errorMaskStorage.getAccess();
for (deUint32 y = 0; y < m_imageExtent.height; y++)
for (deUint32 x = 0; x < m_imageExtent.width; x++)
{
// skip textels on diagonal (gradient lights texels on diagonal and stencil operation in test does not)
if ((x + y) == (m_imageExtent.width - 1))
{
errorMask.setPixel(IVec4(0, 0xff, 0, 0xff), x, y, 0);
continue;
}
IVec4 refPix = reference.getPixelInt(x, y, 0);
IVec4 cmpPix = result.getPixelInt(x, y, 0);
bool isOk = (refPix[0] == cmpPix[0]);
errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, 0);
isResultCorrect &= isOk;
}
Vec4 pixelBias(0.0f);
Vec4 pixelScale(1.0f);
if (isResultCorrect)
{
log << TestLog::ImageSet("Image comparison", "")
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
<< TestLog::EndImageSet;
return true;
}
log << TestLog::ImageSet("Image comparison", "")
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
<< TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
<< TestLog::Image("ErrorMask", "Error mask", errorMask)
<< TestLog::EndImageSet;
return false;
}
return floatThresholdCompare(log, "Image comparison", "", reference, result, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
}
class NoneStageTestCase : public vkt::TestCase
{
public:
NoneStageTestCase (tcu::TestContext& testContext,
const std::string& name,
const TestParams& testParams);
~NoneStageTestCase (void) = default;
void initPrograms (SourceCollections& sourceCollections) const override;
TestInstance* createInstance (Context& context) const override;
void checkSupport (Context& context) const override;
private:
const TestParams m_testParams;
};
NoneStageTestCase::NoneStageTestCase(tcu::TestContext& testContext, const std::string& name, const TestParams& testParams)
: vkt::TestCase (testContext, name, "")
, m_testParams (testParams)
{
}
void NoneStageTestCase::initPrograms(SourceCollections& sourceCollections) const
{
const auto writeLayout = m_testParams.writeLayout;
const auto writeAspect = m_testParams.writeAspect;
const auto readLayout = m_testParams.readLayout;
const auto readAspect = m_testParams.readAspect;
// for tests that use only transfer and general layouts we don't create pipeline
if (((writeLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) || (readLayout == VK_IMAGE_LAYOUT_GENERAL)) &&
((writeLayout == VK_IMAGE_LAYOUT_GENERAL) || (readLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)))
return;
sourceCollections.glslSources.add("vert") << glu::VertexSource(
"#version 450\n"
"layout(location = 0) in vec4 inPosition;\n"
"layout(location = 0) out vec2 outUV;\n"
"void main(void)\n"
"{\n"
" outUV = vec2(inPosition.x * 0.5 + 0.5, inPosition.y * 0.5 + 0.5);\n"
" gl_Position = inPosition;\n"
"}\n"
);
sourceCollections.glslSources.add("frag-color") << glu::FragmentSource(
"#version 450\n"
"layout(binding = 0) uniform sampler2D u_sampler;\n"
"layout(location = 0) in vec2 inUV;\n"
"layout(location = 0) out vec4 fragColor;\n"
"void main(void)\n"
"{\n"
" fragColor = texture(u_sampler, inUV);\n"
"}\n"
);
if (writeAspect & VK_IMAGE_ASPECT_DEPTH_BIT)
{
sourceCollections.glslSources.add("frag-color-to-depth") << glu::FragmentSource(
"#version 450\n"
"layout(binding = 0) uniform sampler2D u_sampler;\n"
"layout(location = 0) in vec2 inUV;\n"
"void main(void)\n"
"{\n"
" gl_FragDepth = texture(u_sampler, inUV).r;\n"
"}\n"
);
}
if (writeAspect & VK_IMAGE_ASPECT_STENCIL_BIT)
{
sourceCollections.glslSources.add("frag-color-to-stencil") << glu::FragmentSource(
"#version 450\n"
"void main(void)\n"
"{\n"
"}\n"
);
if ((readLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) ||
((readLayout == VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR) && (readAspect == IMAGE_ASPECT_ALL)))
{
// use usampler2D and uvec4 for color
sourceCollections.glslSources.add("frag-stencil-to-color") << glu::FragmentSource(
"#version 450\n"
"layout(binding = 0) uniform usampler2D u_sampler;\n"
"layout(location = 0) in vec2 inUV;\n"
"layout(location = 0) out uvec4 fragColor;\n"
"void main(void)\n"
"{\n"
" fragColor = texture(u_sampler, inUV);\n"
"}\n"
);
}
}
if (readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
{
// for stencil only cases we need to use usubpassInput (for depth and depth_stencil we need to use subpassInput)
const bool readDepth = readAspect & VK_IMAGE_ASPECT_DEPTH_BIT;
const std::map<std::string, std::string> specializations
{
{ "SUBPASS_INPUT", (readDepth ? "subpassInput" : "usubpassInput") },
{ "VALUE_TYPE", (readDepth ? "float" : "uint") }
};
std::string source =
"#version 450\n"
"layout (input_attachment_index = 0, binding = 0) uniform ${SUBPASS_INPUT} depthOrStencilInput;\n"
"layout(location = 0) in vec2 inUV;\n"
"layout(location = 0) out ${VALUE_TYPE} fragColor;\n"
"void main (void)\n"
"{\n"
" fragColor = subpassLoad(depthOrStencilInput).x;\n"
"}\n";
sourceCollections.glslSources.add("frag-depth-or-stencil-to-color")
<< glu::FragmentSource(tcu::StringTemplate(source).specialize(specializations));
}
}
TestInstance* NoneStageTestCase::createInstance(Context& context) const
{
return new NoneStageTestInstance(context, m_testParams);
}
void NoneStageTestCase::checkSupport(Context& context) const
{
context.requireDeviceFunctionality("VK_KHR_synchronization2");
const auto writeAspect = m_testParams.writeAspect;
const auto readAspect = m_testParams.readAspect;
// check whether implementation supports separate depth/stencil layouts
if (((writeAspect == VK_IMAGE_ASPECT_DEPTH_BIT) && (readAspect == VK_IMAGE_ASPECT_DEPTH_BIT)) ||
((writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) && (readAspect == VK_IMAGE_ASPECT_STENCIL_BIT)))
{
if(!context.getSeparateDepthStencilLayoutsFeatures().separateDepthStencilLayouts)
TCU_THROW(NotSupportedError, "Implementation does not support separateDepthStencilLayouts");
}
const auto writeLayout = m_testParams.writeLayout;
const auto readLayout = m_testParams.readLayout;
bool usePipelineToWrite = (writeLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) && (writeLayout != VK_IMAGE_LAYOUT_GENERAL);
bool usePipelineToRead = (readLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) && (readLayout != VK_IMAGE_LAYOUT_GENERAL);
if (!usePipelineToWrite && !usePipelineToRead)
return;
VkFormat transitionImageFormat = VK_FORMAT_R8G8B8A8_UNORM;
if ((writeAspect == VK_IMAGE_ASPECT_DEPTH_BIT) || (readAspect == VK_IMAGE_ASPECT_DEPTH_BIT))
transitionImageFormat = VK_FORMAT_D32_SFLOAT;
else if ((writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) || (readAspect == VK_IMAGE_ASPECT_STENCIL_BIT))
transitionImageFormat = VK_FORMAT_S8_UINT;
else if ((writeAspect == IMAGE_ASPECT_DEPTH_STENCIL) || (readAspect == IMAGE_ASPECT_DEPTH_STENCIL))
transitionImageFormat = VK_FORMAT_D24_UNORM_S8_UINT;
struct FormatToCheck
{
VkFormat format;
VkImageUsageFlags usage;
};
std::vector<FormatToCheck> formatsToCheck
{
// reference image
{ transitionImageFormat, (VkImageUsageFlags)VK_IMAGE_USAGE_TRANSFER_DST_BIT },
// image to write
{ transitionImageFormat, (VkImageUsageFlags)VK_IMAGE_USAGE_TRANSFER_SRC_BIT }
};
// note: conditions here are analogic to conditions in test case constructor
// everything not needed was cout out leaving only logic related to
// m_referenceImage and m_imageToWrite
if (usePipelineToWrite)
{
if (writeAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
{
if (writeAspect & VK_IMAGE_ASPECT_DEPTH_BIT)
{
formatsToCheck[0].format = VK_FORMAT_R32_SFLOAT;
formatsToCheck[0].usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
}
else
formatsToCheck[0].usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
formatsToCheck[1].usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
}
else
{
formatsToCheck[0].usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
formatsToCheck[1].usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
}
if (usePipelineToRead)
{
// for layouts that operate on depth or stencil (not depth_stencil) use input attachment to read
if ((readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) && (readAspect != IMAGE_ASPECT_DEPTH_STENCIL))
{
formatsToCheck[1].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
if (!usePipelineToWrite)
formatsToCheck[0].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
}
else // use image sampler for color and depth_stencil layouts
{
formatsToCheck[0].usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
// for depth_stencil layouts we need to have depth_stencil_attachment usage
if (!usePipelineToWrite && (readAspect & VK_IMAGE_ASPECT_STENCIL_BIT))
formatsToCheck[0].usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
}
}
// it simplifies logic to pop image to write then to add conditions everywhere above
if (!usePipelineToWrite)
formatsToCheck.pop_back();
for (const auto& formatData : formatsToCheck)
{
VkImageFormatProperties properties;
const vk::InstanceInterface& vki = context.getInstanceInterface();
if (vki.getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(),
formatData.format,
VK_IMAGE_TYPE_2D,
VK_IMAGE_TILING_OPTIMAL,
formatData.usage,
0,
&properties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
{
std::string error = std::string("Format (") +
vk::getFormatName(formatData.format) + ") doesn't support required capabilities.";
TCU_THROW(NotSupportedError, error.c_str());
}
}
}
} // anonymous
tcu::TestCaseGroup* createNoneStageTests(tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> noneStageTests(new tcu::TestCaseGroup(testCtx, "none_stage", ""));
struct LayoutData
{
VkImageLayout token;
VkImageAspectFlags aspect;
std::string name;
};
const std::vector<LayoutData> writableLayoutsData
{
{ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, IMAGE_ASPECT_ALL, "transfer_dst" },
{ VK_IMAGE_LAYOUT_GENERAL, IMAGE_ASPECT_ALL, "general" },
{ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, "color_attachment" },
{ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL, "depth_stencil_attachment" },
{ VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT, "depth_attachment" },
{ VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_STENCIL_BIT, "stencil_attachment" },
{ VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_ASPECT_COLOR_BIT, "generic_color_attachment" },
{ VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_ASPECT_DEPTH_BIT, "generic_depth_attachment" },
{ VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_ASPECT_STENCIL_BIT, "generic_stencil_attachment" },
{ VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, IMAGE_ASPECT_DEPTH_STENCIL, "generic_depth_stencil_attachment" },
};
const std::vector<LayoutData> readableLayoutsData
{
{ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, IMAGE_ASPECT_ALL, "transfer_src" },
{ VK_IMAGE_LAYOUT_GENERAL, IMAGE_ASPECT_ALL, "general" },
{ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, IMAGE_ASPECT_ALL, "shader_read" },
{ VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL, "depth_stencil_read" },
{ VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL, "depth_read_stencil_attachment" },
{ VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL, "depth_attachment_stencil_read" },
{ VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT, "depth_read" },
{ VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_STENCIL_BIT, "stencil_read" },
{ VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, IMAGE_ASPECT_ALL, "generic_color_read" },
{ VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_ASPECT_DEPTH_BIT, "generic_depth_read" },
{ VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_ASPECT_STENCIL_BIT, "generic_stencil_read" },
{ VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, IMAGE_ASPECT_DEPTH_STENCIL, "generic_depth_stencil_read" },
};
struct SynchronizationData
{
SynchronizationType type;
std::string casePrefix;
bool useGenericAccessFlags;
};
std::vector<SynchronizationData> synchronizationData
{
{ SynchronizationType::SYNCHRONIZATION2, "", true },
{ SynchronizationType::SYNCHRONIZATION2, "old_access_", false },
// using legacy synchronization structures with NONE_STAGE
{ SynchronizationType::LEGACY, "legacy_", false }
};
for (const auto& syncData : synchronizationData)
{
for (const auto& writeData : writableLayoutsData)
{
for (const auto& readData : readableLayoutsData)
{
if (readData.aspect && writeData.aspect &&
(readData.aspect != writeData.aspect))
continue;
const std::string name = syncData.casePrefix + writeData.name + "_to_" + readData.name;
noneStageTests->addChild(new NoneStageTestCase(testCtx, name, {
syncData.type,
syncData.useGenericAccessFlags,
writeData.token,
writeData.aspect,
readData.token,
readData.aspect
}));
}
}
}
return noneStageTests.release();
}
} // synchronization
} // vkt