blob: c92d71e5dac89ae957bc2b9fe8e2c951d835c9ab [file] [log] [blame]
/*-------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2015 Google 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
* \brief RenderPass tests
*//*--------------------------------------------------------------------*/
#include "vktRenderPassTests.hpp"
#include "vktRenderPassTestsUtil.hpp"
#include "vktRenderPassMultisampleTests.hpp"
#include "vktRenderPassMultisampleResolveTests.hpp"
#include "vktRenderPassSampleReadTests.hpp"
#include "vktRenderPassSparseRenderTargetTests.hpp"
#include "vktRenderPassSubpassDependencyTests.hpp"
#include "vktRenderPassUnusedAttachmentTests.hpp"
#include "vktRenderPassUnusedClearAttachmentTests.hpp"
#include "vktRenderPassDepthStencilResolveTests.hpp"
#include "vktRenderPassUnusedAttachmentSparseFillingTests.hpp"
#include "vktRenderPassFragmentDensityMapTests.hpp"
#include "vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.hpp"
#include "vktRenderPassLoadStoreOpNoneTests.hpp"
#include "vktDynamicRenderingTests.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktTestGroupUtil.hpp"
#include "vkDefs.hpp"
#include "vkDeviceUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkPlatform.hpp"
#include "vkPrograms.hpp"
#include "vkQueryUtil.hpp"
#include "vkRef.hpp"
#include "vkRefUtil.hpp"
#include "vkStrUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"
#include "tcuFloat.hpp"
#include "tcuFormatUtil.hpp"
#include "tcuMaybe.hpp"
#include "tcuResultCollector.hpp"
#include "tcuTestLog.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuVectorUtil.hpp"
#include "deRandom.hpp"
#include "deSTLUtil.hpp"
#include "deSharedPtr.hpp"
#include "deStringUtil.hpp"
#include "deUniquePtr.hpp"
#include <limits>
#include <set>
#include <string>
#include <vector>
#include <memory>
using namespace vk;
using tcu::BVec4;
using tcu::IVec2;
using tcu::IVec4;
using tcu::UVec2;
using tcu::UVec4;
using tcu::Vec2;
using tcu::Vec4;
using tcu::Maybe;
using tcu::just;
using tcu::nothing;
using tcu::ConstPixelBufferAccess;
using tcu::PixelBufferAccess;
using tcu::TestLog;
using de::UniquePtr;
using std::pair;
using std::set;
using std::string;
using std::vector;
namespace vkt
{
namespace
{
using namespace renderpass;
typedef vector<deUint8> DepthValuesArray;
static const deUint8 DEPTH_VALUES[] = { 0u, 255u, 1u };
enum AllocationKind
{
ALLOCATION_KIND_SUBALLOCATED,
ALLOCATION_KIND_DEDICATED,
};
struct TestConfigExternal
{
TestConfigExternal (AllocationKind allocationKind_,
RenderingType renderingType_)
: allocationKind (allocationKind_)
, renderingType (renderingType_)
{
}
AllocationKind allocationKind;
RenderingType renderingType;
};
de::MovePtr<Allocation> allocateBuffer (const InstanceInterface& vki,
const DeviceInterface& vkd,
const VkPhysicalDevice& physDevice,
const VkDevice device,
const VkBuffer& buffer,
const MemoryRequirement requirement,
Allocator& allocator,
AllocationKind allocationKind)
{
switch (allocationKind)
{
case ALLOCATION_KIND_SUBALLOCATED:
{
const VkMemoryRequirements memoryRequirements = getBufferMemoryRequirements(vkd, device, buffer);
return allocator.allocate(memoryRequirements, requirement);
}
case ALLOCATION_KIND_DEDICATED:
{
return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement);
}
default:
{
TCU_THROW(InternalError, "Invalid allocation kind");
}
}
}
de::MovePtr<Allocation> allocateImage (const InstanceInterface& vki,
const DeviceInterface& vkd,
const VkPhysicalDevice& physDevice,
const VkDevice device,
const VkImage& image,
const MemoryRequirement requirement,
Allocator& allocator,
AllocationKind allocationKind)
{
switch (allocationKind)
{
case ALLOCATION_KIND_SUBALLOCATED:
{
const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vkd, device, image);
return allocator.allocate(memoryRequirements, requirement);
}
case ALLOCATION_KIND_DEDICATED:
{
return allocateDedicated(vki, vkd, physDevice, device, image, requirement);
}
default:
{
TCU_THROW(InternalError, "Invalid allocation kind");
}
}
}
enum BoolOp
{
BOOLOP_AND,
BOOLOP_OR,
BOOLOP_EQ,
BOOLOP_NEQ
};
const char* boolOpToString (BoolOp op)
{
switch (op)
{
case BOOLOP_OR:
return "||";
case BOOLOP_AND:
return "&&";
case BOOLOP_EQ:
return "==";
case BOOLOP_NEQ:
return "!=";
default:
DE_FATAL("Unknown boolean operation.");
return DE_NULL;
}
}
bool performBoolOp (BoolOp op, bool a, bool b)
{
switch (op)
{
case BOOLOP_OR:
return a || b;
case BOOLOP_AND:
return a && b;
case BOOLOP_EQ:
return a == b;
case BOOLOP_NEQ:
return a != b;
default:
DE_FATAL("Unknown boolean operation.");
return false;
}
}
BoolOp boolOpFromIndex (size_t index)
{
const BoolOp ops[] =
{
BOOLOP_OR,
BOOLOP_AND,
BOOLOP_EQ,
BOOLOP_NEQ
};
return ops[index % DE_LENGTH_OF_ARRAY(ops)];
}
static float requiredDepthEpsilon(VkFormat format)
{
// Possible precision loss in the unorm depth pipeline means that we need to check depths
// that go in and back out of the depth buffer with an epsilon rather than an exact match
deUint32 unormBits = 0;
switch (format)
{
case VK_FORMAT_D16_UNORM:
unormBits = 16;
break;
case VK_FORMAT_X8_D24_UNORM_PACK32:
case VK_FORMAT_D24_UNORM_S8_UINT:
unormBits = 24;
break;
case VK_FORMAT_D32_SFLOAT:
case VK_FORMAT_D32_SFLOAT_S8_UINT:
default:
unormBits = 0;
break;
}
if (unormBits > 0)
return 1.0f / (float)((1 << unormBits) - 1);
return 0.0f; // Require exact match
}
static bool depthsEqual(float a, float b, float epsilon)
{
return fabs(a - b) <= epsilon;
}
Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vk,
VkDevice device,
VkFramebufferCreateFlags pCreateInfo_flags,
VkRenderPass pCreateInfo_renderPass,
deUint32 pCreateInfo_attachmentCount,
const VkImageView* pCreateInfo_pAttachments,
deUint32 pCreateInfo_width,
deUint32 pCreateInfo_height,
deUint32 pCreateInfo_layers)
{
const VkFramebufferCreateInfo pCreateInfo =
{
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
DE_NULL,
pCreateInfo_flags,
pCreateInfo_renderPass,
pCreateInfo_attachmentCount,
pCreateInfo_pAttachments,
pCreateInfo_width,
pCreateInfo_height,
pCreateInfo_layers,
};
return createFramebuffer(vk, device, &pCreateInfo);
}
Move<VkImage> createImage (const DeviceInterface& vk,
VkDevice device,
VkImageCreateFlags pCreateInfo_flags,
VkImageType pCreateInfo_imageType,
VkFormat pCreateInfo_format,
VkExtent3D pCreateInfo_extent,
deUint32 pCreateInfo_mipLevels,
deUint32 pCreateInfo_arrayLayers,
VkSampleCountFlagBits pCreateInfo_samples,
VkImageTiling pCreateInfo_tiling,
VkImageUsageFlags pCreateInfo_usage,
VkSharingMode pCreateInfo_sharingMode,
deUint32 pCreateInfo_queueFamilyCount,
const deUint32* pCreateInfo_pQueueFamilyIndices,
VkImageLayout pCreateInfo_initialLayout)
{
const VkImageCreateInfo pCreateInfo =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
DE_NULL,
pCreateInfo_flags,
pCreateInfo_imageType,
pCreateInfo_format,
pCreateInfo_extent,
pCreateInfo_mipLevels,
pCreateInfo_arrayLayers,
pCreateInfo_samples,
pCreateInfo_tiling,
pCreateInfo_usage,
pCreateInfo_sharingMode,
pCreateInfo_queueFamilyCount,
pCreateInfo_pQueueFamilyIndices,
pCreateInfo_initialLayout
};
return createImage(vk, device, &pCreateInfo);
}
void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
{
VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
}
void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
{
VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
}
Move<VkImageView> createImageView (const DeviceInterface& vk,
VkDevice device,
VkImageViewCreateFlags pCreateInfo_flags,
VkImage pCreateInfo_image,
VkImageViewType pCreateInfo_viewType,
VkFormat pCreateInfo_format,
VkComponentMapping pCreateInfo_components,
VkImageSubresourceRange pCreateInfo_subresourceRange)
{
const VkImageViewCreateInfo pCreateInfo =
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
DE_NULL,
pCreateInfo_flags,
pCreateInfo_image,
pCreateInfo_viewType,
pCreateInfo_format,
pCreateInfo_components,
pCreateInfo_subresourceRange,
};
return createImageView(vk, device, &pCreateInfo);
}
Move<VkBuffer> createBuffer (const DeviceInterface& vk,
VkDevice device,
VkBufferCreateFlags pCreateInfo_flags,
VkDeviceSize pCreateInfo_size,
VkBufferUsageFlags pCreateInfo_usage,
VkSharingMode pCreateInfo_sharingMode,
deUint32 pCreateInfo_queueFamilyCount,
const deUint32* pCreateInfo_pQueueFamilyIndices)
{
const VkBufferCreateInfo pCreateInfo =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
DE_NULL,
pCreateInfo_flags,
pCreateInfo_size,
pCreateInfo_usage,
pCreateInfo_sharingMode,
pCreateInfo_queueFamilyCount,
pCreateInfo_pQueueFamilyIndices,
};
return createBuffer(vk, device, &pCreateInfo);
}
VkRenderPassBeginInfo createRenderPassBeginInfo (VkRenderPass pRenderPassBegin_renderPass,
VkFramebuffer pRenderPassBegin_framebuffer,
VkRect2D pRenderPassBegin_renderArea,
deUint32 pRenderPassBegin_clearValueCount,
const VkClearValue* pRenderPassBegin_pAttachmentClearValues)
{
const VkRenderPassBeginInfo renderPassBeginInfo =
{
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
DE_NULL,
pRenderPassBegin_renderPass,
pRenderPassBegin_framebuffer,
pRenderPassBegin_renderArea,
pRenderPassBegin_clearValueCount,
pRenderPassBegin_pAttachmentClearValues,
};
return renderPassBeginInfo;
}
void queueSubmit (const DeviceInterface& vk, VkQueue queue, deUint32 cmdBufferCount, const VkCommandBuffer* pCmdBuffers, VkFence fence)
{
const VkSubmitInfo submitInfo =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO,
DE_NULL,
0u, // waitSemaphoreCount
(const VkSemaphore*)DE_NULL, // pWaitSemaphores
(const VkPipelineStageFlags*)DE_NULL,
cmdBufferCount, // commandBufferCount
pCmdBuffers,
0u, // signalSemaphoreCount
(const VkSemaphore*)DE_NULL, // pSignalSemaphores
};
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence));
}
void waitForFences (const DeviceInterface& vk, VkDevice device, deUint32 fenceCount, const VkFence* pFences, VkBool32 waitAll, deUint64 timeout)
{
VK_CHECK(vk.waitForFences(device, fenceCount, pFences, waitAll, timeout));
}
VkImageAspectFlags getImageAspectFlags (VkFormat vkFormat)
{
const tcu::TextureFormat format = mapVkFormat(vkFormat);
DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 22);
switch (format.order)
{
case tcu::TextureFormat::DS:
return VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
case tcu::TextureFormat::D:
return VK_IMAGE_ASPECT_DEPTH_BIT;
case tcu::TextureFormat::S:
return VK_IMAGE_ASPECT_STENCIL_BIT;
default:
return VK_IMAGE_ASPECT_COLOR_BIT;
}
}
VkAccessFlags getAllMemoryReadFlags (void)
{
return VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_UNIFORM_READ_BIT
| VK_ACCESS_HOST_READ_BIT
| VK_ACCESS_INDEX_READ_BIT
| VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
| VK_ACCESS_INDIRECT_COMMAND_READ_BIT
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
| VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
}
VkAccessFlags getAllMemoryWriteFlags (void)
{
return VK_ACCESS_TRANSFER_WRITE_BIT
| VK_ACCESS_HOST_WRITE_BIT
| VK_ACCESS_SHADER_WRITE_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
}
VkAccessFlags getMemoryFlagsForLayout (const VkImageLayout layout)
{
switch (layout)
{
case VK_IMAGE_LAYOUT_GENERAL: return getAllMemoryReadFlags() | getAllMemoryWriteFlags();
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: return VK_ACCESS_SHADER_READ_BIT;
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: return VK_ACCESS_TRANSFER_READ_BIT;
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: return VK_ACCESS_TRANSFER_WRITE_BIT;
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
default:
return (VkAccessFlags)0;
}
}
VkPipelineStageFlags getAllPipelineStageFlags (void)
{
/* All relevant flags for a pipeline containing VS+PS. */
return VK_PIPELINE_STAGE_TRANSFER_BIT
| VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
| VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
| VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
| VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
| VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
| VK_PIPELINE_STAGE_HOST_BIT;
}
class AttachmentReference
{
public:
AttachmentReference (deUint32 attachment,
VkImageLayout layout,
VkImageAspectFlags aspectMask = static_cast<VkImageAspectFlags>(0u))
: m_attachment (attachment)
, m_layout (layout)
, m_aspectMask (aspectMask)
{
}
deUint32 getAttachment (void) const { return m_attachment; }
VkImageLayout getImageLayout (void) const { return m_layout; }
VkImageAspectFlags getAspectMask (void) const { return m_aspectMask; }
void setImageLayout (VkImageLayout layout) { m_layout = layout; }
private:
deUint32 m_attachment;
VkImageLayout m_layout;
VkImageAspectFlags m_aspectMask;
};
class Subpass
{
public:
Subpass (VkPipelineBindPoint pipelineBindPoint,
VkSubpassDescriptionFlags flags,
const vector<AttachmentReference>& inputAttachments,
const vector<AttachmentReference>& colorAttachments,
const vector<AttachmentReference>& resolveAttachments,
AttachmentReference depthStencilAttachment,
const vector<deUint32>& preserveAttachments,
bool omitBlendState = false)
: m_pipelineBindPoint (pipelineBindPoint)
, m_flags (flags)
, m_inputAttachments (inputAttachments)
, m_colorAttachments (colorAttachments)
, m_resolveAttachments (resolveAttachments)
, m_depthStencilAttachment (depthStencilAttachment)
, m_preserveAttachments (preserveAttachments)
, m_omitBlendState (omitBlendState)
{
}
VkPipelineBindPoint getPipelineBindPoint (void) const { return m_pipelineBindPoint; }
VkSubpassDescriptionFlags getFlags (void) const { return m_flags; }
const vector<AttachmentReference>& getInputAttachments (void) const { return m_inputAttachments; }
const vector<AttachmentReference>& getColorAttachments (void) const { return m_colorAttachments; }
const vector<AttachmentReference>& getResolveAttachments (void) const { return m_resolveAttachments; }
const AttachmentReference& getDepthStencilAttachment (void) const { return m_depthStencilAttachment; }
const vector<deUint32>& getPreserveAttachments (void) const { return m_preserveAttachments; }
bool getOmitBlendState (void) const { return m_omitBlendState; }
private:
VkPipelineBindPoint m_pipelineBindPoint;
VkSubpassDescriptionFlags m_flags;
vector<AttachmentReference> m_inputAttachments;
vector<AttachmentReference> m_colorAttachments;
vector<AttachmentReference> m_resolveAttachments;
AttachmentReference m_depthStencilAttachment;
vector<deUint32> m_preserveAttachments;
bool m_omitBlendState;
};
class SubpassDependency
{
public:
SubpassDependency (deUint32 srcPass,
deUint32 dstPass,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkAccessFlags srcAccessMask,
VkAccessFlags dstAccessMask,
VkDependencyFlags flags)
: m_srcPass (srcPass)
, m_dstPass (dstPass)
, m_srcStageMask (srcStageMask)
, m_dstStageMask (dstStageMask)
, m_srcAccessMask (srcAccessMask)
, m_dstAccessMask (dstAccessMask)
, m_flags (flags)
{
}
deUint32 getSrcPass (void) const { return m_srcPass; }
deUint32 getDstPass (void) const { return m_dstPass; }
VkPipelineStageFlags getSrcStageMask (void) const { return m_srcStageMask; }
VkPipelineStageFlags getDstStageMask (void) const { return m_dstStageMask; }
VkAccessFlags getSrcAccessMask (void) const { return m_srcAccessMask; }
VkAccessFlags getDstAccessMask (void) const { return m_dstAccessMask; }
VkDependencyFlags getFlags (void) const { return m_flags; }
void setSrcAccessMask (const VkAccessFlags& flags) { m_srcAccessMask = flags; }
void setDstAccessMask (const VkAccessFlags& flags) { m_dstAccessMask = flags; }
private:
deUint32 m_srcPass;
deUint32 m_dstPass;
VkPipelineStageFlags m_srcStageMask;
VkPipelineStageFlags m_dstStageMask;
VkAccessFlags m_srcAccessMask;
VkAccessFlags m_dstAccessMask;
VkDependencyFlags m_flags;
};
class Attachment
{
public:
Attachment (VkFormat format,
VkSampleCountFlagBits samples,
VkAttachmentLoadOp loadOp,
VkAttachmentStoreOp storeOp,
VkAttachmentLoadOp stencilLoadOp,
VkAttachmentStoreOp stencilStoreOp,
VkImageLayout initialLayout,
VkImageLayout finalLayout)
: m_format (format)
, m_samples (samples)
, m_loadOp (loadOp)
, m_storeOp (storeOp)
, m_stencilLoadOp (stencilLoadOp)
, m_stencilStoreOp (stencilStoreOp)
, m_initialLayout (initialLayout)
, m_finalLayout (finalLayout)
{
}
VkFormat getFormat (void) const { return m_format; }
VkSampleCountFlagBits getSamples (void) const { return m_samples; }
VkAttachmentLoadOp getLoadOp (void) const { return m_loadOp; }
VkAttachmentStoreOp getStoreOp (void) const { return m_storeOp; }
VkAttachmentLoadOp getStencilLoadOp (void) const { return m_stencilLoadOp; }
VkAttachmentStoreOp getStencilStoreOp (void) const { return m_stencilStoreOp; }
VkImageLayout getInitialLayout (void) const { return m_initialLayout; }
VkImageLayout getFinalLayout (void) const { return m_finalLayout; }
private:
VkFormat m_format;
VkSampleCountFlagBits m_samples;
VkAttachmentLoadOp m_loadOp;
VkAttachmentStoreOp m_storeOp;
VkAttachmentLoadOp m_stencilLoadOp;
VkAttachmentStoreOp m_stencilStoreOp;
VkImageLayout m_initialLayout;
VkImageLayout m_finalLayout;
};
class RenderPass
{
public:
RenderPass (const vector<Attachment>& attachments,
const vector<Subpass>& subpasses,
const vector<SubpassDependency>& dependencies,
const vector<VkInputAttachmentAspectReference> inputAspects = vector<VkInputAttachmentAspectReference>())
: m_attachments (attachments)
, m_subpasses (subpasses)
, m_dependencies (dependencies)
, m_inputAspects (inputAspects)
{
}
const vector<Attachment>& getAttachments (void) const { return m_attachments; }
const vector<Subpass>& getSubpasses (void) const { return m_subpasses; }
const vector<SubpassDependency>& getDependencies (void) const { return m_dependencies; }
const vector<VkInputAttachmentAspectReference>& getInputAspects (void) const { return m_inputAspects; }
private:
const vector<Attachment> m_attachments;
const vector<Subpass> m_subpasses;
const vector<SubpassDependency> m_dependencies;
const vector<VkInputAttachmentAspectReference> m_inputAspects;
};
struct TestConfig
{
enum RenderTypes
{
RENDERTYPES_NONE = 0,
RENDERTYPES_CLEAR = (1<<1),
RENDERTYPES_DRAW = (1<<2)
};
enum CommandBufferTypes
{
COMMANDBUFFERTYPES_INLINE = (1<<0),
COMMANDBUFFERTYPES_SECONDARY = (1<<1)
};
enum ImageMemory
{
IMAGEMEMORY_STRICT = (1<<0),
IMAGEMEMORY_LAZY = (1<<1)
};
TestConfig (const RenderPass& renderPass_,
RenderTypes renderTypes_,
CommandBufferTypes commandBufferTypes_,
ImageMemory imageMemory_,
const UVec2& targetSize_,
const UVec2& renderPos_,
const UVec2& renderSize_,
deBool useFormatCompCount_,
deUint32 seed_,
deUint32 drawStartNdx_,
AllocationKind allocationKind_,
RenderingType renderingType_,
vector<DeviceCoreFeature> requiredFeatures_ = vector<DeviceCoreFeature>())
: renderPass (renderPass_)
, renderTypes (renderTypes_)
, commandBufferTypes (commandBufferTypes_)
, imageMemory (imageMemory_)
, targetSize (targetSize_)
, renderPos (renderPos_)
, renderSize (renderSize_)
, useFormatCompCount (useFormatCompCount_)
, seed (seed_)
, drawStartNdx (drawStartNdx_)
, allocationKind (allocationKind_)
, renderingType (renderingType_)
, requiredFeatures (requiredFeatures_)
{
DepthValuesArray shuffledDepthValues (&DEPTH_VALUES[0], &DEPTH_VALUES[DE_LENGTH_OF_ARRAY(DEPTH_VALUES)]);
de::Random rng (seed + 1);
rng.shuffle(shuffledDepthValues.begin(), shuffledDepthValues.end());
depthValues.push_back(shuffledDepthValues[0]);
depthValues.push_back(shuffledDepthValues[1]);
}
RenderPass renderPass;
RenderTypes renderTypes;
CommandBufferTypes commandBufferTypes;
ImageMemory imageMemory;
UVec2 targetSize;
UVec2 renderPos;
UVec2 renderSize;
deBool useFormatCompCount;
deUint32 seed;
deUint32 drawStartNdx;
AllocationKind allocationKind;
RenderingType renderingType;
vector<DeviceCoreFeature> requiredFeatures;
DepthValuesArray depthValues;
};
TestConfig::RenderTypes operator| (TestConfig::RenderTypes a, TestConfig::RenderTypes b)
{
return (TestConfig::RenderTypes)(((deUint32)a) | ((deUint32)b));
}
TestConfig::CommandBufferTypes operator| (TestConfig::CommandBufferTypes a, TestConfig::CommandBufferTypes b)
{
return (TestConfig::CommandBufferTypes)(((deUint32)a) | ((deUint32)b));
}
TestConfig::ImageMemory operator| (TestConfig::ImageMemory a, TestConfig::ImageMemory b)
{
return (TestConfig::ImageMemory)(((deUint32)a) | ((deUint32)b));
}
void checkSupport (Context& context, TestConfig config)
{
for (size_t featureNdx = 0; featureNdx < config.requiredFeatures.size(); featureNdx++)
context.requireDeviceCoreFeature(config.requiredFeatures[featureNdx]);
}
void logRenderPassInfo (TestLog& log,
const RenderPass& renderPass)
{
const bool useExternalInputAspect = !renderPass.getInputAspects().empty();
const tcu::ScopedLogSection section (log, "RenderPass", "RenderPass");
{
const tcu::ScopedLogSection attachmentsSection (log, "Attachments", "Attachments");
const vector<Attachment>& attachments = renderPass.getAttachments();
for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
{
const tcu::ScopedLogSection attachmentSection (log, "Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx));
const Attachment& attachment = attachments[attachmentNdx];
log << TestLog::Message << "Format: " << attachment.getFormat() << TestLog::EndMessage;
log << TestLog::Message << "Samples: " << attachment.getSamples() << TestLog::EndMessage;
log << TestLog::Message << "LoadOp: " << attachment.getLoadOp() << TestLog::EndMessage;
log << TestLog::Message << "StoreOp: " << attachment.getStoreOp() << TestLog::EndMessage;
log << TestLog::Message << "StencilLoadOp: " << attachment.getStencilLoadOp() << TestLog::EndMessage;
log << TestLog::Message << "StencilStoreOp: " << attachment.getStencilStoreOp() << TestLog::EndMessage;
log << TestLog::Message << "InitialLayout: " << attachment.getInitialLayout() << TestLog::EndMessage;
log << TestLog::Message << "FinalLayout: " << attachment.getFinalLayout() << TestLog::EndMessage;
}
}
if (useExternalInputAspect)
{
const tcu::ScopedLogSection inputAspectSection (log, "InputAspects", "InputAspects");
for (size_t aspectNdx = 0; aspectNdx < renderPass.getInputAspects().size(); aspectNdx++)
{
const VkInputAttachmentAspectReference& inputAspect (renderPass.getInputAspects()[aspectNdx]);
log << TestLog::Message << "Subpass: " << inputAspect.subpass << TestLog::EndMessage;
log << TestLog::Message << "InputAttachmentIndex: " << inputAspect.inputAttachmentIndex << TestLog::EndMessage;
log << TestLog::Message << "AspectFlags: " << getImageAspectFlagsStr(inputAspect.aspectMask) << TestLog::EndMessage;
}
}
{
const tcu::ScopedLogSection subpassesSection (log, "Subpasses", "Subpasses");
const vector<Subpass>& subpasses = renderPass.getSubpasses();
for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
{
const tcu::ScopedLogSection subpassSection (log, "Subpass" + de::toString(subpassNdx), "Subpass " + de::toString(subpassNdx));
const Subpass& subpass = subpasses[subpassNdx];
const vector<AttachmentReference>& inputAttachments = subpass.getInputAttachments();
const vector<AttachmentReference>& colorAttachments = subpass.getColorAttachments();
const vector<AttachmentReference>& resolveAttachments = subpass.getResolveAttachments();
const vector<deUint32>& preserveAttachments = subpass.getPreserveAttachments();
if (!inputAttachments.empty())
{
const tcu::ScopedLogSection inputAttachmentsSection (log, "Inputs", "Inputs");
for (size_t inputNdx = 0; inputNdx < inputAttachments.size(); inputNdx++)
{
const tcu::ScopedLogSection inputAttachmentSection (log, "Input" + de::toString(inputNdx), "Input " + de::toString(inputNdx));
const AttachmentReference& inputAttachment = inputAttachments[inputNdx];
log << TestLog::Message << "Attachment: " << inputAttachment.getAttachment() << TestLog::EndMessage;
log << TestLog::Message << "Layout: " << inputAttachment.getImageLayout() << TestLog::EndMessage;
if (!useExternalInputAspect)
log << TestLog::Message << "AspectMask: " << inputAttachment.getAspectMask() << TestLog::EndMessage;
}
}
if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
{
const tcu::ScopedLogSection depthStencilAttachmentSection (log, "DepthStencil", "DepthStencil");
const AttachmentReference& depthStencilAttachment = subpass.getDepthStencilAttachment();
log << TestLog::Message << "Attachment: " << depthStencilAttachment.getAttachment() << TestLog::EndMessage;
log << TestLog::Message << "Layout: " << depthStencilAttachment.getImageLayout() << TestLog::EndMessage;
}
if (!colorAttachments.empty())
{
const tcu::ScopedLogSection colorAttachmentsSection (log, "Colors", "Colors");
for (size_t colorNdx = 0; colorNdx < colorAttachments.size(); colorNdx++)
{
const tcu::ScopedLogSection colorAttachmentSection (log, "Color" + de::toString(colorNdx), "Color " + de::toString(colorNdx));
const AttachmentReference& colorAttachment = colorAttachments[colorNdx];
log << TestLog::Message << "Attachment: " << colorAttachment.getAttachment() << TestLog::EndMessage;
log << TestLog::Message << "Layout: " << colorAttachment.getImageLayout() << TestLog::EndMessage;
}
}
if (!resolveAttachments.empty())
{
const tcu::ScopedLogSection resolveAttachmentsSection (log, "Resolves", "Resolves");
for (size_t resolveNdx = 0; resolveNdx < resolveAttachments.size(); resolveNdx++)
{
const tcu::ScopedLogSection resolveAttachmentSection (log, "Resolve" + de::toString(resolveNdx), "Resolve " + de::toString(resolveNdx));
const AttachmentReference& resolveAttachment = resolveAttachments[resolveNdx];
log << TestLog::Message << "Attachment: " << resolveAttachment.getAttachment() << TestLog::EndMessage;
log << TestLog::Message << "Layout: " << resolveAttachment.getImageLayout() << TestLog::EndMessage;
}
}
if (!preserveAttachments.empty())
{
const tcu::ScopedLogSection preserveAttachmentsSection (log, "Preserves", "Preserves");
for (size_t preserveNdx = 0; preserveNdx < preserveAttachments.size(); preserveNdx++)
{
const tcu::ScopedLogSection preserveAttachmentSection (log, "Preserve" + de::toString(preserveNdx), "Preserve " + de::toString(preserveNdx));
const deUint32 preserveAttachment = preserveAttachments[preserveNdx];
log << TestLog::Message << "Attachment: " << preserveAttachment << TestLog::EndMessage;
}
}
}
}
if (!renderPass.getDependencies().empty())
{
const tcu::ScopedLogSection dependenciesSection (log, "Dependencies", "Dependencies");
for (size_t depNdx = 0; depNdx < renderPass.getDependencies().size(); depNdx++)
{
const tcu::ScopedLogSection dependencySection (log, "Dependency" + de::toString(depNdx), "Dependency " + de::toString(depNdx));
const SubpassDependency& dep = renderPass.getDependencies()[depNdx];
log << TestLog::Message << "Source: " << dep.getSrcPass() << TestLog::EndMessage;
log << TestLog::Message << "Destination: " << dep.getDstPass() << TestLog::EndMessage;
log << TestLog::Message << "Source Stage Mask: " << dep.getSrcStageMask() << TestLog::EndMessage;
log << TestLog::Message << "Destination Stage Mask: " << dep.getDstStageMask() << TestLog::EndMessage;
log << TestLog::Message << "Input Mask: " << dep.getDstAccessMask() << TestLog::EndMessage;
log << TestLog::Message << "Output Mask: " << dep.getSrcAccessMask() << TestLog::EndMessage;
log << TestLog::Message << "Dependency Flags: " << getDependencyFlagsStr(dep.getFlags()) << TestLog::EndMessage;
}
}
}
std::string clearColorToString (VkFormat vkFormat, VkClearColorValue value, deBool useFormatCompCount)
{
const tcu::TextureFormat format = mapVkFormat(vkFormat);
const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(format);
const deUint32 componentCount = (useFormatCompCount ? (deUint32)tcu::getNumUsedChannels(format.order) : 4);
std::ostringstream stream;
stream << "(";
switch (channelClass)
{
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
for (deUint32 i = 0; i < componentCount; i++)
{
if (i > 0)
stream << ", ";
if (channelMask[i])
stream << value.int32[i];
else
stream << "Undef";
}
break;
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
for (deUint32 i = 0; i < componentCount; i++)
{
if (i > 0)
stream << ", ";
if (channelMask[i])
stream << value.uint32[i];
else
stream << "Undef";
}
break;
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
for (deUint32 i = 0; i < componentCount; i++)
{
if (i > 0)
stream << ", ";
if (channelMask[i])
stream << value.float32[i];
else
stream << "Undef";
}
break;
default:
DE_FATAL("Unknown channel class");
}
stream << ")";
return stream.str();
}
std::string clearValueToString (VkFormat vkFormat, VkClearValue value, deBool useFormatCompCount)
{
const tcu::TextureFormat format = mapVkFormat(vkFormat);
if (tcu::hasStencilComponent(format.order) || tcu::hasDepthComponent(format.order))
{
std::ostringstream stream;
stream << "(";
if (tcu::hasStencilComponent(format.order))
stream << "stencil: " << value.depthStencil.stencil;
if (tcu::hasStencilComponent(format.order) && tcu::hasDepthComponent(format.order))
stream << ", ";
if (tcu::hasDepthComponent(format.order))
stream << "depth: " << value.depthStencil.depth;
stream << ")";
return stream.str();
}
else
return clearColorToString(vkFormat, value.color, useFormatCompCount);
}
VkClearColorValue randomColorClearValue (const Attachment& attachment, de::Random& rng, deBool useFormatCompCount)
{
const float clearNan = tcu::Float32::nan().asFloat();
const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(format);
const deUint32 componentCount = (useFormatCompCount ? (deUint32)tcu::getNumUsedChannels(format.order) : 4);
VkClearColorValue clearColor;
switch (channelClass)
{
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
{
for (deUint32 ndx = 0; ndx < componentCount; ndx++)
{
if (!channelMask[ndx])
clearColor.int32[ndx] = std::numeric_limits<deInt32>::min();
else
clearColor.uint32[ndx] = rng.getBool() ? 1u : 0u;
}
break;
}
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
{
for (deUint32 ndx = 0; ndx < componentCount; ndx++)
{
if (!channelMask[ndx])
clearColor.uint32[ndx] = std::numeric_limits<deUint32>::max();
else
clearColor.uint32[ndx] = rng.getBool() ? 1u : 0u;
}
break;
}
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
{
for (deUint32 ndx = 0; ndx < componentCount; ndx++)
{
if (!channelMask[ndx])
clearColor.float32[ndx] = clearNan;
else
clearColor.float32[ndx] = rng.getBool() ? 1.0f : 0.0f;
}
break;
}
default:
DE_FATAL("Unknown channel class");
}
return clearColor;
}
template <typename AttachmentDesc>
AttachmentDesc createAttachmentDescription (const Attachment& attachment)
{
const AttachmentDesc attachmentDescription // VkAttachmentDescription || VkAttachmentDescription2KHR
(
// || VkStructureType sType;
DE_NULL, // || const void* pNext;
0u, // VkAttachmentDescriptionFlags flags; || VkAttachmentDescriptionFlags flags;
attachment.getFormat(), // VkFormat format; || VkFormat format;
attachment.getSamples(), // VkSampleCountFlagBits samples; || VkSampleCountFlagBits samples;
attachment.getLoadOp(), // VkAttachmentLoadOp loadOp; || VkAttachmentLoadOp loadOp;
attachment.getStoreOp(), // VkAttachmentStoreOp storeOp; || VkAttachmentStoreOp storeOp;
attachment.getStencilLoadOp(), // VkAttachmentLoadOp stencilLoadOp; || VkAttachmentLoadOp stencilLoadOp;
attachment.getStencilStoreOp(), // VkAttachmentStoreOp stencilStoreOp; || VkAttachmentStoreOp stencilStoreOp;
attachment.getInitialLayout(), // VkImageLayout initialLayout; || VkImageLayout initialLayout;
attachment.getFinalLayout() // VkImageLayout finalLayout; || VkImageLayout finalLayout;
);
return attachmentDescription;
}
template <typename AttachmentRef>
AttachmentRef createAttachmentReference (const AttachmentReference& referenceInfo)
{
const AttachmentRef reference // VkAttachmentReference || VkAttachmentReference2KHR
(
// || VkStructureType sType;
DE_NULL, // || const void* pNext;
referenceInfo.getAttachment(), // deUint32 attachment; || deUint32 attachment;
referenceInfo.getImageLayout(), // VkImageLayout layout; || VkImageLayout layout;
referenceInfo.getAspectMask() // || VkImageAspectFlags aspectMask;
);
return reference;
}
template <typename SubpassDesc, typename AttachmentRef>
SubpassDesc createSubpassDescription (const Subpass& subpass,
vector<AttachmentRef>* attachmentReferenceLists,
vector<deUint32>* preserveAttachmentReferences)
{
vector<AttachmentRef>& inputAttachmentReferences = attachmentReferenceLists[0];
vector<AttachmentRef>& colorAttachmentReferences = attachmentReferenceLists[1];
vector<AttachmentRef>& resolveAttachmentReferences = attachmentReferenceLists[2];
vector<AttachmentRef>& depthStencilAttachmentReferences = attachmentReferenceLists[3];
for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
colorAttachmentReferences.push_back(createAttachmentReference<AttachmentRef>(subpass.getColorAttachments()[attachmentNdx]));
for (size_t attachmentNdx = 0; attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++)
inputAttachmentReferences.push_back(createAttachmentReference<AttachmentRef>(subpass.getInputAttachments()[attachmentNdx]));
for (size_t attachmentNdx = 0; attachmentNdx < subpass.getResolveAttachments().size(); attachmentNdx++)
resolveAttachmentReferences.push_back(createAttachmentReference<AttachmentRef>(subpass.getResolveAttachments()[attachmentNdx]));
depthStencilAttachmentReferences.push_back(createAttachmentReference<AttachmentRef>(subpass.getDepthStencilAttachment()));
for (size_t attachmentNdx = 0; attachmentNdx < subpass.getPreserveAttachments().size(); attachmentNdx++)
preserveAttachmentReferences->push_back(subpass.getPreserveAttachments()[attachmentNdx]);
DE_ASSERT(resolveAttachmentReferences.empty() || colorAttachmentReferences.size() == resolveAttachmentReferences.size());
{
const SubpassDesc subpassDescription // VkSubpassDescription || VkSubpassDescription2KHR
(
// || VkStructureType sType;
DE_NULL, // || const void* pNext;
subpass.getFlags(), // VkSubpassDescriptionFlags flags; || VkSubpassDescriptionFlags flags;
subpass.getPipelineBindPoint(), // VkPipelineBindPoint pipelineBindPoint; || VkPipelineBindPoint pipelineBindPoint;
0u, // || deUint32 viewMask;
(deUint32)inputAttachmentReferences.size(), // deUint32 inputAttachmentCount; || deUint32 inputAttachmentCount;
inputAttachmentReferences.empty() ? DE_NULL : &inputAttachmentReferences[0], // const VkAttachmentReference* pInputAttachments; || const VkAttachmentReference2KHR* pInputAttachments;
(deUint32)colorAttachmentReferences.size(), // deUint32 colorAttachmentCount; || deUint32 colorAttachmentCount;
colorAttachmentReferences.empty() ? DE_NULL : &colorAttachmentReferences[0], // const VkAttachmentReference* pColorAttachments; || const VkAttachmentReference2KHR* pColorAttachments;
resolveAttachmentReferences.empty() ? DE_NULL : &resolveAttachmentReferences[0], // const VkAttachmentReference* pResolveAttachments; || const VkAttachmentReference2KHR* pResolveAttachments;
&depthStencilAttachmentReferences[0], // const VkAttachmentReference* pDepthStencilAttachment; || const VkAttachmentReference2KHR* pDepthStencilAttachment;
(deUint32)preserveAttachmentReferences->size(), // deUint32 preserveAttachmentCount; || deUint32 preserveAttachmentCount;
preserveAttachmentReferences->empty() ? DE_NULL : &(*preserveAttachmentReferences)[0] // const deUint32* pPreserveAttachments; || const deUint32* pPreserveAttachments;
);
return subpassDescription;
}
}
template <typename SubpassDep>
SubpassDep createSubpassDependency (const SubpassDependency& dependencyInfo)
{
const SubpassDep dependency // VkSubpassDependency || VkSubpassDependency2KHR
(
// || VkStructureType sType;
DE_NULL, // || const void* pNext;
dependencyInfo.getSrcPass(), // deUint32 srcSubpass; || deUint32 srcSubpass;
dependencyInfo.getDstPass(), // deUint32 dstSubpass; || deUint32 dstSubpass;
dependencyInfo.getSrcStageMask(), // VkPipelineStageFlags srcStageMask; || VkPipelineStageFlags srcStageMask;
dependencyInfo.getDstStageMask(), // VkPipelineStageFlags dstStageMask; || VkPipelineStageFlags dstStageMask;
dependencyInfo.getSrcAccessMask(), // VkAccessFlags srcAccessMask; || VkAccessFlags srcAccessMask;
dependencyInfo.getDstAccessMask(), // VkAccessFlags dstAccessMask; || VkAccessFlags dstAccessMask;
dependencyInfo.getFlags(), // VkDependencyFlags dependencyFlags; || VkDependencyFlags dependencyFlags;
0u // || deInt32 viewOffset;
);
return dependency;
}
de::MovePtr<VkRenderPassInputAttachmentAspectCreateInfo> createRenderPassInputAttachmentAspectCreateInfo(const RenderPass& renderPassInfo)
{
de::MovePtr<VkRenderPassInputAttachmentAspectCreateInfo> result (DE_NULL);
if (!renderPassInfo.getInputAspects().empty())
{
const VkRenderPassInputAttachmentAspectCreateInfo inputAspectCreateInfo =
{
VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO,
DE_NULL,
(deUint32)renderPassInfo.getInputAspects().size(),
renderPassInfo.getInputAspects().data(),
};
result = de::MovePtr<VkRenderPassInputAttachmentAspectCreateInfo>(new VkRenderPassInputAttachmentAspectCreateInfo(inputAspectCreateInfo));
}
return result;
}
template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
Move<VkRenderPass> createRenderPass (const DeviceInterface& vk,
VkDevice device,
const RenderPass& renderPassInfo)
{
const size_t perSubpassAttachmentReferenceLists = 4;
vector<AttachmentDesc> attachments;
vector<SubpassDesc> subpasses;
vector<SubpassDep> dependencies;
vector<vector<AttachmentRef> > attachmentReferenceLists(renderPassInfo.getSubpasses().size() * perSubpassAttachmentReferenceLists);
vector<vector<deUint32> > preserveAttachments(renderPassInfo.getSubpasses().size());
de::MovePtr<VkRenderPassInputAttachmentAspectCreateInfo> inputAspectCreateInfo(createRenderPassInputAttachmentAspectCreateInfo(renderPassInfo));
for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
attachments.push_back(createAttachmentDescription<AttachmentDesc>(renderPassInfo.getAttachments()[attachmentNdx]));
for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
subpasses.push_back(createSubpassDescription<SubpassDesc>(renderPassInfo.getSubpasses()[subpassNdx], &(attachmentReferenceLists[subpassNdx * perSubpassAttachmentReferenceLists]), &preserveAttachments[subpassNdx]));
for (size_t depNdx = 0; depNdx < renderPassInfo.getDependencies().size(); depNdx++)
dependencies.push_back(createSubpassDependency<SubpassDep>(renderPassInfo.getDependencies()[depNdx]));
const RenderPassCreateInfo renderPassCreator // VkRenderPassCreateInfo || VkRenderPassCreateInfo2KHR
(
// VkStructureType sType; || VkStructureType sType;
inputAspectCreateInfo.get(), // const void* pNext; || const void* pNext;
(VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags; || VkRenderPassCreateFlags flags;
(deUint32)attachments.size(), // deUint32 attachmentCount; || deUint32 attachmentCount;
(attachments.empty() ? DE_NULL : &attachments[0]), // const VkAttachmentDescription* pAttachments; || const VkAttachmentDescription2KHR* pAttachments;
(deUint32)subpasses.size(), // deUint32 subpassCount; || deUint32 subpassCount;
(subpasses.empty() ? DE_NULL : &subpasses[0]), // const VkSubpassDescription* pSubpasses; || const VkSubpassDescription2KHR* pSubpasses;
(deUint32)dependencies.size(), // deUint32 dependencyCount; || deUint32 dependencyCount;
(dependencies.empty() ? DE_NULL : &dependencies[0]), // const VkSubpassDependency* pDependencies; || const VkSubpassDependency2KHR* pDependencies;
0u, // || deUint32 correlatedViewMaskCount;
DE_NULL // || const deUint32* pCorrelatedViewMasks;
);
return renderPassCreator.createRenderPass(vk, device);
}
Move<VkRenderPass> createRenderPass (const DeviceInterface& vk,
VkDevice device,
const RenderPass& renderPassInfo,
const RenderingType renderPassType)
{
switch (renderPassType)
{
case RENDERING_TYPE_RENDERPASS_LEGACY:
return createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, device, renderPassInfo);
case RENDERING_TYPE_RENDERPASS2:
return createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, device, renderPassInfo);
default:
TCU_THROW(InternalError, "Impossible");
}
}
Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vk,
VkDevice device,
VkRenderPass renderPass,
const UVec2& size,
const vector<VkImageView>& attachments)
{
return createFramebuffer(vk, device, 0u, renderPass, (deUint32)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0], size.x(), size.y(), 1u);
}
Move<VkImage> createAttachmentImage (const DeviceInterface& vk,
VkDevice device,
deUint32 queueIndex,
const UVec2& size,
VkFormat format,
VkSampleCountFlagBits samples,
VkImageUsageFlags usageFlags,
VkImageLayout layout)
{
VkImageUsageFlags targetUsageFlags = 0;
const tcu::TextureFormat textureFormat = mapVkFormat(format);
DE_ASSERT(!(tcu::hasDepthComponent(vk::mapVkFormat(format).order) || tcu::hasStencilComponent(vk::mapVkFormat(format).order))
|| ((usageFlags & vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) == 0));
DE_ASSERT((tcu::hasDepthComponent(vk::mapVkFormat(format).order) || tcu::hasStencilComponent(vk::mapVkFormat(format).order))
|| ((usageFlags & vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0));
if (tcu::hasDepthComponent(textureFormat.order) || tcu::hasStencilComponent(textureFormat.order))
targetUsageFlags |= vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
else
targetUsageFlags |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
return createImage(vk, device,
(VkImageCreateFlags)0,
VK_IMAGE_TYPE_2D,
format,
vk::makeExtent3D(size.x(), size.y(), 1u),
1u /* mipLevels */,
1u /* arraySize */,
samples,
VK_IMAGE_TILING_OPTIMAL,
usageFlags | targetUsageFlags,
VK_SHARING_MODE_EXCLUSIVE,
1,
&queueIndex,
layout);
}
de::MovePtr<Allocation> createImageMemory (const InstanceInterface& vki,
const VkPhysicalDevice& vkd,
const DeviceInterface& vk,
VkDevice device,
Allocator& allocator,
VkImage image,
bool lazy,
AllocationKind allocationKind)
{
const MemoryRequirement memoryRequirement = lazy ? MemoryRequirement::LazilyAllocated : MemoryRequirement::Any;
de::MovePtr<Allocation> allocation = allocateImage(vki, vk, vkd, device, image, memoryRequirement, allocator, allocationKind);
bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
return allocation;
}
Move<VkImageView> createImageAttachmentView (const DeviceInterface& vk,
VkDevice device,
VkImage image,
VkFormat format,
VkImageAspectFlags aspect)
{
const VkImageSubresourceRange range =
{
aspect,
0,
1,
0,
1
};
return createImageView(vk, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
}
VkClearValue randomClearValue (const Attachment& attachment, de::Random& rng, deBool useFormatCompCount, const DepthValuesArray& depthValues)
{
const float clearNan = tcu::Float32::nan().asFloat();
const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
if (tcu::hasStencilComponent(format.order) || tcu::hasDepthComponent(format.order))
{
VkClearValue clearValue;
clearValue.depthStencil.depth = clearNan;
clearValue.depthStencil.stencil = 0xCDu;
if (tcu::hasStencilComponent(format.order))
clearValue.depthStencil.stencil = rng.getBool()
? 0xFFu
: 0x0u;
if (tcu::hasDepthComponent(format.order))
clearValue.depthStencil.depth = float(depthValues[rng.getBool() ? 1 : 0]) / 255.0f;
return clearValue;
}
else
{
VkClearValue clearValue;
clearValue.color = randomColorClearValue(attachment, rng, useFormatCompCount);
return clearValue;
}
}
class AttachmentResources
{
public:
AttachmentResources (const InstanceInterface& vki,
const VkPhysicalDevice& physDevice,
const DeviceInterface& vk,
VkDevice device,
Allocator& allocator,
deUint32 queueIndex,
const UVec2& size,
const Attachment& attachmentInfo,
VkImageUsageFlags usageFlags,
const AllocationKind allocationKind)
: m_image (createAttachmentImage(vk, device, queueIndex, size, attachmentInfo.getFormat(), attachmentInfo.getSamples(), usageFlags, VK_IMAGE_LAYOUT_UNDEFINED))
, m_imageMemory (createImageMemory(vki, physDevice, vk, device, allocator, *m_image, ((usageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) != 0), allocationKind))
, m_attachmentView (createImageAttachmentView(vk, device, *m_image, attachmentInfo.getFormat(), getImageAspectFlags(attachmentInfo.getFormat())))
{
const tcu::TextureFormat format = mapVkFormat(attachmentInfo.getFormat());
const bool isDepthFormat = tcu::hasDepthComponent(format.order);
const bool isStencilFormat = tcu::hasStencilComponent(format.order);
if (isDepthFormat && isStencilFormat)
{
m_depthInputAttachmentView = createImageAttachmentView(vk, device, *m_image, attachmentInfo.getFormat(), VK_IMAGE_ASPECT_DEPTH_BIT);
m_stencilInputAttachmentView = createImageAttachmentView(vk, device, *m_image, attachmentInfo.getFormat(), VK_IMAGE_ASPECT_STENCIL_BIT);
m_inputAttachmentViews = std::make_pair(*m_depthInputAttachmentView, *m_stencilInputAttachmentView);
}
else
m_inputAttachmentViews = std::make_pair(*m_attachmentView, (vk::VkImageView)0u);
if ((usageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) == 0)
{
if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
{
const tcu::TextureFormat depthFormat = getDepthCopyFormat(attachmentInfo.getFormat());
const tcu::TextureFormat stencilFormat = getStencilCopyFormat(attachmentInfo.getFormat());
m_bufferSize = size.x() * size.y() * depthFormat.getPixelSize();
m_secondaryBufferSize = size.x() * size.y() * stencilFormat.getPixelSize();
m_buffer = createBuffer(vk, device, 0, m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
m_bufferMemory = allocateBuffer(vki, vk, physDevice, device, *m_buffer, MemoryRequirement::HostVisible, allocator, allocationKind);
bindBufferMemory(vk, device, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset());
m_secondaryBuffer = createBuffer(vk, device, 0, m_secondaryBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
m_secondaryBufferMemory = allocateBuffer(vki, vk, physDevice, device, *m_secondaryBuffer, MemoryRequirement::HostVisible, allocator, allocationKind);
bindBufferMemory(vk, device, *m_secondaryBuffer, m_secondaryBufferMemory->getMemory(), m_secondaryBufferMemory->getOffset());
}
else
{
m_bufferSize = size.x() * size.y() * format.getPixelSize();
m_buffer = createBuffer(vk, device, 0, m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
m_bufferMemory = allocateBuffer(vki, vk, physDevice, device, *m_buffer, MemoryRequirement::HostVisible, allocator, allocationKind);
bindBufferMemory(vk, device, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset());
}
}
}
const pair<VkImageView, VkImageView>& getInputAttachmentViews (void) const
{
return m_inputAttachmentViews;
}
~AttachmentResources (void)
{
}
VkImageView getAttachmentView (void) const
{
return *m_attachmentView;
}
VkImage getImage (void) const
{
return *m_image;
}
VkBuffer getBuffer (void) const
{
DE_ASSERT(*m_buffer != DE_NULL);
return *m_buffer;
}
VkDeviceSize getBufferSize (void) const
{
DE_ASSERT(*m_buffer != DE_NULL);
return m_bufferSize;
}
const Allocation& getResultMemory (void) const
{
DE_ASSERT(m_bufferMemory);
return *m_bufferMemory;
}
VkBuffer getSecondaryBuffer (void) const
{
DE_ASSERT(*m_secondaryBuffer != DE_NULL);
return *m_secondaryBuffer;
}
VkDeviceSize getSecondaryBufferSize (void) const
{
DE_ASSERT(*m_secondaryBuffer != DE_NULL);
return m_secondaryBufferSize;
}
const Allocation& getSecondaryResultMemory (void) const
{
DE_ASSERT(m_secondaryBufferMemory);
return *m_secondaryBufferMemory;
}
private:
const Unique<VkImage> m_image;
const UniquePtr<Allocation> m_imageMemory;
const Unique<VkImageView> m_attachmentView;
Move<VkImageView> m_depthInputAttachmentView;
Move<VkImageView> m_stencilInputAttachmentView;
pair<VkImageView, VkImageView> m_inputAttachmentViews;
Move<VkBuffer> m_buffer;
VkDeviceSize m_bufferSize;
de::MovePtr<Allocation> m_bufferMemory;
Move<VkBuffer> m_secondaryBuffer;
VkDeviceSize m_secondaryBufferSize;
de::MovePtr<Allocation> m_secondaryBufferMemory;
};
void uploadBufferData (const DeviceInterface& vk,
VkDevice device,
const Allocation& memory,
size_t size,
const void* data,
VkDeviceSize nonCoherentAtomSize)
{
// Expand the range to flush to account for the nonCoherentAtomSize
const VkDeviceSize roundedOffset = de::roundDown(memory.getOffset(), nonCoherentAtomSize);
const VkDeviceSize roundedSize = de::roundUp(memory.getOffset() - roundedOffset + static_cast<VkDeviceSize>(size), nonCoherentAtomSize);
const VkMappedMemoryRange range =
{
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType;
DE_NULL, // pNext;
memory.getMemory(), // mem;
roundedOffset, // offset;
roundedSize, // size;
};
void* const ptr = memory.getHostPtr();
deMemcpy(ptr, data, size);
VK_CHECK(vk.flushMappedMemoryRanges(device, 1, &range));
}
VkImageAspectFlagBits getPrimaryImageAspect (tcu::TextureFormat::ChannelOrder order)
{
DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 22);
switch (order)
{
case tcu::TextureFormat::D:
case tcu::TextureFormat::DS:
return VK_IMAGE_ASPECT_DEPTH_BIT;
case tcu::TextureFormat::S:
return VK_IMAGE_ASPECT_STENCIL_BIT;
default:
return VK_IMAGE_ASPECT_COLOR_BIT;
}
}
deUint32 getAttachmentNdx (const vector<AttachmentReference>& colorAttachments, size_t ndx)
{
return (colorAttachments[ndx].getAttachment() == VK_ATTACHMENT_UNUSED) ? (deUint32)ndx : colorAttachments[ndx].getAttachment();
}
class RenderQuad
{
public:
RenderQuad (const Vec2& posA, const Vec2& posB)
: m_vertices(6)
{
m_vertices[0] = posA;
m_vertices[1] = Vec2(posA[0], posB[1]);
m_vertices[2] = posB;
m_vertices[3] = posB;
m_vertices[4] = Vec2(posB[0], posA[1]);
m_vertices[5] = posA;
}
const Vec2& getCornerA (void) const
{
return m_vertices[0];
}
const Vec2& getCornerB (void) const
{
return m_vertices[2];
}
const void* getVertexPointer (void) const
{
return &m_vertices[0];
}
size_t getVertexDataSize (void) const
{
return sizeof(Vec2) * m_vertices.size();
}
private:
vector<Vec2> m_vertices;
};
class ColorClear
{
public:
ColorClear (const UVec2& offset,
const UVec2& size,
const VkClearColorValue& color)
: m_offset (offset)
, m_size (size)
, m_color (color)
{
}
const UVec2& getOffset (void) const { return m_offset; }
const UVec2& getSize (void) const { return m_size; }
const VkClearColorValue& getColor (void) const { return m_color; }
private:
UVec2 m_offset;
UVec2 m_size;
VkClearColorValue m_color;
};
class DepthStencilClear
{
public:
DepthStencilClear (const UVec2& offset,
const UVec2& size,
float depth,
deUint32 stencil)
: m_offset (offset)
, m_size (size)
, m_depth (depth)
, m_stencil (stencil)
{
}
const UVec2& getOffset (void) const { return m_offset; }
const UVec2& getSize (void) const { return m_size; }
float getDepth (void) const { return m_depth; }
deUint32 getStencil (void) const { return m_stencil; }
private:
const UVec2 m_offset;
const UVec2 m_size;
const float m_depth;
const deUint32 m_stencil;
};
class SubpassRenderInfo
{
public:
SubpassRenderInfo (const RenderPass& renderPass,
deUint32 subpassIndex,
deUint32 drawStartNdx,
bool isSecondary_,
bool omitBlendState_,
const UVec2& viewportOffset,
const UVec2& viewportSize,
const Maybe<RenderQuad>& renderQuad,
const vector<ColorClear>& colorClears,
const Maybe<DepthStencilClear>& depthStencilClear)
: m_viewportOffset (viewportOffset)
, m_viewportSize (viewportSize)
, m_subpassIndex (subpassIndex)
, m_drawStartNdx (drawStartNdx)
, m_isSecondary (isSecondary_)
, m_omitBlendState (omitBlendState_)
, m_flags (renderPass.getSubpasses()[subpassIndex].getFlags())
, m_renderQuad (renderQuad)
, m_colorClears (colorClears)
, m_depthStencilClear (depthStencilClear)
, m_colorAttachments (renderPass.getSubpasses()[subpassIndex].getColorAttachments())
, m_inputAttachments (renderPass.getSubpasses()[subpassIndex].getInputAttachments())
{
for (deUint32 attachmentNdx = 0; attachmentNdx < (deUint32)m_colorAttachments.size(); attachmentNdx++)
m_colorAttachmentInfo.push_back(renderPass.getAttachments()[getAttachmentNdx(m_colorAttachments, attachmentNdx)]);
if (renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
{
m_depthStencilAttachment = tcu::just(renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment());
m_depthStencilAttachmentInfo = tcu::just(renderPass.getAttachments()[renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment().getAttachment()]);
}
}
const UVec2& getViewportOffset (void) const { return m_viewportOffset; }
const UVec2& getViewportSize (void) const { return m_viewportSize; }
deUint32 getSubpassIndex (void) const { return m_subpassIndex; }
deUint32 getDrawStartNdx (void) const { return m_drawStartNdx; }
bool isSecondary (void) const { return m_isSecondary; }
bool getOmitBlendState (void) const { return m_omitBlendState; }
const Maybe<RenderQuad>& getRenderQuad (void) const { return m_renderQuad; }
const vector<ColorClear>& getColorClears (void) const { return m_colorClears; }
const Maybe<DepthStencilClear>& getDepthStencilClear (void) const { return m_depthStencilClear; }
deUint32 getInputAttachmentCount (void) const { return (deUint32)m_inputAttachments.size(); }
deUint32 getInputAttachmentIndex (deUint32 attachmentNdx) const { return m_inputAttachments[attachmentNdx].getAttachment(); }
VkImageLayout getInputAttachmentLayout (deUint32 attachmentNdx) const { return m_inputAttachments[attachmentNdx].getImageLayout(); }
deUint32 getColorAttachmentCount (void) const { return (deUint32)m_colorAttachments.size(); }
VkImageLayout getColorAttachmentLayout (deUint32 attachmentNdx) const { return m_colorAttachments[attachmentNdx].getImageLayout(); }
deUint32 getColorAttachmentIndex (deUint32 attachmentNdx) const { return m_colorAttachments[attachmentNdx].getAttachment(); }
const Attachment& getColorAttachment (deUint32 attachmentNdx) const { return m_colorAttachmentInfo[attachmentNdx]; }
Maybe<VkImageLayout> getDepthStencilAttachmentLayout (void) const { return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getImageLayout()) : tcu::nothing<VkImageLayout>(); }
Maybe<deUint32> getDepthStencilAttachmentIndex (void) const { return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getAttachment()) : tcu::nothing<deUint32>(); }
const Maybe<Attachment>& getDepthStencilAttachment (void) const { return m_depthStencilAttachmentInfo; }
VkSubpassDescriptionFlags getSubpassFlags (void) const { return m_flags; }
private:
UVec2 m_viewportOffset;
UVec2 m_viewportSize;
deUint32 m_subpassIndex;
deUint32 m_drawStartNdx;
bool m_isSecondary;
bool m_omitBlendState;
VkSubpassDescriptionFlags m_flags;
Maybe<RenderQuad> m_renderQuad;
vector<ColorClear> m_colorClears;
Maybe<DepthStencilClear> m_depthStencilClear;
vector<AttachmentReference> m_colorAttachments;
vector<Attachment> m_colorAttachmentInfo;
Maybe<AttachmentReference> m_depthStencilAttachment;
Maybe<Attachment> m_depthStencilAttachmentInfo;
vector<AttachmentReference> m_inputAttachments;
};
void beginCommandBuffer (const DeviceInterface& vk,
VkCommandBuffer cmdBuffer,
VkCommandBufferUsageFlags pBeginInfo_flags,
VkRenderPass pInheritanceInfo_renderPass,
deUint32 pInheritanceInfo_subpass,
VkFramebuffer pInheritanceInfo_framebuffer,
VkBool32 pInheritanceInfo_occlusionQueryEnable,
VkQueryControlFlags pInheritanceInfo_queryFlags,
VkQueryPipelineStatisticFlags pInheritanceInfo_pipelineStatistics,
const SubpassRenderInfo* pRenderInfo = 0,
bool dynamicRenderPass = false )
{
VkCommandBufferInheritanceInfo pInheritanceInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
DE_NULL,
pInheritanceInfo_renderPass,
pInheritanceInfo_subpass,
pInheritanceInfo_framebuffer,
pInheritanceInfo_occlusionQueryEnable,
pInheritanceInfo_queryFlags,
pInheritanceInfo_pipelineStatistics,
};
std::vector<vk::VkFormat> colorAttachmentFormats;
VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,
DE_NULL,
0u,
0u,
0u,
DE_NULL,
VK_FORMAT_UNDEFINED,
VK_FORMAT_UNDEFINED,
VK_SAMPLE_COUNT_1_BIT,
};
if (pRenderInfo)
{
for (deUint32 i = 0; i < pRenderInfo->getColorAttachmentCount(); ++i)
colorAttachmentFormats.push_back(pRenderInfo->getColorAttachment(i).getFormat());
inheritanceRenderingInfo.colorAttachmentCount = static_cast<deUint32>(colorAttachmentFormats.size());
inheritanceRenderingInfo.pColorAttachmentFormats = colorAttachmentFormats.data();
if (pRenderInfo->getDepthStencilAttachment())
{
inheritanceRenderingInfo.depthAttachmentFormat = pRenderInfo->getDepthStencilAttachment()->getFormat();
inheritanceRenderingInfo.stencilAttachmentFormat = pRenderInfo->getDepthStencilAttachment()->getFormat();
}
if (pRenderInfo->getColorAttachmentCount())
inheritanceRenderingInfo.rasterizationSamples = pRenderInfo->getColorAttachment(0).getSamples();
else if (pRenderInfo->getDepthStencilAttachment())
inheritanceRenderingInfo.rasterizationSamples = pRenderInfo->getDepthStencilAttachment()->getSamples();
if (dynamicRenderPass)
pInheritanceInfo.pNext = &inheritanceRenderingInfo;
}
const VkCommandBufferBeginInfo pBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
DE_NULL,
pBeginInfo_flags,
&pInheritanceInfo,
};
VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &pBeginInfo));
}
Move<VkPipeline> createSubpassPipeline (const DeviceInterface& vk,
VkDevice device,
VkRenderPass renderPass,
VkShaderModule vertexShaderModule,
VkShaderModule fragmentShaderModule,
VkPipelineLayout pipelineLayout,
const SubpassRenderInfo& renderInfo)
{
Maybe<VkSampleCountFlagBits> rasterSamples;
vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates;
for (deUint32 attachmentNdx = 0; attachmentNdx < renderInfo.getColorAttachmentCount(); attachmentNdx++)
{
const Attachment& attachment = renderInfo.getColorAttachment(attachmentNdx);
DE_ASSERT(!rasterSamples || *rasterSamples == attachment.getSamples());
rasterSamples = attachment.getSamples();
{
const VkPipelineColorBlendAttachmentState attachmentBlendState =
{
VK_FALSE, // blendEnable
VK_BLEND_FACTOR_SRC_ALPHA, // srcBlendColor
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // destBlendColor
VK_BLEND_OP_ADD, // blendOpColor
VK_BLEND_FACTOR_ONE, // srcBlendAlpha
VK_BLEND_FACTOR_ONE, // destBlendAlpha
VK_BLEND_OP_ADD, // blendOpAlpha
(attachmentNdx < renderInfo.getDrawStartNdx() ? (deUint32)0 :
VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT) // channelWriteMask
};
attachmentBlendStates.push_back(attachmentBlendState);
}
}
if (renderInfo.getDepthStencilAttachment())
{
const Attachment& attachment = *renderInfo.getDepthStencilAttachment();
DE_ASSERT(!rasterSamples || *rasterSamples == attachment.getSamples());
rasterSamples = attachment.getSamples();
}
// If there are no attachment use single sample
if (!rasterSamples)
rasterSamples = VK_SAMPLE_COUNT_1_BIT;
const VkVertexInputBindingDescription vertexBinding =
{
0u, // binding
(deUint32)sizeof(tcu::Vec2), // strideInBytes
VK_VERTEX_INPUT_RATE_VERTEX, // stepRate
};
const VkVertexInputAttributeDescription vertexAttrib =
{
0u, // location
0u, // binding
VK_FORMAT_R32G32_SFLOAT, // format
0u, // offsetInBytes
};
const VkPipelineVertexInputStateCreateInfo vertexInputState =
{
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // sType
DE_NULL, // pNext
(VkPipelineVertexInputStateCreateFlags)0u,
1u, // bindingCount
&vertexBinding, // pVertexBindingDescriptions
1u, // attributeCount
&vertexAttrib, // pVertexAttributeDescriptions
};
const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
{
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkPipelineInputAssemblyStateCreateFlags flags
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology
VK_FALSE // VkBool32 primitiveRestartEnable
};
const VkViewport viewport =
{
(float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y(),
(float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y(),
0.0f, 1.0f
};
const VkRect2D scissor =
{
{ (deInt32)renderInfo.getViewportOffset().x(), (deInt32)renderInfo.getViewportOffset().y() },
{ renderInfo.getViewportSize().x(), renderInfo.getViewportSize().y() }
};
const VkPipelineViewportStateCreateInfo viewportState =
{
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
(VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags
1u, // deUint32 viewportCount
&viewport, // const VkViewport* pViewports
1u, // deUint32 scissorCount
&scissor // const VkRect2D* pScissors
};
const VkPipelineRasterizationStateCreateInfo rasterizationState =
{
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkPipelineRasterizationStateCreateFlags flags
VK_FALSE, // VkBool32 depthClampEnable
VK_FALSE, // VkBool32 rasterizerDiscardEnable
VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode
VK_CULL_MODE_NONE, // VkCullModeFlags cullMode
VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace
VK_FALSE, // VkBool32 depthBiasEnable
0.0f, // float depthBiasConstantFactor
0.0f, // float depthBiasClamp
0.0f, // float depthBiasSlopeFactor
1.0f // float lineWidth
};
const VkPipelineMultisampleStateCreateInfo multisampleState =
{
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // sType
DE_NULL, // pNext
(VkPipelineMultisampleStateCreateFlags)0u,
*rasterSamples, // rasterSamples
VK_FALSE, // sampleShadingEnable
0.0f, // minSampleShading
DE_NULL, // pSampleMask
VK_FALSE, // alphaToCoverageEnable
VK_FALSE, // alphaToOneEnable
};
const size_t stencilIndex = renderInfo.getSubpassIndex();
const VkBool32 writeDepth = renderInfo.getDepthStencilAttachmentLayout()
&& *renderInfo.getDepthStencilAttachmentLayout() != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
&& *renderInfo.getDepthStencilAttachmentLayout() != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL
? VK_TRUE
: VK_FALSE;
const VkBool32 writeStencil = renderInfo.getDepthStencilAttachmentLayout()
&& *renderInfo.getDepthStencilAttachmentLayout() != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
&& *renderInfo.getDepthStencilAttachmentLayout() != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL
? VK_TRUE
: VK_FALSE;
const VkPipelineDepthStencilStateCreateInfo depthStencilState =
{
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // sType
DE_NULL, // pNext
(VkPipelineDepthStencilStateCreateFlags)0u,
writeDepth, // depthTestEnable
writeDepth, // depthWriteEnable
VK_COMPARE_OP_ALWAYS, // depthCompareOp
VK_FALSE, // depthBoundsEnable
writeStencil, // stencilTestEnable
{
VK_STENCIL_OP_REPLACE, // stencilFailOp
VK_STENCIL_OP_REPLACE, // stencilPassOp
VK_STENCIL_OP_REPLACE, // stencilDepthFailOp
VK_COMPARE_OP_ALWAYS, // stencilCompareOp
~0u, // stencilCompareMask
~0u, // stencilWriteMask
((stencilIndex % 2) == 0) ? ~0x0u : 0x0u // stencilReference
}, // front
{
VK_STENCIL_OP_REPLACE, // stencilFailOp
VK_STENCIL_OP_REPLACE, // stencilPassOp
VK_STENCIL_OP_REPLACE, // stencilDepthFailOp
VK_COMPARE_OP_ALWAYS, // stencilCompareOp
~0u, // stencilCompareMask
~0u, // stencilWriteMask
((stencilIndex % 2) == 0) ? ~0x0u : 0x0u // stencilReference
}, // back
0.0f, // minDepthBounds;
1.0f // maxDepthBounds;
};
const VkPipelineColorBlendStateCreateInfo blendState =
{
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // sType
DE_NULL, // pNext
(VkPipelineColorBlendStateCreateFlags)0u,
VK_FALSE, // logicOpEnable
VK_LOGIC_OP_COPY, // logicOp
(deUint32)attachmentBlendStates.size(), // attachmentCount
attachmentBlendStates.empty() ? DE_NULL : &attachmentBlendStates[0],// pAttachments
{ 0.0f, 0.0f, 0.0f, 0.0f } // blendConst
};
std::vector<vk::VkFormat> colorAttachmentFormats;
for (deUint32 i = 0; i < renderInfo.getColorAttachmentCount(); ++i)
colorAttachmentFormats.push_back(renderInfo.getColorAttachment(i).getFormat());
vk::VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
if (renderInfo.getDepthStencilAttachment())
{
const Attachment& attachment = *renderInfo.getDepthStencilAttachment();
depthStencilFormat = attachment.getFormat();
}
VkPipelineRenderingCreateInfoKHR renderingCreateInfo
{
VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
DE_NULL,
0u,
static_cast<deUint32>(colorAttachmentFormats.size()),
colorAttachmentFormats.data(),
depthStencilFormat,
depthStencilFormat
};
return makeGraphicsPipeline(vk, // const DeviceInterface& vk
device, // const VkDevice device
pipelineLayout, // const VkPipelineLayout pipelineLayout
vertexShaderModule, // const VkShaderModule vertexShaderModule
DE_NULL, // const VkShaderModule tessellationControlShaderModule
DE_NULL, // const VkShaderModule tessellationEvalShaderModule
DE_NULL, // const VkShaderModule geometryShaderModule
fragmentShaderModule, // const VkShaderModule fragmentShaderModule
renderPass, // const VkRenderPass renderPass
renderInfo.getSubpassIndex(), // const deUint32 subpass
&vertexInputState, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
&inputAssemblyState, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
&viewportState, // const VkPipelineViewportStateCreateInfo* pViewportStat;
&rasterizationState, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState
&multisampleState, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
&depthStencilState, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
renderInfo.getOmitBlendState()
? DE_NULL : &blendState, // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
DE_NULL, // const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfo
(renderPass == DE_NULL)
? &renderingCreateInfo : DE_NULL); // const void* pNext)
}
class SubpassRenderer
{
public:
SubpassRenderer (Context& context,
const DeviceInterface& vk,
VkDevice device,
Allocator& allocator,
VkRenderPass renderPass,
VkFramebuffer framebuffer,
VkCommandPool commandBufferPool,
deUint32 queueFamilyIndex,
const vector<VkImage>& attachmentImages,
const vector<pair<VkImageView, VkImageView> >& attachmentViews,
const SubpassRenderInfo& renderInfo,
const vector<Attachment>& attachmentInfos,
const AllocationKind allocationKind,
const bool dynamicRendering)
: m_renderInfo (renderInfo)
{
const InstanceInterface& vki = context.getInstanceInterface();
const VkPhysicalDevice& physDevice = context.getPhysicalDevice();
const deUint32 subpassIndex = renderInfo.getSubpassIndex();
vector<VkDescriptorSetLayoutBinding> bindings;
for (deUint32 colorAttachmentNdx = 0; colorAttachmentNdx < renderInfo.getColorAttachmentCount(); colorAttachmentNdx++)
{
const deUint32 attachmentNdx = (renderInfo.getColorAttachmentIndex(colorAttachmentNdx) == VK_ATTACHMENT_UNUSED) ? colorAttachmentNdx
: renderInfo.getColorAttachmentIndex(colorAttachmentNdx);
m_colorAttachmentImages.push_back(attachmentImages[attachmentNdx]);
}
if (renderInfo.getDepthStencilAttachmentIndex())
m_depthStencilAttachmentImage = attachmentImages[*renderInfo.getDepthStencilAttachmentIndex()];
if (renderInfo.getRenderQuad())
{
const RenderQuad& renderQuad = *renderInfo.getRenderQuad();
if (renderInfo.getInputAttachmentCount() > 0)
{
deUint32 bindingIndex = 0;
for (deUint32 inputAttachmentNdx = 0; inputAttachmentNdx < renderInfo.getInputAttachmentCount(); inputAttachmentNdx++)
{
const Attachment attachmentInfo = attachmentInfos[renderInfo.getInputAttachmentIndex(inputAttachmentNdx)];
const VkImageLayout layout = renderInfo.getInputAttachmentLayout(inputAttachmentNdx);
const tcu::TextureFormat format = mapVkFormat(attachmentInfo.getFormat());
const bool isDepthFormat = tcu::hasDepthComponent(format.order);
const bool isStencilFormat = tcu::hasStencilComponent(format.order);
const deUint32 bindingCount = (isDepthFormat && layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
&& (isStencilFormat && layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
? 2u
: 1u;
for (deUint32 bindingNdx = 0; bindingNdx < bindingCount; bindingNdx++)
{
const VkDescriptorSetLayoutBinding binding =
{
bindingIndex,
vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
1u,
vk::VK_SHADER_STAGE_FRAGMENT_BIT,
DE_NULL
};
bindings.push_back(binding);
bindingIndex++;
}
}
const VkDescriptorSetLayoutCreateInfo createInfo =
{
vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
DE_NULL,
0u,
(deUint32)bindings.size(),
&bindings[0]
};
m_descriptorSetLayout = vk::createDescriptorSetLayout(vk, device, &createInfo);
}
const VkDescriptorSetLayout descriptorSetLayout = *m_descriptorSetLayout;
const VkPipelineLayoutCreateInfo pipelineLayoutParams =
{
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType;
DE_NULL, // pNext;
(vk::VkPipelineLayoutCreateFlags)0,
m_descriptorSetLayout ? 1u :0u , // setLayoutCount;
m_descriptorSetLayout ? &descriptorSetLayout : DE_NULL, // pSetLayouts;
0u, // pushConstantRangeCount;
DE_NULL, // pPushConstantRanges;
};
m_vertexShaderModule = createShaderModule(vk, device, context.getBinaryCollection().get(de::toString(subpassIndex) + "-vert"), 0u);
m_fragmentShaderModule = createShaderModule(vk, device, context.getBinaryCollection().get(de::toString(subpassIndex) + "-frag"), 0u);
m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutParams);
m_pipeline = createSubpassPipeline(vk, device, renderPass, *m_vertexShaderModule, *m_fragmentShaderModule, *m_pipelineLayout, m_renderInfo);
// Round up the vertex buffer size to honor nonCoherentAtomSize.
const auto properties = vk::getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice());
const auto vertexBufferSize = de::roundUp(static_cast<VkDeviceSize>(renderQuad.getVertexDataSize()), properties.limits.nonCoherentAtomSize);
m_vertexBuffer = createBuffer(vk, device, 0u, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE, 1u, &queueFamilyIndex);
m_vertexBufferMemory = allocateBuffer(vki, vk, physDevice, device, *m_vertexBuffer, MemoryRequirement::HostVisible, allocator, allocationKind);
bindBufferMemory(vk, device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset());
uploadBufferData(vk, device, *m_vertexBufferMemory, renderQuad.getVertexDataSize(), renderQuad.getVertexPointer(), properties.limits.nonCoherentAtomSize);
if (renderInfo.getInputAttachmentCount() > 0)
{
{
const VkDescriptorPoolSize poolSize =
{
vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
// \note Reserve 2 per input attachment since depthStencil attachments require 2.
renderInfo.getInputAttachmentCount() * 2u
};
const VkDescriptorPoolCreateInfo createInfo =
{
vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
DE_NULL,
VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
// \note Reserve 2 per input attachment since depthStencil attachments require 2.
renderInfo.getInputAttachmentCount() * 2u,
1u,
&poolSize
};
m_descriptorPool = vk::createDescriptorPool(vk, device, &createInfo);
}
{
const VkDescriptorSetAllocateInfo allocateInfo =
{
vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
DE_NULL,
*m_descriptorPool,
1u,
&descriptorSetLayout
};
m_descriptorSet = vk::allocateDescriptorSet(vk, device, &allocateInfo);
}
{
vector<VkWriteDescriptorSet> writes (bindings.size());
vector<VkDescriptorImageInfo> imageInfos (bindings.size());
deUint32 bindingIndex = 0;
for (deUint32 inputAttachmentNdx = 0; inputAttachmentNdx < renderInfo.getInputAttachmentCount(); inputAttachmentNdx++)
{
const Attachment attachmentInfo = attachmentInfos[renderInfo.getInputAttachmentIndex(inputAttachmentNdx)];
const tcu::TextureFormat format = mapVkFormat(attachmentInfo.getFormat());
const bool isDepthFormat = tcu::hasDepthComponent(format.order);
const bool isStencilFormat = tcu::hasStencilComponent(format.order);
const VkImageLayout inputAttachmentLayout = renderInfo.getInputAttachmentLayout(inputAttachmentNdx);
if (isDepthFormat && isStencilFormat)
{
if (inputAttachmentLayout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
{
const VkDescriptorImageInfo imageInfo =
{
(VkSampler)0,
attachmentViews[renderInfo.getInputAttachmentIndex(inputAttachmentNdx)].first,
inputAttachmentLayout
};
imageInfos[bindingIndex] = imageInfo;
{
const VkWriteDescriptorSet write =
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
DE_NULL,
*m_descriptorSet,
bindingIndex,
0u,
1u,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
&imageInfos[bindingIndex],
DE_NULL,
DE_NULL
};
writes[bindingIndex] = write;
bindingIndex++;
}
}
if (inputAttachmentLayout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
{
const VkDescriptorImageInfo imageInfo =
{
(VkSampler)0,
attachmentViews[renderInfo.getInputAttachmentIndex(inputAttachmentNdx)].second,
inputAttachmentLayout
};
imageInfos[bindingIndex] = imageInfo;
{
const VkWriteDescriptorSet write =
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
DE_NULL,
*m_descriptorSet,
bindingIndex,
0u,
1u,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
&imageInfos[bindingIndex],
DE_NULL,
DE_NULL
};
writes[bindingIndex] = write;
bindingIndex++;
}
}
}
else
{
const VkDescriptorImageInfo imageInfo =
{
(VkSampler)0,
attachmentViews[renderInfo.getInputAttachmentIndex(inputAttachmentNdx)].first,
inputAttachmentLayout
};
imageInfos[bindingIndex] = imageInfo;
{
const VkWriteDescriptorSet write =
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
DE_NULL,
*m_descriptorSet,
bindingIndex,
0u,
1u,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
&imageInfos[bindingIndex],
DE_NULL,
DE_NULL
};
writes[bindingIndex] = write;
bindingIndex++;
}
}
}
vk.updateDescriptorSets(device, (deUint32)writes.size(), &writes[0], 0u, DE_NULL);
}
}
}
if (renderInfo.isSecondary())
{
m_commandBuffer = allocateCommandBuffer(vk, device, commandBufferPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
beginCommandBuffer(vk, *m_commandBuffer, vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, renderPass, subpassIndex, framebuffer, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0, &renderInfo, dynamicRendering);
pushRenderCommands(vk, *m_commandBuffer);
endCommandBuffer(vk, *m_commandBuffer);
}
}
bool isSecondary (void) const
{
return m_commandBuffer;
}
VkCommandBuffer getCommandBuffer (void) const
{
DE_ASSERT(isSecondary());
return *m_commandBuffer;
}
void pushRenderCommands (const DeviceInterface& vk,
VkCommandBuffer commandBuffer)
{
if (!m_renderInfo.getColorClears().empty())
{
const vector<ColorClear>& colorClears (m_renderInfo.getColorClears());
for (deUint32 attachmentNdx = 0; attachmentNdx < m_renderInfo.getColorAttachmentCount(); attachmentNdx++)
{
const ColorClear& colorClear = colorClears[attachmentNdx];
const VkClearAttachment attachment =
{
VK_IMAGE_ASPECT_COLOR_BIT,
attachmentNdx,
makeClearValue(colorClear.getColor()),
};
const VkClearRect rect =
{
{
{ (deInt32)colorClear.getOffset().x(), (deInt32)colorClear.getOffset().y() },
{ colorClear.getSize().x(), colorClear.getSize().y() }
}, // rect
0u, // baseArrayLayer
1u, // layerCount
};
vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
}
}
if (m_renderInfo.getDepthStencilClear())
{
const DepthStencilClear& depthStencilClear = *m_renderInfo.getDepthStencilClear();
const deUint32 attachmentNdx = m_renderInfo.getColorAttachmentCount();
tcu::TextureFormat format = mapVkFormat(m_renderInfo.getDepthStencilAttachment()->getFormat());
const VkImageLayout layout = *m_renderInfo.getDepthStencilAttachmentLayout();
const VkClearAttachment attachment =
{
(VkImageAspectFlags)((hasDepthComponent(format.order) && layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL ? VK_IMAGE_ASPECT_DEPTH_BIT : 0)
| (hasStencilComponent(format.order) && layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ? VK_IMAGE_ASPECT_STENCIL_BIT : 0)),
attachmentNdx,
makeClearValueDepthStencil(depthStencilClear.getDepth(), depthStencilClear.getStencil())
};
const VkClearRect rect =
{
{
{ (deInt32)depthStencilClear.getOffset().x(), (deInt32)depthStencilClear.getOffset().y() },
{ depthStencilClear.getSize().x(), depthStencilClear.getSize().y() }
}, // rect
0u, // baseArrayLayer
1u, // layerCount
};
if ((tcu::hasDepthComponent(format.order) && layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
|| (tcu::hasStencilComponent(format.order) && layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL))
{
vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
}
}
vector<VkImageMemoryBarrier> selfDeps;
VkPipelineStageFlags srcStages = 0;
VkPipelineStageFlags dstStages = 0;
for (deUint32 inputAttachmentNdx = 0; inputAttachmentNdx < m_renderInfo.getInputAttachmentCount(); inputAttachmentNdx++)
{
for (deUint32 colorAttachmentNdx = 0; colorAttachmentNdx < m_renderInfo.getColorAttachmentCount(); colorAttachmentNdx++)
{
if (m_renderInfo.getInputAttachmentIndex(inputAttachmentNdx) == m_renderInfo.getColorAttachmentIndex(colorAttachmentNdx))
{
const VkImageMemoryBarrier barrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
DE_NULL, // pNext
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // dstAccessMask
VK_IMAGE_LAYOUT_GENERAL, // oldLayout
VK_IMAGE_LAYOUT_GENERAL, // newLayout
VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
m_colorAttachmentImages[colorAttachmentNdx], // image
{ // subresourceRange
VK_IMAGE_ASPECT_COLOR_BIT, // aspect
0, // baseMipLevel
1, // mipLevels
0, // baseArraySlice
1 // arraySize
}
};
srcStages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dstStages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
selfDeps.push_back(barrier);
}
}
if (m_renderInfo.getDepthStencilAttachmentIndex() && (m_renderInfo.getInputAttachmentIndex(inputAttachmentNdx) == *m_renderInfo.getDepthStencilAttachmentIndex()))
{
const tcu::TextureFormat format = mapVkFormat(m_renderInfo.getDepthStencilAttachment()->getFormat());
const bool hasDepth = hasDepthComponent(format.order);
const bool hasStencil = hasStencilComponent(format.order);
const VkImageMemoryBarrier barrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType;
DE_NULL, // pNext;
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // srcAccessMask
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // dstAccessMask
m_renderInfo.getInputAttachmentLayout(inputAttachmentNdx), // oldLayout
m_renderInfo.getInputAttachmentLayout(inputAttachmentNdx), // newLayout;
VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex;
VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex;
m_depthStencilAttachmentImage, // image;
{ // subresourceRange;
(hasDepth ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u)
| (hasStencil ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT : 0u), // aspect;
0, // baseMipLevel;
1, // mipLevels;
0, // baseArraySlice;
1 // arraySize;
}
};
srcStages |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dstStages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
selfDeps.push_back(barrier);
}
}
if (!selfDeps.empty())
{
DE_ASSERT(srcStages != 0);
DE_ASSERT(dstStages != 0);
vk.cmdPipelineBarrier(commandBuffer, srcStages, dstStages, VK_DEPENDENCY_BY_REGION_BIT, 0, DE_NULL, 0, DE_NULL, (deUint32)selfDeps.size(), &selfDeps[0]);
}
if (m_renderInfo.getRenderQuad())
{
const VkDeviceSize offset = 0;
const VkBuffer vertexBuffer = *m_vertexBuffer;
vk.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
if (m_descriptorSet)
{
const VkDescriptorSet descriptorSet = *m_descriptorSet;
vk.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, NULL);
}
vk.cmdBindVertexBuffers(commandBuffer, 0u, 1u, &vertexBuffer, &offset);
vk.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u);
}
}
private:
const SubpassRenderInfo m_renderInfo;
Move<VkCommandBuffer> m_commandBuffer;
Move<VkPipeline> m_pipeline;
Move<VkDescriptorSetLayout> m_descriptorSetLayout;
Move<VkPipelineLayout> m_pipelineLayout;
Move<VkShaderModule> m_vertexShaderModule;
Move<VkShaderModule> m_fragmentShaderModule;
Move<VkDescriptorPool> m_descriptorPool;
Move<VkDescriptorSet> m_descriptorSet;
Move<VkBuffer> m_vertexBuffer;
de::MovePtr<Allocation> m_vertexBufferMemory;
vector<VkImage> m_colorAttachmentImages;
VkImage m_depthStencilAttachmentImage;
};
void pushImageInitializationCommands (const DeviceInterface& vk,
VkCommandBuffer commandBuffer,
const vector<Attachment>& attachmentInfo,
const vector<de::SharedPtr<AttachmentResources> >& attachmentResources,
deUint32 queueIndex,
const vector<Maybe<VkClearValue> >& clearValues)
{
{
vector<VkImageMemoryBarrier> initializeLayouts;
for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
{
if (!clearValues[attachmentNdx])
continue;
const VkImageMemoryBarrier barrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType;
DE_NULL, // pNext;
(VkAccessFlags)0, // srcAccessMask
getAllMemoryReadFlags() | VK_ACCESS_TRANSFER_WRITE_BIT, // dstAccessMask
VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // newLayout;
queueIndex, // srcQueueFamilyIndex;
queueIndex, // destQueueFamilyIndex;
attachmentResources[attachmentNdx]->getImage(), // image;
{ // subresourceRange;
getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
0, // baseMipLevel;
1, // mipLevels;
0, // baseArraySlice;
1 // arraySize;
}
};
initializeLayouts.push_back(barrier);
}
if (!initializeLayouts.empty())
vk.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, (VkDependencyFlags)0,
0, (const VkMemoryBarrier*)DE_NULL,
0, (const VkBufferMemoryBarrier*)DE_NULL,
(deUint32)initializeLayouts.size(), &initializeLayouts[0]);
}
for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
{
if (!clearValues[attachmentNdx])
continue;
const tcu::TextureFormat format = mapVkFormat(attachmentInfo[attachmentNdx].getFormat());
if (hasStencilComponent(format.order) || hasDepthComponent(format.order))
{
const float clearNan = tcu::Float32::nan().asFloat();
const float clearDepth = hasDepthComponent(format.order) ? clearValues[attachmentNdx]->depthStencil.depth : clearNan;
const deUint32 clearStencil = hasStencilComponent(format.order) ? clearValues[attachmentNdx]->depthStencil.stencil : 0xDEu;
const VkClearDepthStencilValue depthStencil =
{
clearDepth,
clearStencil
};
const VkImageSubresourceRange range =
{
(VkImageAspectFlags)((hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0)
| (hasStencilComponent(format.order) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0)),
0,
1,
0,
1
};
vk.cmdClearDepthStencilImage(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &depthStencil, 1, &range);
}
else
{
const VkImageSubresourceRange range =
{
VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask;
0, // baseMipLevel;
1, // mipLevels;
0, // baseArrayLayer;
1 // layerCount;
};
const VkClearColorValue clearColor = clearValues[attachmentNdx]->color;
vk.cmdClearColorImage(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &range);
}
}
{
vector<VkImageMemoryBarrier> renderPassLayouts;
for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
{
const VkImageLayout oldLayout = clearValues[attachmentNdx] ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
const VkImageMemoryBarrier barrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType;
DE_NULL, // pNext;
getMemoryFlagsForLayout(oldLayout), // srcAccessMask
getAllMemoryReadFlags() | getMemoryFlagsForLayout(attachmentInfo[attachmentNdx].getInitialLayout()), // dstAccessMask
oldLayout, // oldLayout
attachmentInfo[attachmentNdx].getInitialLayout(), // newLayout;
queueIndex, // srcQueueFamilyIndex;
queueIndex, // destQueueFamilyIndex;
attachmentResources[attachmentNdx]->getImage(), // image;
{ // subresourceRange;
getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
0, // baseMipLevel;
1, // mipLevels;
0, // baseArraySlice;
1 // arraySize;
}
};
renderPassLayouts.push_back(barrier);
}
if (!renderPassLayouts.empty())
vk.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, (VkDependencyFlags)0,
0, (const VkMemoryBarrier*)DE_NULL,
0, (const VkBufferMemoryBarrier*)DE_NULL,
(deUint32)renderPassLayouts.size(), &renderPassLayouts[0]);
}
}
template<typename RenderpassSubpass>
void pushRenderPassCommands (const DeviceInterface& vk,
VkCommandBuffer commandBuffer,
VkRenderPass renderPass,
VkFramebuffer framebuffer,
const vector<de::SharedPtr<SubpassRenderer> >& subpassRenderers,
const UVec2& renderPos,
const UVec2& renderSize,
const vector<Maybe<VkClearValue> >& renderPassClearValues,
TestConfig::RenderTypes render)
{
const float clearNan = tcu::Float32::nan().asFloat();
vector<VkClearValue> attachmentClearValues;
const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo (DE_NULL);
for (size_t attachmentNdx = 0; attachmentNdx < renderPassClearValues.size(); attachmentNdx++)
{
if (renderPassClearValues[attachmentNdx])
attachmentClearValues.push_back(*renderPassClearValues[attachmentNdx]);
else
attachmentClearValues.push_back(makeClearValueColorF32(clearNan, clearNan, clearNan, clearNan));
}
{
const VkRect2D renderArea =
{
{ (deInt32)renderPos.x(), (deInt32)renderPos.y() },
{ renderSize.x(), renderSize.y() }
};
for (size_t subpassNdx = 0; subpassNdx < subpassRenderers.size(); subpassNdx++)
{
const VkSubpassContents contents = subpassRenderers[subpassNdx]->isSecondary() ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE;
const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo (DE_NULL, contents);
const VkRenderPassBeginInfo renderPassBeginInfo = createRenderPassBeginInfo(renderPass,
framebuffer,
renderArea,
(deUint32)attachmentClearValues.size(),
attachmentClearValues.empty() ? DE_NULL : &attachmentClearValues[0]);
if (subpassNdx == 0)
RenderpassSubpass::cmdBeginRenderPass(vk, commandBuffer, &renderPassBeginInfo, &subpassBeginInfo);
else
RenderpassSubpass::cmdNextSubpass(vk, commandBuffer, &subpassBeginInfo, &subpassEndInfo);
if (render)
{
if (contents == VK_SUBPASS_CONTENTS_INLINE)
{
subpassRenderers[subpassNdx]->pushRenderCommands(vk, commandBuffer);
}
else if (contents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS)
{
const VkCommandBuffer cmd = subpassRenderers[subpassNdx]->getCommandBuffer();
vk.cmdExecuteCommands(commandBuffer, 1, &cmd);
}
else
DE_FATAL("Invalid contents");
}
}
RenderpassSubpass::cmdEndRenderPass(vk, commandBuffer, &subpassEndInfo);
}
}
void pushDynamicRenderingCommands (const DeviceInterface& vk,
VkCommandBuffer commandBuffer,
const RenderPass& renderPassInfo,
const vector<de::SharedPtr<AttachmentResources> >& attachmentResources,
const vector<de::SharedPtr<SubpassRenderer> >& subpassRenderers,
const UVec2& renderPos,
const UVec2& renderSize,
const vector<Maybe<VkClearValue> >& renderPassClearValues,
deUint32 queueIndex,
TestConfig::RenderTypes render)
{
const float clearNan = tcu::Float32::nan().asFloat();
const VkClearValue clearValueNan = makeClearValueColorF32(clearNan, clearNan, clearNan, clearNan);
DE_ASSERT(subpassRenderers.size() == 1);
VkRenderingFlagsKHR renderingFlags = 0u;
if (subpassRenderers[0]->isSecondary())
renderingFlags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR;
const VkRect2D renderArea
{
{ (deInt32)renderPos.x(), (deInt32)renderPos.y() },
{ renderSize.x(), renderSize.y() }
};
// translate structures that were prepared to construct renderpass to structures needed for dynamic rendering
vector<VkImageMemoryBarrier> imageBarriersBeforeRendering;
vector<VkImageMemoryBarrier> imageBarriersAfterRendering;
std::vector<vk::VkRenderingAttachmentInfoKHR> colorAttachmentVect;
const Subpass& subpassInfo = renderPassInfo.getSubpasses()[0];
const vector<AttachmentReference>& colorAttachmentsInfo = subpassInfo.getColorAttachments();
const vector<AttachmentReference>& resolveAttachmentsInfo = subpassInfo.getResolveAttachments();
for (deUint32 i = 0 ; i < colorAttachmentsInfo.size() ; ++i)
{
const AttachmentReference& colorAttachmentReference = colorAttachmentsInfo[i];
const deUint32 colorAttachmentIndex = colorAttachmentReference.getAttachment();
const Attachment& colorAttachmentInfo = renderPassInfo.getAttachments()[colorAttachmentIndex];
VkResolveModeFlagBits resolveMode = VK_RESOLVE_MODE_NONE;
VkImageView resolveImageView = DE_NULL;
VkImageLayout resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
// handle resolve attachments if they were specified
if (!resolveAttachmentsInfo.empty())
{
const AttachmentReference& resolveAttachmentReference = resolveAttachmentsInfo[i];
const deUint32 resolveAttachmentIndex = resolveAttachmentReference.getAttachment();
const Attachment& resolveAttachmentInfo = renderPassInfo.getAttachments()[resolveAttachmentIndex];
resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
resolveImageView = attachmentResources[resolveAttachmentIndex]->getAttachmentView();
resolveImageLayout = resolveAttachmentInfo.getInitialLayout();
}
colorAttachmentVect.push_back({
vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType
DE_NULL, // const void* pNext
attachmentResources[colorAttachmentIndex]->getAttachmentView(), // VkImageView imageView
colorAttachmentReference.getImageLayout(), // VkImageLayout imageLayout
resolveMode, // VkResolveModeFlagBits resolveMode
resolveImageView, // VkImageView resolveImageView
resolveImageLayout, // VkImageLayout resolveImageLayout
colorAttachmentInfo.getLoadOp(), // VkAttachmentLoadOp loadOp
colorAttachmentInfo.getStoreOp(), // VkAttachmentStoreOp storeOp
(renderPassClearValues[colorAttachmentIndex] ?
*renderPassClearValues[colorAttachmentIndex] :
clearValueNan) // VkClearValue clearValue
});
const VkImageLayout initialLayout = colorAttachmentInfo.getInitialLayout();
const VkImageLayout renderingLayout = colorAttachmentReference.getImageLayout();
const VkImageLayout finalLayout = colorAttachmentInfo.getFinalLayout();
const VkImageMemoryBarrier barrierBeforeRendering
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
DE_NULL, // pNext
getAllMemoryWriteFlags() | getMemoryFlagsForLayout(initialLayout), // srcAccessMask
getMemoryFlagsForLayout(renderingLayout), // dstAccessMask
initialLayout, // oldLayout
renderingLayout, // newLayout
queueIndex, // srcQueueFamilyIndex
queueIndex, // destQueueFamilyIndex
attachmentResources[colorAttachmentIndex]->getImage(), // image
{ // subresourceRange
getImageAspectFlags(colorAttachmentInfo.getFormat()), // aspect;
0, // baseMipLevel
1, // mipLevels
0, // baseArraySlice
1 // arraySize
}
};
imageBarriersBeforeRendering.push_back(barrierBeforeRendering);
const VkImageMemoryBarrier barrierAfterRendering
{<