| /*------------------------------------------------------------------------- |
| * 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 "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_, |
| RenderPassType renderPassType_) |
| : allocationKind (allocationKind_) |
| , renderPassType (renderPassType_) |
| { |
| } |
| |
| AllocationKind allocationKind; |
| RenderPassType renderPassType; |
| }; |
| |
| 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 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 VkCommandBufferInheritanceInfo pInheritanceInfo = |
| { |
| VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, |
| DE_NULL, |
| pInheritanceInfo_renderPass, |
| pInheritanceInfo_subpass, |
| pInheritanceInfo_framebuffer, |
| pInheritanceInfo_occlusionQueryEnable, |
| pInheritanceInfo_queryFlags, |
| pInheritanceInfo_pipelineStatistics, |
| }; |
| const VkCommandBufferBeginInfo pBeginInfo = |
| { |
| VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, |
| DE_NULL, |
| pBeginInfo_flags, |
| &pInheritanceInfo, |
| }; |
| VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &pBeginInfo)); |
| } |
| |
| 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 == 21); |
| |
| 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; } |
| |
| 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_, |
| RenderPassType renderPassType_, |
| 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_) |
| , renderPassType (renderPassType_) |
| , 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; |
| RenderPassType renderPassType; |
| 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 RenderPassType renderPassType) |
| { |
| switch (renderPassType) |
| { |
| case RENDERPASS_TYPE_LEGACY: |
| return createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, device, renderPassInfo); |
| case RENDERPASS_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 == 21); |
| |
| 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; |
| }; |
| |
| 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 |
| }; |
| |
| 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 |
| } |
| |
| 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) |
| : 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, static_cast<size_t>(vertexBufferSize), 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); |
| 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 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, |
| RenderPassType renderPassType) |
| { |
| switch (renderPassType) |
| { |
| case RENDERPASS_TYPE_LEGACY: |
| return pushRenderPassCommands<RenderpassSubpass1>(vk, commandBuffer, renderPass, framebuffer, subpassRenderers, renderPos, renderSize, renderPassClearValues, render); |
| case RENDERPASS_TYPE_RENDERPASS2: |
| return pushRenderPassCommands<RenderpassSubpass2>(vk, commandBuffer, renderPass, framebuffer, subpassRenderers, renderPos, renderSize, renderPassClearValues, render); |
| default: |
| TCU_THROW(InternalError, "Impossible"); |
| } |
| } |
| |
| void pushReadImagesToBuffers (const DeviceInterface& vk, |
| VkCommandBuffer commandBuffer, |
| deUint32 queueIndex, |
| |
| const vector<de::SharedPtr<AttachmentResources> >& attachmentResources, |
| const vector<Attachment>& attachmentInfo, |
| const vector<bool>& isLazy, |
| |
| const UVec2& targetSize) |
| { |
| { |
| vector<VkImageMemoryBarrier> imageBarriers; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++) |
| { |
| if (isLazy[attachmentNdx]) |
| continue; |
| |
| const VkImageLayout oldLayout = attachmentInfo[attachmentNdx].getFinalLayout(); |
| const VkImageMemoryBarrier barrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType |
| DE_NULL, // pNext |
| |
| getAllMemoryWriteFlags() | getMemoryFlagsForLayout(oldLayout), // srcAccessMask |
| getAllMemoryReadFlags(), // dstAccessMask |
| |
| oldLayout, // oldLayout |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout |
| |
| queueIndex, // srcQueueFamilyIndex |
| queueIndex, // destQueueFamilyIndex |
| |
| attachmentResources[attachmentNdx]->getImage(), // image |
| { // subresourceRange |
| getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect; |
| 0, // baseMipLevel |
| 1, // mipLevels |
| 0, // baseArraySlice |
| 1 // arraySize |
| } |
| }; |
| |
| imageBarriers.push_back(barrier); |
| } |
| |
| if (!imageBarriers.empty()) |
| vk.cmdPipelineBarrier(commandBuffer, |
| getAllPipelineStageFlags(), |
| getAllPipelineStageFlags(), |
| (VkDependencyFlags)0, |
| 0, (const VkMemoryBarrier*)DE_NULL, |
| 0, (const VkBufferMemoryBarrier*)DE_NULL, |
| (deUint32)imageBarriers.size(), &imageBarriers[0]); |
| } |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++) |
| { |
| if (isLazy[attachmentNdx]) |
| continue; |
| |
| const tcu::TextureFormat::ChannelOrder order = mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order; |
| const VkBufferImageCopy rect = |
| { |
| 0, // bufferOffset |
| 0, // bufferRowLength |
| 0, // bufferImageHeight |
| { // imageSubresource |
| (vk::VkImageAspectFlags)getPrimaryImageAspect(mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order), // aspect |
| 0, // mipLevel |
| 0, // arraySlice |
| 1 // arraySize |
| }, |
| { 0, 0, 0 }, // imageOffset |
| { targetSize.x(), targetSize.y(), 1u } // imageExtent |
| }; |
| |
| vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getBuffer(), 1, &rect); |
| |
| if (tcu::TextureFormat::DS == order) |
| { |
| const VkBufferImageCopy stencilRect = |
| { |
| 0, // bufferOffset |
| 0, // bufferRowLength |
| 0, // bufferImageHeight |
| { // imageSubresource |
| VK_IMAGE_ASPECT_STENCIL_BIT, // aspect |
| 0, // mipLevel |
| 0, // arraySlice |
| 1 // arraySize |
| }, |
| { 0, 0, 0 }, // imageOffset |
| { targetSize.x(), targetSize.y(), 1u } // imageExtent |
| }; |
| |
| vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getSecondaryBuffer(), 1, &stencilRect); |
| } |
| } |
| |
| { |
| vector<VkBufferMemoryBarrier> bufferBarriers; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++) |
| { |
| if (isLazy[attachmentNdx]) |
| continue; |
| |
| const tcu::TextureFormat::ChannelOrder order = mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order; |
| const VkBufferMemoryBarrier bufferBarrier = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, |
| DE_NULL, |
| |
| getAllMemoryWriteFlags(), |
| getAllMemoryReadFlags(), |
| |
| queueIndex, |
| queueIndex, |
| |
| attachmentResources[attachmentNdx]->getBuffer(), |
| 0, |
| attachmentResources[attachmentNdx]->getBufferSize() |
| }; |
| |
| bufferBarriers.push_back(bufferBarrier); |
| |
| if (tcu::TextureFormat::DS == order) |
| { |
| const VkBufferMemoryBarrier secondaryBufferBarrier = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, |
| DE_NULL, |
| |
| getAllMemoryWriteFlags(), |
| getAllMemoryReadFlags(), |
| |
| queueIndex, |
| queueIndex, |
| |
| attachmentResources[attachmentNdx]->getSecondaryBuffer(), |
| 0, |
| attachmentResources[attachmentNdx]->getSecondaryBufferSize() |
| }; |
| |
| bufferBarriers.push_back(secondaryBufferBarrier); |
| } |
| } |
| |
| if (!bufferBarriers.empty()) |
| vk.cmdPipelineBarrier(commandBuffer, |
| getAllPipelineStageFlags(), |
| getAllPipelineStageFlags(), |
| (VkDependencyFlags)0, |
| 0, (const VkMemoryBarrier*)DE_NULL, |
| (deUint32)bufferBarriers.size(), &bufferBarriers[0], |
| 0, (const VkImageMemoryBarrier*)DE_NULL); |
| } |
| } |
| |
| class PixelValue |
| { |
| public: |
| PixelValue (const Maybe<bool>& x = nothing<bool>(), |
| const Maybe<bool>& y = nothing<bool>(), |
| const Maybe<bool>& z = nothing<bool>(), |
| const Maybe<bool>& w = nothing<bool>()); |
| |
| void setUndefined (size_t ndx); |
| void setValue (size_t ndx, bool value); |
| Maybe<bool> getValue (size_t ndx) const; |
| |
| private: |
| deUint16 m_status; |
| }; |
| |
| PixelValue::PixelValue (const Maybe<bool>& x, |
| const Maybe<bool>& y, |
| const Maybe<bool>& z, |
| const Maybe<bool>& w) |
| : m_status (0) |
| { |
| const Maybe<bool> values[] = |
| { |
| x, y, z, w |
| }; |
| |
| for (size_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(values); ndx++) |
| { |
| if (values[ndx]) |
| setValue(ndx, *values[ndx]); |
| else |
| setUndefined(ndx); |
| } |
| |
| DE_ASSERT(m_status <= 0xFFu); |
| } |
| |
| void PixelValue::setUndefined (size_t ndx) |
| { |
| DE_ASSERT(ndx < 4); |
| DE_ASSERT(m_status <= 0xFFu); |
| |
| m_status &= (deUint16)~(0x1u << (deUint16)(ndx * 2)); |
| DE_ASSERT(m_status <= 0xFFu); |
| } |
| |
| void PixelValue::setValue (size_t ndx, bool value) |
| { |
| DE_ASSERT(ndx < 4); |
| DE_ASSERT(m_status <= 0xFFu); |
| |
| m_status = (deUint16)(m_status | (deUint16)(0x1u << (ndx * 2))); |
| |
| if (value) |
| m_status = (deUint16)(m_status | (deUint16)(0x1u << (ndx * 2 + 1))); |
| else |
| m_status &= (deUint16)~(0x1u << (deUint16)(ndx * 2 + 1)); |
| |
| DE_ASSERT(m_status <= 0xFFu); |
| } |
| |
| Maybe<bool> PixelValue::getValue (size_t ndx) const |
| { |
| DE_ASSERT(ndx < 4); |
| DE_ASSERT(m_status <= 0xFFu); |
| |
| if ((m_status & (0x1u << (deUint16)(ndx * 2))) != 0) |
| { |
| return just((m_status & (0x1u << (deUint32)(ndx * 2 + 1))) != 0); |
| } |
| else |
| return nothing<bool>(); |
| } |
| |
| void clearReferenceValues (vector<PixelValue>& values, |
| const UVec2& targetSize, |
| const UVec2& offset, |
| const UVec2& size, |
| const BVec4& mask, |
| const PixelValue& value) |
| { |
| DE_ASSERT(targetSize.x() * targetSize.y() == (deUint32)values.size()); |
| DE_ASSERT(offset.x() + size.x() <= targetSize.x()); |
| DE_ASSERT(offset.y() + size.y() <= targetSize.y()); |
| |
| for (deUint32 y = offset.y(); y < offset.y() + size.y(); y++) |
| for (deUint32 x = offset.x(); x < offset.x() + size.x(); x++) |
| { |
| for (int compNdx = 0; compNdx < 4; compNdx++) |
| { |
| if (mask[compNdx]) |
| { |
| if (value.getValue(compNdx)) |
| values[x + y * targetSize.x()].setValue(compNdx, *value.getValue(compNdx)); |
| else |
| values[x + y * targetSize.x()].setUndefined(compNdx); |
| } |
| } |
| } |
| } |
| |
| void markUndefined (vector<PixelValue>& values, |
| const BVec4& mask, |
| const UVec2& targetSize, |
| const UVec2& offset, |
| const UVec2& size) |
| { |
| DE_ASSERT(targetSize.x() * targetSize.y() == (deUint32)values.size()); |
| |
| for (deUint32 y = offset.y(); y < offset.y() + size.y(); y++) |
| for (deUint32 x = offset.x(); x < offset.x() + size.x(); x++) |
| { |
| for (int compNdx = 0; compNdx < 4; compNdx++) |
| { |
| if (mask[compNdx]) |
| values[x + y * targetSize.x()].setUndefined(compNdx); |
| } |
| } |
| } |
| |
| PixelValue clearValueToPixelValue (const VkClearValue& value, |
| const tcu::TextureFormat& format, |
| const DepthValuesArray& depthValues) |
| { |
| const bool isDepthAttachment = hasDepthComponent(format.order); |
| const bool isStencilAttachment = hasStencilComponent(format.order); |
| const bool isDepthOrStencilAttachment = isDepthAttachment || isStencilAttachment; |
| PixelValue pixelValue; |
| |
| if (isDepthOrStencilAttachment) |
| { |
| if (isDepthAttachment) |
| { |
| if (value.depthStencil.depth == float(depthValues[1]) / 255.0f) |
| pixelValue.setValue(0, true); |
| else if (value.depthStencil.depth == float(depthValues[0]) / 255.0f) |
| pixelValue.setValue(0, false); |
| else |
| DE_FATAL("Unknown depth value"); |
| } |
| |
| if (isStencilAttachment) |
| { |
| if (value.depthStencil.stencil == 0xFFu) |
| pixelValue.setValue(1, true); |
| else if (value.depthStencil.stencil == 0x0u) |
| pixelValue.setValue(1, false); |
| else |
| DE_FATAL("Unknown stencil value"); |
| } |
| } |
| else |
| { |
| const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type); |
| const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(format); |
| |
| switch (channelClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| for (int i = 0; i < 4; i++) |
| { |
| if (channelMask[i]) |
| { |
| if (value.color.int32[i] == 1) |
| pixelValue.setValue(i, true); |
| else if (value.color.int32[i] == 0) |
| pixelValue.setValue(i, false); |
| else |
| DE_FATAL("Unknown clear color value"); |
| } |
| } |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| for (int i = 0; i < 4; i++) |
| { |
| if (channelMask[i]) |
| { |
| if (value.color.uint32[i] == 1u) |
| pixelValue.setValue(i, true); |
| else if (value.color.uint32[i] == 0u) |
| pixelValue.setValue(i, false); |
| else |
| DE_FATAL("Unknown clear color value"); |
| } |
| } |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| for (int i = 0; i < 4; i++) |
| { |
| if (channelMask[i]) |
| { |
| if (value.color.float32[i] == 1.0f) |
| pixelValue.setValue(i, true); |
| else if (value.color.float32[i] == 0.0f) |
| pixelValue.setValue(i, false); |
| else |
| DE_FATAL("Unknown clear color value"); |
| } |
| } |
| break; |
| |
| default: |
| DE_FATAL("Unknown channel class"); |
| } |
| } |
| |
| return pixelValue; |
| } |
| |
| void renderReferenceValues (vector<vector<PixelValue> >& referenceAttachments, |
| const RenderPass& renderPassInfo, |
| const UVec2& targetSize, |
| const vector<Maybe<VkClearValue> >& imageClearValues, |
| const vector<Maybe<VkClearValue> >& renderPassClearValues, |
| const vector<SubpassRenderInfo>& subpassRenderInfo, |
| const UVec2& renderPos, |
| const UVec2& renderSize, |
| const deUint32 drawStartNdx, |
| const DepthValuesArray& depthValues) |
| { |
| const vector<Subpass>& subpasses = renderPassInfo.getSubpasses(); |
| vector<bool> attachmentUsed (renderPassInfo.getAttachments().size(), false); |
| |
| referenceAttachments.resize(renderPassInfo.getAttachments().size()); |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++) |
| { |
| const Attachment attachment = renderPassInfo.getAttachments()[attachmentNdx]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| vector<PixelValue>& reference = referenceAttachments[attachmentNdx]; |
| |
| reference.resize(targetSize.x() * targetSize.y()); |
| |
| if (imageClearValues[attachmentNdx]) |
| clearReferenceValues(reference, targetSize, UVec2(0, 0), targetSize, BVec4(true), clearValueToPixelValue(*imageClearValues[attachmentNdx], format, depthValues)); |
| } |
| |
| for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++) |
| { |
| const Subpass& subpass = subpasses[subpassNdx]; |
| const SubpassRenderInfo& renderInfo = subpassRenderInfo[subpassNdx]; |
| const vector<AttachmentReference>& colorAttachments = subpass.getColorAttachments(); |
| |
| // Apply load op if attachment was used for the first time |
| for (size_t attachmentNdx = 0; attachmentNdx < colorAttachments.size(); attachmentNdx++) |
| { |
| const deUint32 attachmentIndex = getAttachmentNdx(colorAttachments, attachmentNdx); |
| |
| if (!attachmentUsed[attachmentIndex] && colorAttachments[attachmentNdx].getAttachment() != VK_ATTACHMENT_UNUSED) |
| { |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| vector<PixelValue>& reference = referenceAttachments[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| |
| DE_ASSERT(!tcu::hasDepthComponent(format.order)); |
| DE_ASSERT(!tcu::hasStencilComponent(format.order)); |
| |
| if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR) |
| clearReferenceValues(reference, targetSize, renderPos, renderSize, BVec4(true), clearValueToPixelValue(*renderPassClearValues[attachmentIndex], format, depthValues)); |
| else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE) |
| markUndefined(reference, BVec4(true), targetSize, renderPos, renderSize); |
| |
| attachmentUsed[attachmentIndex] = true; |
| } |
| } |
| |
| // Apply load op to depth/stencil attachment if it was used for the first time |
| if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED) |
| { |
| const deUint32 attachmentIndex = subpass.getDepthStencilAttachment().getAttachment(); |
| |
| // Apply load op if attachment was used for the first time |
| if (!attachmentUsed[attachmentIndex]) |
| { |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| vector<PixelValue>& reference = referenceAttachments[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| |
| if (tcu::hasDepthComponent(format.order)) |
| { |
| if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR) |
| clearReferenceValues(reference, targetSize, renderPos, renderSize, BVec4(true, false, false, false), clearValueToPixelValue(*renderPassClearValues[attachmentIndex], format, depthValues)); |
| else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE) |
| markUndefined(reference, BVec4(true, false, false, false), targetSize, renderPos, renderSize); |
| } |
| |
| if (tcu::hasStencilComponent(format.order)) |
| { |
| if (attachment.getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR) |
| clearReferenceValues(reference, targetSize, renderPos, renderSize, BVec4(false, true, false, false), clearValueToPixelValue(*renderPassClearValues[attachmentIndex], format, depthValues)); |
| else if (attachment.getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE) |
| markUndefined(reference, BVec4(false, true, false, false), targetSize, renderPos, renderSize); |
| } |
| |
| attachmentUsed[attachmentIndex] = true; |
| } |
| } |
| |
| for (size_t colorClearNdx = 0; colorClearNdx < renderInfo.getColorClears().size(); colorClearNdx++) |
| { |
| const ColorClear& colorClear = renderInfo.getColorClears()[colorClearNdx]; |
| const UVec2 offset = colorClear.getOffset(); |
| const UVec2 size = colorClear.getSize(); |
| const deUint32 attachmentIndex = subpass.getColorAttachments()[colorClearNdx].getAttachment(); |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| vector<PixelValue>& reference = referenceAttachments[attachmentIndex]; |
| VkClearValue value; |
| |
| value.color = colorClear.getColor(); |
| |
| clearReferenceValues(reference, targetSize, offset, size, BVec4(true), clearValueToPixelValue(value, format, depthValues)); |
| } |
| |
| if (renderInfo.getDepthStencilClear()) |
| { |
| const DepthStencilClear& dsClear = *renderInfo.getDepthStencilClear(); |
| const UVec2 offset = dsClear.getOffset(); |
| const UVec2 size = dsClear.getSize(); |
| const deUint32 attachmentIndex = subpass.getDepthStencilAttachment().getAttachment(); |
| const VkImageLayout layout = subpass.getDepthStencilAttachment().getImageLayout(); |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| const bool hasStencil = tcu::hasStencilComponent(format.order) |
| && layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; |
| const bool hasDepth = tcu::hasDepthComponent(format.order) |
| && layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; |
| vector<PixelValue>& reference = referenceAttachments[attachmentIndex]; |
| VkClearValue value; |
| |
| value.depthStencil.depth = dsClear.getDepth(); |
| value.depthStencil.stencil = dsClear.getStencil(); |
| |
| clearReferenceValues(reference, targetSize, offset, size, BVec4(hasDepth, hasStencil, false, false), clearValueToPixelValue(value, format, depthValues)); |
| } |
| |
| if (renderInfo.getRenderQuad()) |
| { |
| const RenderQuad& renderQuad = *renderInfo.getRenderQuad(); |
| const Vec2 posA = renderQuad.getCornerA(); |
| const Vec2 posB = renderQuad.getCornerB(); |
| const Vec2 origin = Vec2((float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y()) + Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f); |
| const Vec2 p = Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f); |
| const IVec2 posAI (deRoundFloatToInt32(origin.x() + (p.x() * posA.x())), |
| deRoundFloatToInt32(origin.y() + (p.y() * posA.y()))); |
| const IVec2 posBI (deRoundFloatToInt32(origin.x() + (p.x() * posB.x())), |
| deRoundFloatToInt32(origin.y() + (p.y() * posB.y()))); |
| |
| DE_ASSERT(posAI.x() < posBI.x()); |
| DE_ASSERT(posAI.y() < posBI.y()); |
| |
| if (subpass.getInputAttachments().empty()) |
| { |
| for (size_t attachmentRefNdx = drawStartNdx; attachmentRefNdx < subpass.getColorAttachments().size(); attachmentRefNdx++) |
| { |
| const deUint32 attachmentIndex = subpass.getColorAttachments()[attachmentRefNdx].getAttachment(); |
| |
| if (attachmentIndex == VK_ATTACHMENT_UNUSED) |
| continue; |
| |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(format); |
| vector<PixelValue>& reference = referenceAttachments[attachmentIndex]; |
| |
| for (int y = posAI.y(); y < (int)posBI.y(); y++) |
| for (int x = posAI.x(); x < (int)posBI.x(); x++) |
| { |
| for (int compNdx = 0; compNdx < 4; compNdx++) |
| { |
| const size_t index = subpassNdx + attachmentIndex + compNdx; |
| const BoolOp op = boolOpFromIndex(index); |
| const bool boolX = x % 2 == (int)(index % 2); |
| const bool boolY = y % 2 == (int)((index / 2) % 2); |
| |
| if (channelMask[compNdx]) |
| reference[x + y * targetSize.x()].setValue(compNdx, performBoolOp(op, boolX, boolY)); |
| } |
| } |
| } |
| |
| if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED) |
| { |
| const deUint32 attachmentIndex = subpass.getDepthStencilAttachment().getAttachment(); |
| const VkImageLayout layout = subpass.getDepthStencilAttachment().getImageLayout(); |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| vector<PixelValue>& reference = referenceAttachments[attachmentIndex]; |
| |
| for (int y = posAI.y(); y < (int)posBI.y(); y++) |
| for (int x = posAI.x(); x < (int)posBI.x(); x++) |
| { |
| if (tcu::hasDepthComponent(format.order) |
| && layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL |
| && layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| const size_t index = subpassNdx + 1; |
| const BoolOp op = boolOpFromIndex(index); |
| const bool boolX = x % 2 == (int)(index % 2); |
| const bool boolY = y % 2 == (int)((index / 2) % 2); |
| |
| reference[x + y * targetSize.x()].setValue(0, performBoolOp(op, boolX, boolY)); |
| } |
| |
| if (tcu::hasStencilComponent(format.order) |
| && layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL |
| && layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL) |
| { |
| const size_t index = subpassNdx; |
| reference[x + y * targetSize.x()].setValue(1, (index % 2) == 0); |
| } |
| } |
| } |
| } |
| else |
| { |
| size_t outputComponentCount = 0; |
| vector<Maybe<bool> > inputs; |
| |
| DE_ASSERT(posAI.x() < posBI.x()); |
| DE_ASSERT(posAI.y() < posBI.y()); |
| |
| for (size_t attachmentRefNdx = 0; attachmentRefNdx < subpass.getColorAttachments().size(); attachmentRefNdx++) |
| { |
| const deUint32 attachmentIndex = subpass.getColorAttachments()[attachmentRefNdx].getAttachment(); |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| const int componentCount = tcu::getNumUsedChannels(format.order); |
| |
| outputComponentCount += (size_t)componentCount; |
| } |
| |
| if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED |
| && subpass.getDepthStencilAttachment().getImageLayout() != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL |
| && subpass.getDepthStencilAttachment().getImageLayout() != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| const Attachment& attachment (renderPassInfo.getAttachments()[subpass.getDepthStencilAttachment().getAttachment()]); |
| const tcu::TextureFormat format (mapVkFormat(attachment.getFormat())); |
| |
| if (tcu::hasDepthComponent(format.order)) |
| outputComponentCount++; |
| } |
| |
| if (outputComponentCount > 0) |
| { |
| for (int y = posAI.y(); y < (int)posBI.y(); y++) |
| for (int x = posAI.x(); x < (int)posBI.x(); x++) |
| { |
| for (size_t inputAttachmentNdx = 0; inputAttachmentNdx < subpass.getInputAttachments().size(); inputAttachmentNdx++) |
| { |
| const deUint32 attachmentIndex = subpass.getInputAttachments()[inputAttachmentNdx].getAttachment(); |
| const VkImageLayout layout = subpass.getInputAttachments()[inputAttachmentNdx].getImageLayout(); |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| const int componentCount = tcu::getNumUsedChannels(format.order); |
| |
| for (int compNdx = 0; compNdx < componentCount; compNdx++) |
| { |
| if ((compNdx != 0 || layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL) |
| && (compNdx != 1 || layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)) |
| { |
| inputs.push_back(referenceAttachments[attachmentIndex][x + y * targetSize.x()].getValue(compNdx)); |
| } |
| } |
| } |
| |
| const size_t inputsPerOutput = inputs.size() >= outputComponentCount |
| ? ((inputs.size() / outputComponentCount) |
| + ((inputs.size() % outputComponentCount) != 0 ? 1 : 0)) |
| : 1; |
| |
| size_t outputValueNdx = 0; |
| |
| for (size_t attachmentRefNdx = 0; attachmentRefNdx < subpass.getColorAttachments().size(); attachmentRefNdx++) |
| { |
| const deUint32 attachmentIndex = subpass.getColorAttachments()[attachmentRefNdx].getAttachment(); |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| vector<PixelValue>& reference = referenceAttachments[attachmentIndex]; |
| const int componentCount = tcu::getNumUsedChannels(format.order); |
| |
| for (int compNdx = 0; compNdx < componentCount; compNdx++) |
| { |
| const size_t index = subpassNdx + attachmentIndex + outputValueNdx; |
| const BoolOp op = boolOpFromIndex(index); |
| const bool boolX = x % 2 == (int)(index % 2); |
| const bool boolY = y % 2 == (int)((index / 2) % 2); |
| Maybe<bool> output = tcu::just(performBoolOp(op, boolX, boolY)); |
| |
| for (size_t i = 0; i < inputsPerOutput; i++) |
| { |
| if (!output) |
| break; |
| else if (!inputs[((outputValueNdx + compNdx) * inputsPerOutput + i) % inputs.size()]) |
| output = tcu::nothing<bool>(); |
| else |
| output = (*output) == (*inputs[((outputValueNdx + compNdx) * inputsPerOutput + i) % inputs.size()]); |
| } |
| |
| if (output) |
| reference[x + y * targetSize.x()].setValue(compNdx, *output); |
| else |
| reference[x + y * targetSize.x()].setUndefined(compNdx); |
| } |
| |
| outputValueNdx += componentCount; |
| } |
| |
| if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED |
| && subpass.getDepthStencilAttachment().getImageLayout() != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL |
| && subpass.getDepthStencilAttachment().getImageLayout() != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| const deUint32 attachmentIndex = subpass.getDepthStencilAttachment().getAttachment(); |
| vector<PixelValue>& reference = referenceAttachments[attachmentIndex]; |
| const size_t index = subpassNdx + attachmentIndex; |
| const BoolOp op = boolOpFromIndex(index); |
| const bool boolX = x % 2 == (int)(index % 2); |
| const bool boolY = y % 2 == (int)((index / 2) % 2); |
| Maybe<bool> output = tcu::just(performBoolOp(op, boolX, boolY)); |
| |
| for (size_t i = 0; i < inputsPerOutput; i++) |
| { |
| if (!output) |
| break; |
| else if (inputs[(outputValueNdx * inputsPerOutput + i) % inputs.size()]) |
| output = (*output) == (*inputs[(outputValueNdx * inputsPerOutput + i) % inputs.size()]); |
| else |
| output = tcu::nothing<bool>(); |
| } |
| |
| if (output) |
| reference[x + y * targetSize.x()].setValue(0, *output); |
| else |
| reference[x + y * targetSize.x()].setUndefined(0); |
| } |
| |
| inputs.clear(); |
| } |
| } |
| |
| if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED |
| && subpass.getDepthStencilAttachment().getImageLayout() != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL |
| && subpass.getDepthStencilAttachment().getImageLayout() != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL) |
| { |
| const deUint32 attachmentIndex = subpass.getDepthStencilAttachment().getAttachment(); |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| vector<PixelValue>& reference = referenceAttachments[attachmentIndex]; |
| |
| if (tcu::hasStencilComponent(format.order)) |
| { |
| for (int y = posAI.y(); y < (int)posBI.y(); y++) |
| for (int x = posAI.x(); x < (int)posBI.x(); x++) |
| { |
| const size_t index = subpassNdx; |
| reference[x + y * targetSize.x()].setValue(1, (index % 2) == 0); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| // Mark all attachments that were used but not stored as undefined |
| for (size_t attachmentIndex = 0; attachmentIndex < renderPassInfo.getAttachments().size(); attachmentIndex++) |
| { |
| const Attachment attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| vector<PixelValue>& reference = referenceAttachments[attachmentIndex]; |
| const bool isStencilAttachment = hasStencilComponent(format.order); |
| const bool isDepthOrStencilAttachment = hasDepthComponent(format.order) || isStencilAttachment; |
| |
| if (attachmentUsed[attachmentIndex] && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE) |
| { |
| if (isDepthOrStencilAttachment) |
| markUndefined(reference, BVec4(true, false, false, false), targetSize, renderPos, renderSize); |
| else |
| markUndefined(reference, BVec4(true), targetSize, renderPos, renderSize); |
| } |
| |
| if (attachmentUsed[attachmentIndex] && isStencilAttachment && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE) |
| markUndefined(reference, BVec4(false, true, false, false), targetSize, renderPos, renderSize); |
| } |
| } |
| |
| void renderReferenceImagesFromValues (vector<tcu::TextureLevel>& referenceImages, |
| const vector<vector<PixelValue> >& referenceValues, |
| const UVec2& targetSize, |
| const RenderPass& renderPassInfo, |
| const DepthValuesArray& depthValues) |
| { |
| referenceImages.resize(referenceValues.size()); |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++) |
| { |
| const Attachment attachment = renderPassInfo.getAttachments()[attachmentNdx]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| const vector<PixelValue>& reference = referenceValues[attachmentNdx]; |
| const bool hasDepth = tcu::hasDepthComponent(format.order); |
| const bool hasStencil = tcu::hasStencilComponent(format.order); |
| const bool hasDepthOrStencil = hasDepth || hasStencil; |
| tcu::TextureLevel& referenceImage = referenceImages[attachmentNdx]; |
| |
| referenceImage.setStorage(format, targetSize.x(), targetSize.y()); |
| |
| if (hasDepthOrStencil) |
| { |
| if (hasDepth) |
| { |
| const PixelBufferAccess depthAccess (tcu::getEffectiveDepthStencilAccess(referenceImage.getAccess(), tcu::Sampler::MODE_DEPTH)); |
| |
| for (deUint32 y = 0; y < targetSize.y(); y++) |
| for (deUint32 x = 0; x < targetSize.x(); x++) |
| { |
| if (reference[x + y * targetSize.x()].getValue(0)) |
| { |
| if (*reference[x + y * targetSize.x()].getValue(0)) |
| depthAccess.setPixDepth(float(depthValues[1]) / 255.0f, x, y); |
| else |
| depthAccess.setPixDepth(float(depthValues[0]) / 255.0f, x, y); |
| } |
| else // Fill with 3x3 grid |
| depthAccess.setPixDepth(((x / 3) % 2) == ((y / 3) % 2) ? 0.33f : 0.66f, x, y); |
| } |
| } |
| |
| if (hasStencil) |
| { |
| const PixelBufferAccess stencilAccess (tcu::getEffectiveDepthStencilAccess(referenceImage.getAccess(), tcu::Sampler::MODE_STENCIL)); |
| |
| for (deUint32 y = 0; y < targetSize.y(); y++) |
| for (deUint32 x = 0; x < targetSize.x(); x++) |
| { |
| if (reference[x + y * targetSize.x()].getValue(1)) |
| { |
| if (*reference[x + y * targetSize.x()].getValue(1)) |
| stencilAccess.setPixStencil(0xFFu, x, y); |
| else |
| stencilAccess.setPixStencil(0x0u, x, y); |
| } |
| else // Fill with 3x3 grid |
| stencilAccess.setPixStencil(((x / 3) % 2) == ((y / 3) % 2) ? 85 : 170, x, y); |
| } |
| } |
| } |
| else |
| { |
| for (deUint32 y = 0; y < targetSize.y(); y++) |
| for (deUint32 x = 0; x < targetSize.x(); x++) |
| { |
| tcu::Vec4 color; |
| |
| for (int compNdx = 0; compNdx < 4; compNdx++) |
| { |
| if (reference[x + y * targetSize.x()].getValue(compNdx)) |
| { |
| if (*reference[x + y * targetSize.x()].getValue(compNdx)) |
| color[compNdx] = 1.0f; |
| else |
| color[compNdx] = 0.0f; |
| } |
| else // Fill with 3x3 grid |
| color[compNdx] = ((compNdx + (x / 3)) % 2) == ((y / 3) % 2) ? 0.33f : 0.66f; |
| } |
| |
| referenceImage.getAccess().setPixel(color, x, y); |
| } |
| } |
| } |
| } |
| |
| bool verifyColorAttachment (const vector<PixelValue>& reference, |
| const ConstPixelBufferAccess& result, |
| const PixelBufferAccess& errorImage, |
| const deBool useFormatCompCount) |
| { |
| const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); |
| const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); |
| bool ok = true; |
| |
| DE_ASSERT(result.getWidth() * result.getHeight() == (int)reference.size()); |
| DE_ASSERT(result.getWidth() == errorImage.getWidth()); |
| DE_ASSERT(result.getHeight() == errorImage.getHeight()); |
| |
| for (int y = 0; y < result.getHeight(); y++) |
| for (int x = 0; x < result.getWidth(); x++) |
| { |
| const Vec4 resultColor = result.getPixel(x, y); |
| const PixelValue& referenceValue = reference[x + y * result.getWidth()]; |
| bool pixelOk = true; |
| const deUint32 componentCount = useFormatCompCount ? (deUint32)tcu::getNumUsedChannels(result.getFormat().order) : 4; |
| |
| for (deUint32 compNdx = 0; compNdx < componentCount; compNdx++) |
| { |
| const Maybe<bool> maybeValue = referenceValue.getValue(compNdx); |
| |
| if (maybeValue) |
| { |
| const bool value = *maybeValue; |
| |
| if ((value && (resultColor[compNdx] != 1.0f)) |
| || (!value && resultColor[compNdx] != 0.0f)) |
| pixelOk = false; |
| } |
| } |
| |
| if (!pixelOk) |
| { |
| errorImage.setPixel(red, x, y); |
| ok = false; |
| } |
| else |
| errorImage.setPixel(green, x, y); |
| } |
| |
| return ok; |
| } |
| |
| // Setting the alpha value to 1.0f by default helps visualization when the alpha channel is not used. |
| const tcu::Vec4 kDefaultColorForLog {0.0f, 0.0f, 0.0f, 1.0f}; |
| const float kTrueComponent = 1.0f; |
| const float kFalseComponent = 0.5f; |
| const float kUnsetComponentLow = 0.0f; |
| const float kUnsetComponentHigh = 0.25f; |
| |
| std::unique_ptr<tcu::TextureLevel> renderColorImageForLog (const ConstPixelBufferAccess& image, int numChannels) |
| { |
| // Same channel order, but using UNORM_INT8 for the color format. |
| const auto order = image.getFormat().order; |
| const tcu::TextureFormat loggableFormat {order, tcu::TextureFormat::UNORM_INT8}; |
| const int width = image.getWidth(); |
| const int height = image.getHeight(); |
| std::unique_ptr<tcu::TextureLevel> result {new tcu::TextureLevel{loggableFormat, width, height}}; |
| auto access = result->getAccess(); |
| tcu::Vec4 outColor = kDefaultColorForLog; |
| |
| for (int x = 0; x < width; ++x) |
| for (int y = 0; y < height; ++y) |
| { |
| const auto value = image.getPixel(x, y); |
| for (int c = 0; c < numChannels; ++c) |
| { |
| if (value[c] == 0.0f) |
| outColor[c] = kFalseComponent; |
| else if (value[c] == 1.0f) |
| outColor[c] = kTrueComponent; |
| else |
| DE_ASSERT(false); |
| } |
| access.setPixel(outColor, x, y); |
| } |
| |
| return result; |
| } |
| |
| std::unique_ptr<tcu::TextureLevel> renderColorImageForLog (const vector<PixelValue>& reference, const UVec2& targetSize, int numChannels) |
| { |
| const tcu::TextureFormat loggableFormat {tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8}; |
| const int width = static_cast<int>(targetSize.x()); |
| const int height = static_cast<int>(targetSize.y()); |
| std::unique_ptr<tcu::TextureLevel> result {new tcu::TextureLevel{loggableFormat, width, height}}; |
| auto access = result->getAccess(); |
| tcu::Vec4 outColor = kDefaultColorForLog; |
| |
| for (int x = 0; x < width; ++x) |
| for (int y = 0; y < height; ++y) |
| { |
| const int index = x + y * width; |
| for (int c = 0; c < numChannels; ++c) |
| { |
| const auto maybeValue = reference[index].getValue(c); |
| if (maybeValue) |
| outColor[c] = ((*maybeValue) ? kTrueComponent : kFalseComponent); |
| else |
| outColor[c] = ((((x / 3) % 2) == ((y / 3) % 2)) ? kUnsetComponentLow : kUnsetComponentHigh); |
| } |
| access.setPixel(outColor, x, y); |
| } |
| |
| return result; |
| } |
| |
| bool verifyDepthAttachment (const vector<PixelValue>& reference, |
| const ConstPixelBufferAccess& result, |
| const PixelBufferAccess& errorImage, |
| const DepthValuesArray& depthValues, |
| float epsilon) |
| { |
| const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); |
| const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); |
| bool ok = true; |
| |
| DE_ASSERT(result.getWidth() * result.getHeight() == (int)reference.size()); |
| DE_ASSERT(result.getWidth() == errorImage.getWidth()); |
| DE_ASSERT(result.getHeight() == errorImage.getHeight()); |
| |
| for (int y = 0; y < result.getHeight(); y++) |
| for (int x = 0; x < result.getWidth(); x++) |
| { |
| bool pixelOk = true; |
| |
| const float resultDepth = result.getPixDepth(x, y); |
| const PixelValue& referenceValue = reference[x + y * result.getWidth()]; |
| const Maybe<bool> maybeValue = referenceValue.getValue(0); |
| |
| if (maybeValue) |
| { |
| const bool value = *maybeValue; |
| |
| if ((value && !depthsEqual(resultDepth, float(depthValues[1]) / 255.0f, epsilon)) |
| || (!value && !depthsEqual(resultDepth, float(depthValues[0]) / 255.0f, epsilon))) |
| pixelOk = false; |
| } |
| |
| if (!pixelOk) |
| { |
| errorImage.setPixel(red, x, y); |
| ok = false; |
| } |
| else |
| errorImage.setPixel(green, x, y); |
| } |
| |
| return ok; |
| } |
| |
| bool verifyStencilAttachment (const vector<PixelValue>& reference, |
| const ConstPixelBufferAccess& result, |
| const PixelBufferAccess& errorImage) |
| { |
| const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); |
| const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); |
| bool ok = true; |
| |
| DE_ASSERT(result.getWidth() * result.getHeight() == (int)reference.size()); |
| DE_ASSERT(result.getWidth() == errorImage.getWidth()); |
| DE_ASSERT(result.getHeight() == errorImage.getHeight()); |
| |
| for (int y = 0; y < result.getHeight(); y++) |
| for (int x = 0; x < result.getWidth(); x++) |
| { |
| bool pixelOk = true; |
| |
| const deUint32 resultStencil = result.getPixStencil(x, y); |
| const PixelValue& referenceValue = reference[x + y * result.getWidth()]; |
| const Maybe<bool> maybeValue = referenceValue.getValue(1); |
| |
| if (maybeValue) |
| { |
| const bool value = *maybeValue; |
| |
| if ((value && (resultStencil != 0xFFu)) |
| || (!value && resultStencil != 0x0u)) |
| pixelOk = false; |
| } |
| |
| if (!pixelOk) |
| { |
| errorImage.setPixel(red, x, y); |
| ok = false; |
| } |
| else |
| errorImage.setPixel(green, x, y); |
| } |
| |
| return ok; |
| } |
| |
| bool logAndVerifyImages (TestLog& log, |
| const DeviceInterface& vk, |
| VkDevice device, |
| const vector<de::SharedPtr<AttachmentResources> >& attachmentResources, |
| const vector<bool>& attachmentIsLazy, |
| const RenderPass& renderPassInfo, |
| const vector<Maybe<VkClearValue> >& renderPassClearValues, |
| const vector<Maybe<VkClearValue> >& imageClearValues, |
| const vector<SubpassRenderInfo>& subpassRenderInfo, |
| const UVec2& targetSize, |
| const TestConfig& config) |
| { |
| vector<vector<PixelValue> > referenceValues; |
| vector<tcu::TextureLevel> referenceAttachments; |
| bool isOk = true; |
| |
| log << TestLog::Message << "Reference images fill undefined pixels with 3x3 grid pattern." << TestLog::EndMessage; |
| |
| renderReferenceValues(referenceValues, renderPassInfo, targetSize, imageClearValues, renderPassClearValues, subpassRenderInfo, config.renderPos, config.renderSize, config.drawStartNdx, config.depthValues); |
| renderReferenceImagesFromValues(referenceAttachments, referenceValues, targetSize, renderPassInfo, config.depthValues); |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++) |
| { |
| if (!attachmentIsLazy[attachmentNdx]) |
| { |
| bool attachmentOK = true; |
| const Attachment attachment = renderPassInfo.getAttachments()[attachmentNdx]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| |
| if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order)) |
| { |
| const tcu::TextureFormat depthFormat = getDepthCopyFormat(attachment.getFormat()); |
| void* const depthPtr = attachmentResources[attachmentNdx]->getResultMemory().getHostPtr(); |
| |
| const tcu::TextureFormat stencilFormat = getStencilCopyFormat(attachment.getFormat()); |
| void* const stencilPtr = attachmentResources[attachmentNdx]->getSecondaryResultMemory().getHostPtr(); |
| |
| invalidateAlloc(vk, device, attachmentResources[attachmentNdx]->getResultMemory()); |
| invalidateAlloc(vk, device, attachmentResources[attachmentNdx]->getSecondaryResultMemory()); |
| |
| { |
| bool depthOK = true; |
| bool stencilOK = true; |
| const ConstPixelBufferAccess depthAccess (depthFormat, targetSize.x(), targetSize.y(), 1, depthPtr); |
| const ConstPixelBufferAccess stencilAccess (stencilFormat, targetSize.x(), targetSize.y(), 1, stencilPtr); |
| tcu::TextureLevel depthErrorImage (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(), targetSize.y()); |
| tcu::TextureLevel stencilErrorImage (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(), targetSize.y()); |
| |
| if (renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE |
| && !verifyDepthAttachment(referenceValues[attachmentNdx], depthAccess, depthErrorImage.getAccess(), config.depthValues, requiredDepthEpsilon(attachment.getFormat()))) |
| { |
| depthOK = false; |
| } |
| |
| if (renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE |
| && !verifyStencilAttachment(referenceValues[attachmentNdx], stencilAccess, stencilErrorImage.getAccess())) |
| { |
| stencilOK = false; |
| } |
| |
| if (!depthOK || !stencilOK) |
| { |
| log << TestLog::ImageSet("TestImages", "Output depth and stencil attachments, reference images and error masks"); |
| log << TestLog::Image("Attachment" + de::toString(attachmentNdx) + "Depth", "Attachment " + de::toString(attachmentNdx) + " Depth", depthAccess); |
| log << TestLog::Image("Attachment" + de::toString(attachmentNdx) + "Stencil", "Attachment " + de::toString(attachmentNdx) + " Stencil", stencilAccess); |
| log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx), "Attachment reference " + de::toString(attachmentNdx), referenceAttachments[attachmentNdx].getAccess()); |
| |
| if (!depthOK) |
| log << TestLog::Image("DepthAttachmentError" + de::toString(attachmentNdx), "Depth Attachment Error " + de::toString(attachmentNdx), depthErrorImage.getAccess()); |
| |
| if (!stencilOK) |
| log << TestLog::Image("StencilAttachmentError" + de::toString(attachmentNdx), "Stencil Attachment Error " + de::toString(attachmentNdx), stencilErrorImage.getAccess()); |
| |
| log << TestLog::EndImageSet; |
| |
| attachmentOK = false; |
| } |
| } |
| } |
| else |
| { |
| void* const ptr = attachmentResources[attachmentNdx]->getResultMemory().getHostPtr(); |
| |
| invalidateAlloc(vk, device, attachmentResources[attachmentNdx]->getResultMemory()); |
| |
| bool depthOK = true; |
| bool stencilOK = true; |
| bool colorOK = true; |
| const ConstPixelBufferAccess access (format, targetSize.x(), targetSize.y(), 1, ptr); |
| tcu::TextureLevel errorImage (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(), targetSize.y()); |
| |
| if (tcu::hasDepthComponent(format.order)) |
| { |
| if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE || renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE) |
| && !verifyDepthAttachment(referenceValues[attachmentNdx], access, errorImage.getAccess(), config.depthValues, requiredDepthEpsilon(attachment.getFormat()))) |
| { |
| depthOK = false; |
| } |
| } |
| else if (tcu::hasStencilComponent(format.order)) |
| { |
| if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE || renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE) |
| && !verifyStencilAttachment(referenceValues[attachmentNdx], access, errorImage.getAccess())) |
| { |
| stencilOK = false; |
| } |
| } |
| else |
| { |
| if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE || renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE) |
| && !verifyColorAttachment(referenceValues[attachmentNdx], access, errorImage.getAccess(), config.useFormatCompCount)) |
| { |
| colorOK = false; |
| } |
| } |
| |
| if (!depthOK || !stencilOK || !colorOK) |
| { |
| log << TestLog::ImageSet("TestImages", "Output attachment, reference image and error mask"); |
| if (!depthOK || !stencilOK) |
| { |
| // Log without conversions. |
| log << TestLog::Image("Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx), access); |
| log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx), "Attachment reference " + de::toString(attachmentNdx), referenceAttachments[attachmentNdx].getAccess()); |
| } |
| else |
| { |
| // Convert color images to better reflect test status and output in any format. |
| const auto numChannels = tcu::getNumUsedChannels(access.getFormat().order); |
| const auto attachmentForLog = renderColorImageForLog(access, numChannels); |
| const auto referenceForLog = renderColorImageForLog(referenceValues[attachmentNdx], targetSize, numChannels); |
| |
| log << TestLog::Message << "Check the attachment formats and test data to verify which components affect the test result." << TestLog::EndMessage; |
| log << TestLog::Message << "In the reference image, unset pixel components are marked with a 3x3 grid storing values 0.0 and 0.25, pixel components set to false are stored as 0.5 and pixel components set to true are stored as 1.0." << TestLog::EndMessage; |
| log << TestLog::Message << "Output attachment pixel components are always set to 0.5 or 1.0 but may not be taken into account if not set in the reference image." << TestLog::EndMessage; |
| |
| log << TestLog::Image("Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx), attachmentForLog->getAccess()); |
| log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx), "Attachment reference " + de::toString(attachmentNdx), referenceForLog->getAccess()); |
| } |
| log << TestLog::Image("AttachmentError" + de::toString(attachmentNdx), "Attachment Error " + de::toString(attachmentNdx), errorImage.getAccess()); |
| log << TestLog::EndImageSet; |
| |
| attachmentOK = false; |
| } |
| } |
| |
| if (!attachmentOK) |
| isOk = false; |
| } |
| } |
| |
| return isOk; |
| } |
| |
| std::string getInputAttachmentType (VkFormat vkFormat) |
| { |
| const tcu::TextureFormat format = mapVkFormat(vkFormat); |
| const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type); |
| |
| switch (channelClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| return "isubpassInput"; |
| |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| return "usubpassInput"; |
| |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| return "subpassInput"; |
| |
| default: |
| DE_FATAL("Unknown channel class"); |
| return ""; |
| } |
| } |
| |
| std::string getAttachmentType (VkFormat vkFormat, deBool useFormatCompCount) |
| { |
| const tcu::TextureFormat format = mapVkFormat(vkFormat); |
| const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type); |
| const size_t componentCount = (size_t)tcu::getNumUsedChannels(format.order); |
| |
| switch (channelClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| if (useFormatCompCount) |
| return (componentCount == 1 ? "int" : "ivec" + de::toString(componentCount)); |
| else |
| return "ivec4"; |
| |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| if (useFormatCompCount) |
| return (componentCount == 1 ? "uint" : "uvec" + de::toString(componentCount)); |
| else |
| return "uvec4"; |
| |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| if (useFormatCompCount) |
| return (componentCount == 1 ? "float" : "vec" + de::toString(componentCount)); |
| else |
| return "vec4"; |
| |
| default: |
| DE_FATAL("Unknown channel class"); |
| return ""; |
| } |
| } |
| |
| void createTestShaders (SourceCollections& dst, TestConfig config) |
| { |
| if (config.renderTypes & TestConfig::RENDERTYPES_DRAW) |
| { |
| const vector<Subpass>& subpasses = config.renderPass.getSubpasses(); |
| |
| for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++) |
| { |
| const Subpass& subpass = subpasses[subpassNdx]; |
| deUint32 inputAttachmentBinding = 0; |
| std::ostringstream vertexShader; |
| std::ostringstream fragmentShader; |
| |
| vertexShader << "#version 310 es\n" |
| << "layout(location = 0) in highp vec2 a_position;\n" |
| << "void main (void) {\n" |
| << "\tgl_Position = vec4(a_position, 1.0, 1.0);\n" |
| << "}\n"; |
| |
| fragmentShader << "#version 310 es\n" |
| << "precision highp float;\n"; |
| |
| bool hasAnyDepthFormats = false; |
| |
| for (size_t attachmentNdx = config.drawStartNdx; attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++) |
| { |
| const deUint32 attachmentIndex = subpass.getInputAttachments()[attachmentNdx].getAttachment(); |
| const VkImageLayout layout = subpass.getInputAttachments()[attachmentNdx].getImageLayout(); |
| const Attachment attachment = config.renderPass.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| const bool isDepthFormat = tcu::hasDepthComponent(format.order); |
| const bool isStencilFormat = tcu::hasStencilComponent(format.order); |
| |
| if (isDepthFormat || isStencilFormat) |
| { |
| if (isDepthFormat && layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL) |
| { |
| hasAnyDepthFormats = true; |
| fragmentShader << "layout(input_attachment_index = " << attachmentNdx << ", set=0, binding=" << inputAttachmentBinding << ") uniform highp subpassInput i_depth" << attachmentNdx << ";\n"; |
| inputAttachmentBinding++; |
| } |
| |
| if (isStencilFormat && layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| fragmentShader << "layout(input_attachment_index = " << attachmentNdx << ", set=0, binding=" << inputAttachmentBinding << ") uniform highp usubpassInput i_stencil" << attachmentNdx << ";\n"; |
| inputAttachmentBinding++; |
| } |
| } |
| else |
| { |
| const std::string attachmentType = getInputAttachmentType(attachment.getFormat()); |
| |
| fragmentShader << "layout(input_attachment_index = " << attachmentNdx << ", set=0, binding=" << inputAttachmentBinding << ") uniform highp " << attachmentType << " i_color" << attachmentNdx << ";\n"; |
| inputAttachmentBinding++; |
| } |
| } |
| |
| for (size_t attachmentNdx = config.drawStartNdx; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++) |
| { |
| const std::string attachmentType = getAttachmentType(config.renderPass.getAttachments()[getAttachmentNdx(subpass.getColorAttachments(), attachmentNdx)].getFormat(), config.useFormatCompCount); |
| fragmentShader << "layout(location = " << attachmentNdx << ") out highp " << attachmentType << " o_color" << attachmentNdx << ";\n"; |
| } |
| |
| if (hasAnyDepthFormats) |
| fragmentShader << "\nbool depthsEqual(float a, float b, float epsilon) {\n" |
| << "\treturn abs(a - b) <= epsilon;\n}\n\n"; |
| |
| fragmentShader << "void main (void) {\n"; |
| |
| if (subpass.getInputAttachments().empty()) |
| { |
| for (size_t attachmentNdx = config.drawStartNdx; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++) |
| { |
| const deUint32 attachmentIndex = subpass.getColorAttachments()[attachmentNdx].getAttachment(); |
| |
| if (attachmentIndex == VK_ATTACHMENT_UNUSED) |
| continue; |
| |
| const Attachment attachment = config.renderPass.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| const size_t componentCount = config.useFormatCompCount ? (size_t)tcu::getNumUsedChannels(format.order) : 4; |
| const std::string attachmentType = getAttachmentType(attachment.getFormat(), config.useFormatCompCount); |
| |
| fragmentShader << "\to_color" << attachmentNdx << " = " << attachmentType << "(" << attachmentType + "("; |
| |
| for (size_t compNdx = 0; compNdx < componentCount; compNdx++) |
| { |
| const size_t index = subpassNdx + attachmentIndex + compNdx; |
| const BoolOp op = boolOpFromIndex(index); |
| |
| if (compNdx > 0) |
| fragmentShader << ",\n\t\t"; |
| |
| fragmentShader << "((int(gl_FragCoord.x) % 2 == " << (index % 2) |
| << ") " << boolOpToString(op) << " (" |
| << "int(gl_FragCoord.y) % 2 == " << ((index / 2) % 2) |
| << ") ? 1.0 : 0.0)"; |
| } |
| |
| fragmentShader << "));\n"; |
| } |
| |
| if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED |
| && subpass.getDepthStencilAttachment().getImageLayout() != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL |
| && subpass.getDepthStencilAttachment().getImageLayout() != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| const size_t index = subpassNdx + 1; |
| const BoolOp op = boolOpFromIndex(index); |
| |
| fragmentShader << "\tgl_FragDepth = ((int(gl_FragCoord.x) % 2 == " << (index % 2) |
| << ") " << boolOpToString(op) << " (" |
| << "int(gl_FragCoord.y) % 2 == " << ((index / 2) % 2) |
| << ") ? " << deUint32(config.depthValues[1]) << ".0f/255.0f : " << deUint32(config.depthValues[0]) << ".0f/255.0f);\n"; |
| } |
| } |
| else |
| { |
| size_t inputComponentCount = 0; |
| size_t outputComponentCount = 0; |
| |
| for (size_t attachmentNdx = config.drawStartNdx; attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++) |
| { |
| const deUint32 attachmentIndex = subpass.getInputAttachments()[attachmentNdx].getAttachment(); |
| const VkImageLayout layout = subpass.getInputAttachments()[attachmentNdx].getImageLayout(); |
| const Attachment attachment = config.renderPass.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| const size_t componentCount = (size_t)tcu::getNumUsedChannels(format.order); |
| |
| if (layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| inputComponentCount += 1; |
| else if (layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL) |
| inputComponentCount += 1; |
| else |
| inputComponentCount += componentCount; |
| } |
| |
| for (size_t attachmentNdx = config.drawStartNdx; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++) |
| { |
| const deUint32 attachmentIndex = subpass.getColorAttachments()[attachmentNdx].getAttachment(); |
| const Attachment attachment = config.renderPass.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| const size_t componentCount = (size_t)tcu::getNumUsedChannels(format.order); |
| |
| outputComponentCount += componentCount; |
| } |
| |
| if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED |
| && subpass.getDepthStencilAttachment().getImageLayout() != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL |
| && subpass.getDepthStencilAttachment().getImageLayout() != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| outputComponentCount++; |
| } |
| |
| if (outputComponentCount > 0) |
| { |
| const size_t inputsPerOutput = inputComponentCount >= outputComponentCount |
| ? ((inputComponentCount / outputComponentCount) |
| + ((inputComponentCount % outputComponentCount) != 0 ? 1 : 0)) |
| : 1; |
| |
| fragmentShader << "\tbool inputs[" << inputComponentCount << "];\n"; |
| |
| if (outputComponentCount > 0) |
| fragmentShader << "\tbool outputs[" << outputComponentCount << "];\n"; |
| |
| size_t inputValueNdx = 0; |
| |
| for (size_t attachmentNdx = config.drawStartNdx; attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++) |
| { |
| const char* const components[] = |
| { |
| "x", "y", "z", "w" |
| }; |
| const deUint32 attachmentIndex = subpass.getInputAttachments()[attachmentNdx].getAttachment(); |
| const VkImageLayout layout = subpass.getInputAttachments()[attachmentNdx].getImageLayout(); |
| const Attachment attachment = config.renderPass.getAttachments()[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| const size_t componentCount = (size_t)tcu::getNumUsedChannels(format.order); |
| const bool isDepthFormat = tcu::hasDepthComponent(format.order); |
| const bool isStencilFormat = tcu::hasStencilComponent(format.order); |
| |
| if (isDepthFormat || isStencilFormat) |
| { |
| if (isDepthFormat && layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL) |
| { |
| fragmentShader << "\tinputs[" << inputValueNdx << "] = depthsEqual(" << deUint32(config.depthValues[1]) << |
| ".0f/255.0f, float(subpassLoad(i_depth" << attachmentNdx << ").x), " << |
| std::fixed << std::setprecision(12) << requiredDepthEpsilon(attachment.getFormat()) << ");\n"; |
| inputValueNdx++; |
| } |
| |
| if (isStencilFormat && layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| fragmentShader << "\tinputs[" << inputValueNdx << "] = 255u == subpassLoad(i_stencil" << attachmentNdx << ").x;\n"; |
| inputValueNdx++; |
| } |
| } |
| else |
| { |
| for (size_t compNdx = 0; compNdx < componentCount; compNdx++) |
| { |
| fragmentShader << "\tinputs[" << inputValueNdx << "] = 1.0 == float(subpassLoad(i_color" << attachmentNdx << ")." << components[compNdx] << ");\n"; |
| inputValueNdx++; |
| } |
| } |
| } |
| |
| size_t outputValueNdx = 0; |
| |
| for (size_t attachmentNdx = config.drawStartNdx; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++) |
| { |
| const deUint32 attachmentIndex = subpass.getColorAttachments()[attachmentNdx].getAttachment(); |
| const Attachment attachment = config.renderPass.getAttachments()[attachmentIndex]; |
| const std::string attachmentType = getAttachmentType(config.renderPass.getAttachments()[attachmentIndex].getFormat(), config.useFormatCompCount); |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| const size_t componentCount = (size_t)tcu::getNumUsedChannels(format.order); |
| |
| for (size_t compNdx = 0; compNdx < componentCount; compNdx++) |
| { |
| const size_t index = subpassNdx + attachmentIndex + outputValueNdx; |
| const BoolOp op = boolOpFromIndex(index); |
| |
| fragmentShader << "\toutputs[" << outputValueNdx + compNdx << "] = " |
| << "(int(gl_FragCoord.x) % 2 == " << (index % 2) |
| << ") " << boolOpToString(op) << " (" |
| << "int(gl_FragCoord.y) % 2 == " << ((index / 2) % 2) |
| << ");\n"; |
| |
| for (size_t i = 0; i < inputsPerOutput; i++) |
| fragmentShader << "\toutputs[" << outputValueNdx + compNdx << "] = outputs[" << outputValueNdx + compNdx << "] == inputs[" << ((outputValueNdx + compNdx) * inputsPerOutput + i) % inputComponentCount << "];\n"; |
| } |
| |
| fragmentShader << "\to_color" << attachmentNdx << " = " << attachmentType << "("; |
| |
| for (size_t compNdx = 0; compNdx < (config.useFormatCompCount ? componentCount : 4); compNdx++) |
| { |
| if (compNdx > 0) |
| fragmentShader << ", "; |
| |
| if (compNdx < componentCount) |
| fragmentShader << "outputs[" << outputValueNdx + compNdx << "]"; |
| else |
| fragmentShader << "0"; |
| } |
| |
| outputValueNdx += componentCount; |
| |
| fragmentShader << ");\n"; |
| } |
| |
| if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED |
| && subpass.getDepthStencilAttachment().getImageLayout() != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL |
| && subpass.getDepthStencilAttachment().getImageLayout() != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| const deUint32 attachmentIndex = subpass.getDepthStencilAttachment().getAttachment(); |
| const size_t index = subpassNdx + attachmentIndex; |
| const BoolOp op = boolOpFromIndex(index); |
| |
| fragmentShader << "\toutputs[" << outputValueNdx << "] = " |
| << "(int(gl_FragCoord.x) % 2 == " << (index % 2) |
| << ") " << boolOpToString(op) << " (" |
| << "int(gl_FragCoord.y) % 2 == " << ((index / 2) % 2) |
| << ");\n"; |
| |
| for (size_t i = 0; i < inputsPerOutput; i++) |
| fragmentShader << "\toutputs[" << outputValueNdx << "] = outputs[" << outputValueNdx << "] == inputs[" << (outputValueNdx * inputsPerOutput + i) % inputComponentCount << "];\n"; |
| |
| fragmentShader << "\tgl_FragDepth = outputs[" << outputValueNdx << "] ? " << deUint32(config.depthValues[1]) << ".0f/255.0f : " << deUint32(config.depthValues[0]) << ".0f/255.0f;\n"; |
| } |
| } |
| } |
| |
| fragmentShader << "}\n"; |
| |
| dst.glslSources.add(de::toString(subpassNdx) + "-vert") << glu::VertexSource(vertexShader.str()); |
| dst.glslSources.add(de::toString(subpassNdx) + "-frag") << glu::FragmentSource(fragmentShader.str()); |
| } |
| } |
| } |
| |
| void initializeAttachmentIsLazy (vector<bool>& attachmentIsLazy, const vector<Attachment>& attachments, TestConfig::ImageMemory imageMemory) |
| { |
| bool lastAttachmentWasLazy = false; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++) |
| { |
| if (attachments[attachmentNdx].getLoadOp() != VK_ATTACHMENT_LOAD_OP_LOAD |
| && attachments[attachmentNdx].getStoreOp() != VK_ATTACHMENT_STORE_OP_STORE |
| && attachments[attachmentNdx].getStencilLoadOp() != VK_ATTACHMENT_LOAD_OP_LOAD |
| && attachments[attachmentNdx].getStencilStoreOp() != VK_ATTACHMENT_STORE_OP_STORE) |
| { |
| if (imageMemory == TestConfig::IMAGEMEMORY_LAZY || (imageMemory & TestConfig::IMAGEMEMORY_LAZY && !lastAttachmentWasLazy)) |
| { |
| attachmentIsLazy.push_back(true); |
| |
| lastAttachmentWasLazy = true; |
| } |
| else if (imageMemory & TestConfig::IMAGEMEMORY_STRICT) |
| { |
| attachmentIsLazy.push_back(false); |
| lastAttachmentWasLazy = false; |
| } |
| else |
| DE_FATAL("Unknown imageMemory"); |
| } |
| else |
| attachmentIsLazy.push_back(false); |
| } |
| } |
| |
| enum AttachmentRefType |
| { |
| ATTACHMENTREFTYPE_COLOR, |
| ATTACHMENTREFTYPE_DEPTH_STENCIL, |
| ATTACHMENTREFTYPE_INPUT, |
| ATTACHMENTREFTYPE_RESOLVE, |
| }; |
| |
| VkImageUsageFlags getImageUsageFromLayout (VkImageLayout layout) |
| { |
| switch (layout) |
| { |
| case VK_IMAGE_LAYOUT_GENERAL: |
| case VK_IMAGE_LAYOUT_PREINITIALIZED: |
| return 0; |
| |
| case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: |
| return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| |
| case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: |
| case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: |
| return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; |
| |
| case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: |
| return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; |
| |
| case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: |
| return VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| |
| case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: |
| return VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| |
| default: |
| DE_FATAL("Unexpected image layout"); |
| return 0; |
| } |
| } |
| |
| void getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags>& attachmentImageUsage, AttachmentRefType refType, size_t count, const AttachmentReference* references) |
| { |
| for (size_t referenceNdx = 0; referenceNdx < count; ++referenceNdx) |
| { |
| const deUint32 attachment = references[referenceNdx].getAttachment(); |
| |
| if (attachment != VK_ATTACHMENT_UNUSED) |
| { |
| VkImageUsageFlags usage; |
| |
| switch (refType) |
| { |
| case ATTACHMENTREFTYPE_COLOR: |
| case ATTACHMENTREFTYPE_RESOLVE: |
| usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| break; |
| |
| case ATTACHMENTREFTYPE_DEPTH_STENCIL: |
| usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; |
| break; |
| |
| case ATTACHMENTREFTYPE_INPUT: |
| usage = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; |
| break; |
| |
| default: |
| DE_FATAL("Unexpected attachment reference type"); |
| usage = 0; |
| break; |
| } |
| |
| attachmentImageUsage[attachment] |= usage; |
| } |
| } |
| } |
| |
| void getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags>& attachmentImageUsage, AttachmentRefType refType, const vector<AttachmentReference>& references) |
| { |
| if (!references.empty()) |
| { |
| getImageUsageFromAttachmentReferences(attachmentImageUsage, refType, references.size(), &references[0]); |
| } |
| } |
| |
| void initializeAttachmentImageUsage (Context &context, vector<VkImageUsageFlags>& attachmentImageUsage, const RenderPass& renderPassInfo, const vector<bool>& attachmentIsLazy, const vector<Maybe<VkClearValue> >& clearValues) |
| { |
| attachmentImageUsage.resize(renderPassInfo.getAttachments().size(), VkImageUsageFlags(0)); |
| |
| for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); ++subpassNdx) |
| { |
| const Subpass& subpass = renderPassInfo.getSubpasses()[subpassNdx]; |
| |
| getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_COLOR, subpass.getColorAttachments()); |
| getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_DEPTH_STENCIL, 1, &subpass.getDepthStencilAttachment()); |
| getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_INPUT, subpass.getInputAttachments()); |
| getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_RESOLVE, subpass.getResolveAttachments()); |
| } |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++) |
| { |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentNdx]; |
| const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), attachment.getFormat()); |
| const VkFormatFeatureFlags supportedFeatures = formatProperties.optimalTilingFeatures; |
| |
| if ((supportedFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0) |
| attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_SAMPLED_BIT; |
| |
| if ((supportedFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) != 0) |
| attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_STORAGE_BIT; |
| |
| attachmentImageUsage[attachmentNdx] |= getImageUsageFromLayout(attachment.getInitialLayout()); |
| attachmentImageUsage[attachmentNdx] |= getImageUsageFromLayout(attachment.getFinalLayout()); |
| |
| if (!attachmentIsLazy[attachmentNdx]) |
| { |
| if (clearValues[attachmentNdx]) |
| attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| |
| attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| } |
| else |
| { |
| const VkImageUsageFlags allowedTransientBits = static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT); |
| |
| attachmentImageUsage[attachmentNdx] &= allowedTransientBits; |
| attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; |
| } |
| } |
| } |
| |
| void initializeSubpassIsSecondary (vector<bool>& subpassIsSecondary, const vector<Subpass>& subpasses, TestConfig::CommandBufferTypes commandBuffer) |
| { |
| bool lastSubpassWasSecondary = false; |
| |
| for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++) |
| { |
| if (commandBuffer == TestConfig::COMMANDBUFFERTYPES_SECONDARY || (commandBuffer & TestConfig::COMMANDBUFFERTYPES_SECONDARY && !lastSubpassWasSecondary)) |
| { |
| subpassIsSecondary.push_back(true); |
| lastSubpassWasSecondary = true; |
| } |
| else if (commandBuffer & TestConfig::COMMANDBUFFERTYPES_INLINE) |
| { |
| subpassIsSecondary.push_back(false); |
| lastSubpassWasSecondary = false; |
| } |
| else |
| DE_FATAL("Unknown commandBuffer"); |
| } |
| } |
| |
| void initializeImageClearValues (de::Random& rng, vector<Maybe<VkClearValue> >& clearValues, const vector<Attachment>& attachments, const vector<bool>& isLazy, deBool useFormatCompCount, const DepthValuesArray& depthValues) |
| { |
| for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++) |
| { |
| if (!isLazy[attachmentNdx]) |
| clearValues.push_back(just(randomClearValue(attachments[attachmentNdx], rng, useFormatCompCount, depthValues))); |
| else |
| clearValues.push_back(nothing<VkClearValue>()); |
| } |
| } |
| |
| void initializeRenderPassClearValues (de::Random& rng, vector<Maybe<VkClearValue> >& clearValues, const vector<Attachment>& attachments, deBool useFormatCompCount, const DepthValuesArray& depthValues) |
| { |
| for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++) |
| { |
| if (attachments[attachmentNdx].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR |
| || attachments[attachmentNdx].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR) |
| { |
| clearValues.push_back(just(randomClearValue(attachments[attachmentNdx], rng, useFormatCompCount, depthValues))); |
| } |
| else |
| clearValues.push_back(nothing<VkClearValue>()); |
| } |
| } |
| |
| void logSubpassRenderInfo (TestLog& log, const SubpassRenderInfo& info, TestConfig config) |
| { |
| log << TestLog::Message << "Viewport, offset: " << info.getViewportOffset() << ", size: " << info.getViewportSize() << TestLog::EndMessage; |
| |
| if (info.isSecondary()) |
| log << TestLog::Message << "Subpass uses secondary command buffers" << TestLog::EndMessage; |
| else |
| log << TestLog::Message << "Subpass uses inlined commands" << TestLog::EndMessage; |
| |
| for (deUint32 attachmentNdx = 0; attachmentNdx < info.getColorClears().size(); attachmentNdx++) |
| { |
| const ColorClear& colorClear = info.getColorClears()[attachmentNdx]; |
| |
| log << TestLog::Message << "Clearing color attachment " << attachmentNdx |
| << ". Offset: " << colorClear.getOffset() |
| << ", Size: " << colorClear.getSize() |
| << ", Color: " << clearColorToString(info.getColorAttachment(attachmentNdx).getFormat(), colorClear.getColor(), config.useFormatCompCount) << TestLog::EndMessage; |
| } |
| |
| if (info.getDepthStencilClear()) |
| { |
| const DepthStencilClear& depthStencilClear = *info.getDepthStencilClear(); |
| |
| log << TestLog::Message << "Clearing depth stencil attachment" |
| << ". Offset: " << depthStencilClear.getOffset() |
| << ", Size: " << depthStencilClear.getSize() |
| << ", Depth: " << depthStencilClear.getDepth() |
| << ", Stencil: " << depthStencilClear.getStencil() << TestLog::EndMessage; |
| } |
| |
| if (info.getRenderQuad()) |
| { |
| const RenderQuad& renderQuad = *info.getRenderQuad(); |
| |
| log << TestLog::Message << "Rendering grid quad to " << renderQuad.getCornerA() << " -> " << renderQuad.getCornerB() << TestLog::EndMessage; |
| } |
| } |
| |
| void logTestCaseInfo (TestLog& log, |
| const TestConfig& config, |
| const vector<bool>& attachmentIsLazy, |
| const vector<Maybe<VkClearValue> >& imageClearValues, |
| const vector<Maybe<VkClearValue> >& renderPassClearValues, |
| const vector<SubpassRenderInfo>& subpassRenderInfo) |
| { |
| const RenderPass& renderPass = config.renderPass; |
| |
| logRenderPassInfo(log, renderPass); |
| |
| DE_ASSERT(attachmentIsLazy.size() == renderPass.getAttachments().size()); |
| DE_ASSERT(imageClearValues.size() == renderPass.getAttachments().size()); |
| DE_ASSERT(renderPassClearValues.size() == renderPass.getAttachments().size()); |
| |
| log << TestLog::Message << "TargetSize: " << config.targetSize << TestLog::EndMessage; |
| log << TestLog::Message << "Render area, Offset: " << config.renderPos << ", Size: " << config.renderSize << TestLog::EndMessage; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < attachmentIsLazy.size(); attachmentNdx++) |
| { |
| const tcu::ScopedLogSection section (log, "Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx)); |
| |
| if (attachmentIsLazy[attachmentNdx]) |
| log << TestLog::Message << "Is lazy." << TestLog::EndMessage; |
| |
| if (imageClearValues[attachmentNdx]) |
| log << TestLog::Message << "Image is cleared to " << clearValueToString(renderPass.getAttachments()[attachmentNdx].getFormat(), |
| *imageClearValues[attachmentNdx], config.useFormatCompCount) << " before rendering." << TestLog::EndMessage; |
| |
| if (renderPass.getAttachments()[attachmentNdx].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR && renderPassClearValues[attachmentNdx]) |
| log << TestLog::Message << "Attachment is cleared to " << clearValueToString(renderPass.getAttachments()[attachmentNdx].getFormat(), |
| *renderPassClearValues[attachmentNdx], config.useFormatCompCount) << " in the beginning of the render pass." << TestLog::EndMessage; |
| } |
| |
| for (size_t subpassNdx = 0; subpassNdx < renderPass.getSubpasses().size(); subpassNdx++) |
| { |
| const tcu::ScopedLogSection section (log, "Subpass" + de::toString(subpassNdx), "Subpass " + de::toString(subpassNdx)); |
| |
| logSubpassRenderInfo(log, subpassRenderInfo[subpassNdx], config); |
| } |
| } |
| |
| float roundToViewport (float x, deUint32 offset, deUint32 size) |
| { |
| const float origin = (float)(offset) + ((float(size) / 2.0f)); |
| const float p = (float)(size) / 2.0f; |
| const deInt32 xi = deRoundFloatToInt32(origin + (p * x)); |
| |
| return (((float)xi) - origin) / p; |
| } |
| |
| void initializeSubpassRenderInfo (vector<SubpassRenderInfo>& renderInfos, de::Random& rng, const RenderPass& renderPass, const TestConfig& config) |
| { |
| const TestConfig::CommandBufferTypes commandBuffer = config.commandBufferTypes; |
| const vector<Subpass>& subpasses = renderPass.getSubpasses(); |
| bool lastSubpassWasSecondary = false; |
| |
| for (deUint32 subpassNdx = 0; subpassNdx < (deUint32)subpasses.size(); subpassNdx++) |
| { |
| const Subpass& subpass = subpasses[subpassNdx]; |
| const bool subpassIsSecondary = commandBuffer == TestConfig::COMMANDBUFFERTYPES_SECONDARY |
| || (commandBuffer & TestConfig::COMMANDBUFFERTYPES_SECONDARY && !lastSubpassWasSecondary) ? true : false; |
| const bool omitBlendState = subpass.getOmitBlendState(); |
| const UVec2 viewportSize ((config.renderSize * UVec2(2)) / UVec2(3)); |
| const UVec2 viewportOffset (config.renderPos.x() + (subpassNdx % 2) * (config.renderSize.x() / 3), |
| config.renderPos.y() + ((subpassNdx / 2) % 2) * (config.renderSize.y() / 3)); |
| |
| vector<ColorClear> colorClears; |
| Maybe<DepthStencilClear> depthStencilClear; |
| Maybe<RenderQuad> renderQuad; |
| |
| lastSubpassWasSecondary = subpassIsSecondary; |
| |
| if (config.renderTypes & TestConfig::RENDERTYPES_CLEAR) |
| { |
| const vector<AttachmentReference>& colorAttachments = subpass.getColorAttachments(); |
| |
| for (size_t attachmentRefNdx = 0; attachmentRefNdx < colorAttachments.size(); attachmentRefNdx++) |
| { |
| const AttachmentReference& attachmentRef = colorAttachments[attachmentRefNdx]; |
| const Attachment& attachment = renderPass.getAttachments()[attachmentRef.getAttachment()]; |
| const UVec2 size ((viewportSize * UVec2(2)) / UVec2(3)); |
| const UVec2 offset (viewportOffset.x() + ((deUint32)attachmentRefNdx % 2u) * (viewportSize.x() / 3u), |
| viewportOffset.y() + (((deUint32)attachmentRefNdx / 2u) % 2u) * (viewportSize.y() / 3u)); |
| const VkClearColorValue color = randomColorClearValue(attachment, rng, config.useFormatCompCount); |
| |
| colorClears.push_back(ColorClear(offset, size, color)); |
| } |
| |
| if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED) |
| { |
| const Attachment& attachment = renderPass.getAttachments()[subpass.getDepthStencilAttachment().getAttachment()]; |
| const UVec2 size ((viewportSize * UVec2(2)) / UVec2(3)); |
| const UVec2 offset (viewportOffset.x() + ((deUint32)colorAttachments.size() % 2u) * (viewportSize.x() / 3u), |
| viewportOffset.y() + (((deUint32)colorAttachments.size() / 2u) % 2u) * (viewportSize.y() / 3u)); |
| const VkClearValue value = randomClearValue(attachment, rng, config.useFormatCompCount, config.depthValues); |
| |
| depthStencilClear = tcu::just(DepthStencilClear(offset, size, value.depthStencil.depth, value.depthStencil.stencil)); |
| } |
| } |
| |
| if (config.renderTypes & TestConfig::RENDERTYPES_DRAW) |
| { |
| const float w = (subpassNdx % 2) == 0 ? 1.0f : 1.25f; |
| const float h = (subpassNdx % 2) == 0 ? 1.25f : 1.0f; |
| |
| const float x0 = roundToViewport((subpassNdx % 2) == 0 ? 1.0f - w : -1.0f, viewportOffset.x(), viewportSize.x()); |
| const float x1 = roundToViewport((subpassNdx % 2) == 0 ? 1.0f : -1.0f + w, viewportOffset.x(), viewportSize.x()); |
| |
| const float y0 = roundToViewport(((subpassNdx / 2) % 2) == 0 ? 1.0f - h : -1.0f, viewportOffset.y(), viewportSize.y()); |
| const float y1 = roundToViewport(((subpassNdx / 2) % 2) == 0 ? 1.0f : -1.0f + h, viewportOffset.y(), viewportSize.y()); |
| |
| renderQuad = tcu::just(RenderQuad(tcu::Vec2(x0, y0), tcu::Vec2(x1, y1))); |
| } |
| |
| renderInfos.push_back(SubpassRenderInfo(renderPass, subpassNdx, config.drawStartNdx, subpassIsSecondary, omitBlendState, viewportOffset, viewportSize, renderQuad, colorClears, depthStencilClear)); |
| } |
| } |
| |
| void checkTextureFormatSupport (TestLog& log, |
| const InstanceInterface& vk, |
| VkPhysicalDevice device, |
| const vector<Attachment>& attachments) |
| { |
| bool supported = true; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++) |
| { |
| const Attachment& attachment = attachments[attachmentNdx]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| const bool isDepthOrStencilAttachment = hasDepthComponent(format.order) || hasStencilComponent(format.order); |
| const VkFormatFeatureFlags flags = isDepthOrStencilAttachment? VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; |
| VkFormatProperties properties; |
| |
| vk.getPhysicalDeviceFormatProperties(device, attachment.getFormat(), &properties); |
| |
| if ((properties.optimalTilingFeatures & flags) != flags) |
| { |
| supported = false; |
| log << TestLog::Message << "Format: " << attachment.getFormat() << " not supported as " << (isDepthOrStencilAttachment ? "depth stencil attachment" : "color attachment") << TestLog::EndMessage; |
| } |
| } |
| |
| if (!supported) |
| TCU_THROW(NotSupportedError, "Format not supported"); |
| } |
| |
| tcu::TestStatus renderPassTest (Context& context, TestConfig config) |
| { |
| const UVec2 targetSize = config.targetSize; |
| const UVec2 renderPos = config.renderPos; |
| const UVec2 renderSize = config.renderSize; |
| const RenderPass& renderPassInfo = config.renderPass; |
| |
| TestLog& log = context.getTestContext().getLog(); |
| de::Random rng (config.seed); |
| |
| vector<bool> attachmentIsLazy; |
| vector<VkImageUsageFlags> attachmentImageUsage; |
| vector<Maybe<VkClearValue> > imageClearValues; |
| vector<Maybe<VkClearValue> > renderPassClearValues; |
| |
| vector<bool> subpassIsSecondary; |
| vector<SubpassRenderInfo> subpassRenderInfo; |
| |
| if (config.renderPassType == RENDERPASS_TYPE_RENDERPASS2) |
| context.requireDeviceFunctionality("VK_KHR_create_renderpass2"); |
| |
| if (config.allocationKind == ALLOCATION_KIND_DEDICATED) |
| { |
| if (!context.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation")) |
| TCU_THROW(NotSupportedError, "VK_KHR_dedicated_allocation is not supported"); |
| } |
| |
| if (!renderPassInfo.getInputAspects().empty()) |
| { |
| if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance2")) |
| TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance2 not supported."); |
| } |
| |
| { |
| bool requireDepthStencilLayout = false; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++) |
| { |
| if (renderPassInfo.getAttachments()[attachmentNdx].getInitialLayout() == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL |
| || renderPassInfo.getAttachments()[attachmentNdx].getInitialLayout() == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL |
| || renderPassInfo.getAttachments()[attachmentNdx].getFinalLayout() == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL |
| || renderPassInfo.getAttachments()[attachmentNdx].getFinalLayout() == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| requireDepthStencilLayout = true; |
| break; |
| } |
| } |
| |
| for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size() && !requireDepthStencilLayout; subpassNdx++) |
| { |
| const Subpass& subpass (renderPassInfo.getSubpasses()[subpassNdx]); |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++) |
| { |
| if (subpass.getColorAttachments()[attachmentNdx].getImageLayout() == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL |
| || subpass.getColorAttachments()[attachmentNdx].getImageLayout() == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| requireDepthStencilLayout = true; |
| break; |
| } |
| } |
| |
| for (size_t attachmentNdx = 0; !requireDepthStencilLayout && attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++) |
| { |
| if (subpass.getInputAttachments()[attachmentNdx].getImageLayout() == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL |
| || subpass.getInputAttachments()[attachmentNdx].getImageLayout() == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| requireDepthStencilLayout = true; |
| break; |
| } |
| } |
| |
| for (size_t attachmentNdx = 0; !requireDepthStencilLayout && attachmentNdx < subpass.getResolveAttachments().size(); attachmentNdx++) |
| { |
| if (subpass.getResolveAttachments()[attachmentNdx].getImageLayout() == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL |
| || subpass.getResolveAttachments()[attachmentNdx].getImageLayout() == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| requireDepthStencilLayout = true; |
| break; |
| } |
| } |
| |
| if (subpass.getDepthStencilAttachment().getImageLayout() == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL |
| || subpass.getDepthStencilAttachment().getImageLayout() == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) |
| { |
| requireDepthStencilLayout = true; |
| break; |
| } |
| } |
| |
| if (requireDepthStencilLayout && !context.isDeviceFunctionalitySupported("VK_KHR_maintenance2")) |
| TCU_THROW(NotSupportedError, "VK_KHR_maintenance2 is not supported"); |
| } |
| |
| initializeAttachmentIsLazy(attachmentIsLazy, renderPassInfo.getAttachments(), config.imageMemory); |
| initializeImageClearValues(rng, imageClearValues, renderPassInfo.getAttachments(), attachmentIsLazy, config.useFormatCompCount, config.depthValues); |
| initializeAttachmentImageUsage(context, attachmentImageUsage, renderPassInfo, attachmentIsLazy, imageClearValues); |
| initializeRenderPassClearValues(rng, renderPassClearValues, renderPassInfo.getAttachments(), config.useFormatCompCount, config.depthValues); |
| |
| initializeSubpassIsSecondary(subpassIsSecondary, renderPassInfo.getSubpasses(), config.commandBufferTypes); |
| initializeSubpassRenderInfo(subpassRenderInfo, rng, renderPassInfo, config); |
| |
| logTestCaseInfo(log, config, attachmentIsLazy, imageClearValues, renderPassClearValues, subpassRenderInfo); |
| |
| checkTextureFormatSupport(log, context.getInstanceInterface(), context.getPhysicalDevice(), config.renderPass.getAttachments()); |
| |
| { |
| const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()); |
| |
| log << TestLog::Message << "Max color attachments: " << properties.limits.maxColorAttachments << TestLog::EndMessage; |
| |
| for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++) |
| { |
| if (renderPassInfo.getSubpasses()[subpassNdx].getColorAttachments().size() > (size_t)properties.limits.maxColorAttachments) |
| TCU_THROW(NotSupportedError, "Subpass uses more than maxColorAttachments."); |
| } |
| } |
| |
| { |
| const InstanceInterface& vki = context.getInstanceInterface(); |
| const VkPhysicalDevice& physDevice = context.getPhysicalDevice(); |
| const VkDevice device = context.getDevice(); |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkQueue queue = context.getUniversalQueue(); |
| const deUint32 queueIndex = context.getUniversalQueueFamilyIndex(); |
| Allocator& allocator = context.getDefaultAllocator(); |
| |
| const Unique<VkRenderPass> renderPass (createRenderPass(vk, device, renderPassInfo, config.renderPassType)); |
| const Unique<VkCommandPool> commandBufferPool (createCommandPool(vk, device, 0, queueIndex)); |
| const Unique<VkCommandBuffer> initializeImagesCommandBuffer (allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); |
| const Unique<VkCommandBuffer> renderCommandBuffer (allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); |
| const Unique<VkCommandBuffer> readImagesToBuffersCommandBuffer (allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); |
| |
| vector<de::SharedPtr<AttachmentResources> > attachmentResources; |
| vector<de::SharedPtr<SubpassRenderer> > subpassRenderers; |
| vector<VkImage> attachmentImages; |
| vector<VkImageView> attachmentViews; |
| vector<pair<VkImageView, VkImageView> > inputAttachmentViews; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++) |
| { |
| const Attachment& attachmentInfo = renderPassInfo.getAttachments()[attachmentNdx]; |
| |
| attachmentResources.push_back(de::SharedPtr<AttachmentResources>(new AttachmentResources(vki, physDevice, vk, device, allocator, queueIndex, targetSize, attachmentInfo, attachmentImageUsage[attachmentNdx], config.allocationKind))); |
| attachmentViews.push_back(attachmentResources[attachmentNdx]->getAttachmentView()); |
| attachmentImages.push_back(attachmentResources[attachmentNdx]->getImage()); |
| |
| inputAttachmentViews.push_back(attachmentResources[attachmentNdx]->getInputAttachmentViews()); |
| } |
| |
| beginCommandBuffer(vk, *initializeImagesCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0); |
| pushImageInitializationCommands(vk, *initializeImagesCommandBuffer, renderPassInfo.getAttachments(), attachmentResources, queueIndex, imageClearValues); |
| endCommandBuffer(vk, *initializeImagesCommandBuffer); |
| |
| { |
| const Unique<VkFramebuffer> framebuffer (createFramebuffer(vk, device, *renderPass, targetSize, attachmentViews)); |
| |
| for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++) |
| subpassRenderers.push_back(de::SharedPtr<SubpassRenderer>(new SubpassRenderer(context, vk, device, allocator, *renderPass, *framebuffer, *commandBufferPool, queueIndex, attachmentImages, inputAttachmentViews, subpassRenderInfo[subpassNdx], config.renderPass.getAttachments(), config.allocationKind))); |
| |
| beginCommandBuffer(vk, *renderCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0); |
| pushRenderPassCommands(vk, *renderCommandBuffer, *renderPass, *framebuffer, subpassRenderers, renderPos, renderSize, renderPassClearValues, config.renderTypes, config.renderPassType); |
| endCommandBuffer(vk, *renderCommandBuffer); |
| |
| beginCommandBuffer(vk, *readImagesToBuffersCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0); |
| pushReadImagesToBuffers(vk, *readImagesToBuffersCommandBuffer, queueIndex, attachmentResources, renderPassInfo.getAttachments(), attachmentIsLazy, targetSize); |
| endCommandBuffer(vk, *readImagesToBuffersCommandBuffer); |
| { |
| const VkCommandBuffer commandBuffers[] = |
| { |
| *initializeImagesCommandBuffer, |
| *renderCommandBuffer, |
| *readImagesToBuffersCommandBuffer |
| }; |
| const Unique<VkFence> fence (createFence(vk, device, 0u)); |
| |
| queueSubmit(vk, queue, DE_LENGTH_OF_ARRAY(commandBuffers), commandBuffers, *fence); |
| waitForFences(vk, device, 1, &fence.get(), VK_TRUE, ~0ull); |
| } |
| } |
| |
| if (logAndVerifyImages(log, vk, device, attachmentResources, attachmentIsLazy, renderPassInfo, renderPassClearValues, imageClearValues, subpassRenderInfo, targetSize, config)) |
| return tcu::TestStatus::pass("Pass"); |
| else |
| return tcu::TestStatus::fail("Result verification failed"); |
| } |
| } |
| |
| static const VkFormat s_coreColorFormats[] = |
| { |
| VK_FORMAT_R5G6B5_UNORM_PACK16, |
| VK_FORMAT_R8_UNORM, |
| VK_FORMAT_R8_SNORM, |
| VK_FORMAT_R8_UINT, |
| VK_FORMAT_R8_SINT, |
| VK_FORMAT_R8G8_UNORM, |
| VK_FORMAT_R8G8_SNORM, |
| VK_FORMAT_R8G8_UINT, |
| VK_FORMAT_R8G8_SINT, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| VK_FORMAT_R8G8B8A8_SNORM, |
| VK_FORMAT_R8G8B8A8_UINT, |
| VK_FORMAT_R8G8B8A8_SINT, |
| VK_FORMAT_R8G8B8A8_SRGB, |
| VK_FORMAT_A8B8G8R8_UNORM_PACK32, |
| VK_FORMAT_A8B8G8R8_SNORM_PACK32, |
| VK_FORMAT_A8B8G8R8_UINT_PACK32, |
| VK_FORMAT_A8B8G8R8_SINT_PACK32, |
| VK_FORMAT_A8B8G8R8_SRGB_PACK32, |
| VK_FORMAT_B8G8R8A8_UNORM, |
| VK_FORMAT_B8G8R8A8_SRGB, |
| VK_FORMAT_A2R10G10B10_UNORM_PACK32, |
| VK_FORMAT_A2B10G10R10_UNORM_PACK32, |
| VK_FORMAT_A2B10G10R10_UINT_PACK32, |
| VK_FORMAT_R16_UNORM, |
| VK_FORMAT_R16_SNORM, |
| VK_FORMAT_R16_UINT, |
| VK_FORMAT_R16_SINT, |
| VK_FORMAT_R16_SFLOAT, |
| VK_FORMAT_R16G16_UNORM, |
| VK_FORMAT_R16G16_SNORM, |
| VK_FORMAT_R16G16_UINT, |
| VK_FORMAT_R16G16_SINT, |
| VK_FORMAT_R16G16_SFLOAT, |
| VK_FORMAT_R16G16B16A16_UNORM, |
| VK_FORMAT_R16G16B16A16_SNORM, |
| VK_FORMAT_R16G16B16A16_UINT, |
| VK_FORMAT_R16G16B16A16_SINT, |
| VK_FORMAT_R16G16B16A16_SFLOAT, |
| VK_FORMAT_R32_UINT, |
| VK_FORMAT_R32_SINT, |
| VK_FORMAT_R32_SFLOAT, |
| VK_FORMAT_R32G32_UINT, |
| VK_FORMAT_R32G32_SINT, |
| VK_FORMAT_R32G32_SFLOAT, |
| VK_FORMAT_R32G32B32A32_UINT, |
| VK_FORMAT_R32G32B32A32_SINT, |
| VK_FORMAT_R32G32B32A32_SFLOAT |
| }; |
| |
| static const VkFormat s_coreDepthStencilFormats[] = |
| { |
| VK_FORMAT_D16_UNORM, |
| |
| VK_FORMAT_X8_D24_UNORM_PACK32, |
| VK_FORMAT_D32_SFLOAT, |
| |
| VK_FORMAT_D24_UNORM_S8_UINT, |
| VK_FORMAT_D32_SFLOAT_S8_UINT |
| }; |
| |
| void addAttachmentTests (tcu::TestCaseGroup* group, const TestConfigExternal testConfigExternal) |
| { |
| const deUint32 attachmentCounts[] = { 1, 3, 4, 8 }; |
| const VkAttachmentLoadOp loadOps[] = |
| { |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE |
| }; |
| |
| const VkAttachmentStoreOp storeOps[] = |
| { |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE |
| }; |
| |
| const VkImageLayout initialAndFinalColorLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_GENERAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL |
| }; |
| |
| const VkImageLayout initialAndFinalColorLayoutsLazy[] = |
| { |
| VK_IMAGE_LAYOUT_GENERAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
| }; |
| |
| const VkImageLayout initialAndFinalDepthStencilLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_GENERAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL |
| }; |
| |
| const VkImageLayout initialAndFinalDepthStencilLayoutsLazy[] = |
| { |
| VK_IMAGE_LAYOUT_GENERAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
| }; |
| |
| const VkImageLayout subpassLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_GENERAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL |
| }; |
| |
| const VkImageLayout depthStencilLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_GENERAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL |
| }; |
| |
| const TestConfig::RenderTypes renderCommands[] = |
| { |
| TestConfig::RENDERTYPES_NONE, |
| TestConfig::RENDERTYPES_CLEAR, |
| TestConfig::RENDERTYPES_DRAW, |
| TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW, |
| }; |
| |
| const TestConfig::CommandBufferTypes commandBuffers[] = |
| { |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::COMMANDBUFFERTYPES_SECONDARY, |
| TestConfig::COMMANDBUFFERTYPES_INLINE|TestConfig::COMMANDBUFFERTYPES_SECONDARY |
| }; |
| |
| const TestConfig::ImageMemory imageMemories[] = |
| { |
| TestConfig::IMAGEMEMORY_STRICT, |
| TestConfig::IMAGEMEMORY_LAZY, |
| TestConfig::IMAGEMEMORY_STRICT|TestConfig::IMAGEMEMORY_LAZY |
| }; |
| |
| const UVec2 targetSizes[] = |
| { |
| UVec2(64, 64), |
| UVec2(63, 65) |
| }; |
| |
| const UVec2 renderPositions[] = |
| { |
| UVec2(0, 0), |
| UVec2(3, 17) |
| }; |
| |
| const UVec2 renderSizes[] = |
| { |
| UVec2(32, 32), |
| UVec2(60, 47) |
| }; |
| |
| tcu::TestContext& testCtx = group->getTestContext(); |
| de::Random rng (1433774382u); |
| |
| for (size_t attachmentCountNdx = 0; attachmentCountNdx < DE_LENGTH_OF_ARRAY(attachmentCounts); attachmentCountNdx++) |
| { |
| const deUint32 attachmentCount = attachmentCounts[attachmentCountNdx]; |
| const deUint32 testCaseCount = (attachmentCount == 1 ? 100 : 200); |
| de::MovePtr<tcu::TestCaseGroup> attachmentCountGroup (new tcu::TestCaseGroup(testCtx, de::toString(attachmentCount).c_str(), de::toString(attachmentCount).c_str())); |
| |
| for (size_t testCaseNdx = 0; testCaseNdx < testCaseCount; testCaseNdx++) |
| { |
| const bool useDepthStencil = rng.getBool(); |
| const TestConfig::ImageMemory imageMemory = rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories)); |
| VkImageLayout depthStencilLayout = VK_IMAGE_LAYOUT_GENERAL; |
| vector<Attachment> attachments; |
| vector<AttachmentReference> colorAttachmentReferences; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++) |
| { |
| const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; |
| const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreColorFormats), DE_ARRAY_END(s_coreColorFormats)); |
| const VkAttachmentLoadOp loadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps)); |
| const VkAttachmentStoreOp storeOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps)); |
| |
| const VkImageLayout initialLayout = (imageMemory == TestConfig::IMAGEMEMORY_STRICT) |
| ? rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts)) |
| : rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayoutsLazy), DE_ARRAY_END(initialAndFinalColorLayoutsLazy)); |
| const VkImageLayout finalizeLayout = (imageMemory == TestConfig::IMAGEMEMORY_STRICT) |
| ? rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts)) |
| : rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayoutsLazy), DE_ARRAY_END(initialAndFinalColorLayoutsLazy)); |
| const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts)); |
| |
| const VkAttachmentLoadOp stencilLoadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps)); |
| const VkAttachmentStoreOp stencilStoreOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps)); |
| |
| attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout)); |
| colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout)); |
| } |
| |
| if (useDepthStencil) |
| { |
| const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; |
| const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreDepthStencilFormats), DE_ARRAY_END(s_coreDepthStencilFormats)); |
| const VkAttachmentLoadOp loadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps)); |
| const VkAttachmentStoreOp storeOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps)); |
| |
| const VkImageLayout initialLayout = (imageMemory == TestConfig::IMAGEMEMORY_STRICT) |
| ? rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts), DE_ARRAY_END(initialAndFinalDepthStencilLayouts)) |
| : rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayoutsLazy), DE_ARRAY_END(initialAndFinalDepthStencilLayoutsLazy)); |
| const VkImageLayout finalizeLayout = (imageMemory == TestConfig::IMAGEMEMORY_STRICT) |
| ? rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts), DE_ARRAY_END(initialAndFinalDepthStencilLayouts)) |
| : rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayoutsLazy), DE_ARRAY_END(initialAndFinalDepthStencilLayoutsLazy)); |
| |
| const VkAttachmentLoadOp stencilLoadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps)); |
| const VkAttachmentStoreOp stencilStoreOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps)); |
| |
| depthStencilLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(depthStencilLayouts), DE_ARRAY_END(depthStencilLayouts)); |
| attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout)); |
| } |
| |
| { |
| const TestConfig::RenderTypes render = rng.choose<TestConfig::RenderTypes>(DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands)); |
| const TestConfig::CommandBufferTypes commandBuffer = rng.choose<TestConfig::CommandBufferTypes>(DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers)); |
| const vector<Subpass> subpasses (1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference((useDepthStencil ? (deUint32)(attachments.size() - 1) : VK_ATTACHMENT_UNUSED), depthStencilLayout), vector<deUint32>())); |
| const vector<SubpassDependency> deps; |
| |
| const string testCaseName = de::toString(attachmentCountNdx * testCaseCount + testCaseNdx); |
| const RenderPass renderPass (attachments, subpasses, deps); |
| const UVec2 targetSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes)); |
| const UVec2 renderPos = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions)); |
| const UVec2 renderSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes)); |
| const TestConfig testConfig (renderPass, |
| render, |
| commandBuffer, |
| imageMemory, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 1293809, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(attachmentCountGroup.get(), testCaseName.c_str(), testCaseName.c_str(), createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| |
| group->addChild(attachmentCountGroup.release()); |
| } |
| } |
| |
| void addAttachmentWriteMaskTests (tcu::TestCaseGroup* group, const TestConfigExternal testConfigExternal) |
| { |
| const deUint32 attachmentCounts[] = { 1, 2, 3, 4, 8 }; |
| |
| const VkFormat attachmentFormats[] = |
| { |
| VK_FORMAT_R8G8B8A8_UINT, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| VK_FORMAT_R5G6B5_UNORM_PACK16, |
| VK_FORMAT_R8G8_UNORM |
| }; |
| |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| for (deUint32 attachmentCountNdx = 0; attachmentCountNdx < DE_LENGTH_OF_ARRAY(attachmentCounts); attachmentCountNdx++) |
| { |
| const deUint32 attachmentCount = attachmentCounts[attachmentCountNdx]; |
| const string groupName = "attachment_count_" + de::toString(attachmentCount); |
| |
| de::MovePtr<tcu::TestCaseGroup> attachmentCountGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str(), de::toString(attachmentCount).c_str())); |
| |
| for (deUint32 drawStartNdx = 0; drawStartNdx < (attachmentCount); drawStartNdx++) |
| { |
| deUint32 formatNdx = 0; |
| vector<Attachment> attachments; |
| vector<AttachmentReference> colorAttachmentReferences; |
| |
| for (deUint32 attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++) |
| { |
| const VkFormat format = attachmentFormats[formatNdx]; |
| const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; |
| const VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; |
| const VkAttachmentStoreOp storeOp = VK_ATTACHMENT_STORE_OP_STORE; |
| const VkAttachmentLoadOp stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; |
| const VkAttachmentStoreOp stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; |
| const VkImageLayout initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| const VkImageLayout finalizeLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| const VkImageLayout subpassLayout = VK_IMAGE_LAYOUT_GENERAL; |
| |
| attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout)); |
| colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout)); |
| |
| if (++formatNdx == DE_LENGTH_OF_ARRAY(attachmentFormats)) |
| formatNdx = 0; |
| } |
| |
| { |
| const VkImageLayout depthStencilLayout = VK_IMAGE_LAYOUT_GENERAL; |
| const vector<Subpass> subpass (1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, depthStencilLayout), vector<deUint32>())); |
| const vector<SubpassDependency> deps; |
| |
| const string testCaseName = "start_index_" + de::toString(drawStartNdx); |
| const RenderPass renderPass (attachments, subpass, deps); |
| |
| const TestConfig::RenderTypes render = TestConfig::RENDERTYPES_DRAW; |
| const TestConfig::CommandBufferTypes commandBuffer = TestConfig::COMMANDBUFFERTYPES_INLINE; |
| const TestConfig::ImageMemory imageMemory = TestConfig::IMAGEMEMORY_LAZY; |
| const UVec2 targetSize = UVec2(64, 64); |
| const UVec2 renderPos = UVec2(0, 0); |
| const UVec2 renderSize = UVec2(64, 64); |
| const deBool useFormatCompCount = DE_TRUE; |
| const vector<DeviceCoreFeature> requiredFeatures = {DEVICE_CORE_FEATURE_INDEPENDENT_BLEND}; |
| const TestConfig testConfig (renderPass, |
| render, |
| commandBuffer, |
| imageMemory, |
| targetSize, |
| renderPos, |
| renderSize, |
| useFormatCompCount, |
| 1293809, |
| drawStartNdx, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType, |
| requiredFeatures); |
| |
| addFunctionCaseWithPrograms<TestConfig>(attachmentCountGroup.get(), testCaseName.c_str(), testCaseName.c_str(), checkSupport, createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| |
| group->addChild(attachmentCountGroup.release()); |
| } |
| } |
| |
| template<typename T> |
| T chooseRandom (de::Random& rng, const set<T>& values) |
| { |
| size_t ndx = ((size_t)rng.getUint32()) % values.size(); |
| typename set<T>::const_iterator iter = values.begin(); |
| |
| for (; ndx > 0; ndx--) |
| iter++; |
| |
| return *iter; |
| } |
| |
| void addAttachmentAllocationTests (tcu::TestCaseGroup* group, const TestConfigExternal testConfigExternal) |
| { |
| const deUint32 attachmentCounts[] = { 4, 8 }; |
| const VkAttachmentLoadOp loadOps[] = |
| { |
| VK_ATTACHMENT_LOAD_OP_LOAD, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE |
| }; |
| |
| const VkAttachmentStoreOp storeOps[] = |
| { |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE |
| }; |
| |
| const VkImageLayout initialAndFinalColorLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_GENERAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL |
| }; |
| |
| const VkImageLayout initialAndFinalDepthStencilLayouts[] = |
| { |
| VK_IMAGE_LAYOUT_GENERAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL |
| }; |
| |
| const VkImageLayout subpassLayoutsColor[] = |
| { |
| VK_IMAGE_LAYOUT_GENERAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL |
| }; |
| |
| const VkImageLayout subpassLayoutsDepthStencil[] = |
| { |
| VK_IMAGE_LAYOUT_GENERAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL |
| }; |
| |
| const VkImageLayout subpassLayoutsInput[] = |
| { |
| VK_IMAGE_LAYOUT_GENERAL, |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
| }; |
| |
| enum AllocationType |
| { |
| // Each pass uses one more attachmen than previous one |
| ALLOCATIONTYPE_GROW, |
| // Each pass uses one less attachment than previous one |
| ALLOCATIONTYPE_SHRINK, |
| // Each pass drops one attachment and picks up new one |
| ALLOCATIONTYPE_ROLL, |
| // Start by growing and end by shrinking |
| ALLOCATIONTYPE_GROW_SHRINK, |
| // Each subpass has single input and single output attachment |
| ALLOCATIONTYPE_IO_CHAIN, |
| // Each subpass has multiple inputs and multiple outputs attachment |
| ALLOCATIONTYPE_IO_GENERIC |
| }; |
| |
| const AllocationType allocationTypes[] = |
| { |
| ALLOCATIONTYPE_GROW, |
| ALLOCATIONTYPE_SHRINK, |
| ALLOCATIONTYPE_ROLL, |
| ALLOCATIONTYPE_GROW_SHRINK, |
| ALLOCATIONTYPE_IO_CHAIN, |
| ALLOCATIONTYPE_IO_GENERIC |
| }; |
| |
| const char* const allocationTypeStr[] = |
| { |
| "grow", |
| "shrink", |
| "roll", |
| "grow_shrink", |
| "input_output_chain", |
| "input_output", |
| }; |
| |
| const TestConfig::RenderTypes renderCommands[] = |
| { |
| TestConfig::RENDERTYPES_NONE, |
| TestConfig::RENDERTYPES_CLEAR, |
| TestConfig::RENDERTYPES_DRAW, |
| TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW, |
| }; |
| |
| const TestConfig::CommandBufferTypes commandBuffers[] = |
| { |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::COMMANDBUFFERTYPES_SECONDARY, |
| TestConfig::COMMANDBUFFERTYPES_INLINE|TestConfig::COMMANDBUFFERTYPES_SECONDARY |
| }; |
| |
| const TestConfig::ImageMemory imageMemories[] = |
| { |
| TestConfig::IMAGEMEMORY_STRICT, |
| TestConfig::IMAGEMEMORY_LAZY, |
| TestConfig::IMAGEMEMORY_STRICT|TestConfig::IMAGEMEMORY_LAZY |
| }; |
| |
| const UVec2 targetSizes[] = |
| { |
| UVec2(64, 64), |
| UVec2(63, 65) |
| }; |
| |
| const UVec2 renderPositions[] = |
| { |
| UVec2(0, 0), |
| UVec2(3, 17) |
| }; |
| |
| const UVec2 renderSizes[] = |
| { |
| UVec2(32, 32), |
| UVec2(60, 47) |
| }; |
| |
| tcu::TestContext& testCtx = group->getTestContext(); |
| de::Random rng (3700649827u); |
| |
| for (size_t allocationTypeNdx = 0; allocationTypeNdx < DE_LENGTH_OF_ARRAY(allocationTypes); allocationTypeNdx++) |
| { |
| const AllocationType allocationType = allocationTypes[allocationTypeNdx]; |
| const size_t testCaseCount = 100; |
| de::MovePtr<tcu::TestCaseGroup> allocationTypeGroup (new tcu::TestCaseGroup(testCtx, allocationTypeStr[allocationTypeNdx], allocationTypeStr[allocationTypeNdx])); |
| |
| for (size_t testCaseNdx = 0; testCaseNdx < testCaseCount; testCaseNdx++) |
| { |
| if (allocationType == ALLOCATIONTYPE_IO_GENERIC) |
| { |
| const deUint32 attachmentCount = 4u + rng.getUint32() % 31u; |
| const deUint32 subpassCount = 4u + rng.getUint32() % 31u; |
| vector<Attachment> attachments; |
| |
| set<deUint32> definedAttachments; |
| |
| vector<Subpass> subpasses; |
| set<deUint32> colorAttachments; |
| set<deUint32> depthStencilAttachments; |
| |
| for (deUint32 attachmentIndex = 0; attachmentIndex < attachmentCount; attachmentIndex++) |
| { |
| const bool isDepthStencilAttachment = rng.getFloat() < 0.01f; |
| const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; |
| const VkAttachmentLoadOp loadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps)); |
| const VkAttachmentStoreOp storeOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps)); |
| |
| const VkImageLayout initialLayout = isDepthStencilAttachment |
| ? rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts), DE_ARRAY_END(initialAndFinalDepthStencilLayouts)) |
| : rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts)); |
| const VkImageLayout finalizeLayout = isDepthStencilAttachment |
| ? rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts), DE_ARRAY_END(initialAndFinalDepthStencilLayouts)) |
| : rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts)); |
| |
| const VkAttachmentLoadOp stencilLoadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps)); |
| const VkAttachmentStoreOp stencilStoreOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps)); |
| |
| if (isDepthStencilAttachment) |
| { |
| const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreDepthStencilFormats), DE_ARRAY_END(s_coreDepthStencilFormats)); |
| |
| if (loadOp == VK_ATTACHMENT_LOAD_OP_LOAD || loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR |
| || stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD || stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) |
| definedAttachments.insert(attachmentIndex); |
| |
| depthStencilAttachments.insert(attachmentIndex); |
| |
| attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout)); |
| } |
| else |
| { |
| const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreColorFormats), DE_ARRAY_END(s_coreColorFormats)); |
| |
| if (loadOp == VK_ATTACHMENT_LOAD_OP_LOAD || loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) |
| definedAttachments.insert(attachmentIndex); |
| |
| colorAttachments.insert(attachmentIndex); |
| |
| attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout)); |
| } |
| } |
| vector<Maybe<deUint32> > lastUseOfAttachment (attachments.size(), nothing<deUint32>()); |
| vector<SubpassDependency> deps; |
| |
| for (deUint32 subpassIndex = 0; subpassIndex < subpassCount; subpassIndex++) |
| { |
| const deUint32 colorAttachmentCount = depthStencilAttachments.empty() |
| ? 1 + rng.getUint32() % de::min(4u, (deUint32)colorAttachments.size()) |
| : rng.getUint32() % (de::min(4u, (deUint32)colorAttachments.size()) + 1u); |
| const deUint32 inputAttachmentCount = rng.getUint32() % (deUint32)(de::min<size_t>(4, definedAttachments.size()) + 1); |
| const bool useDepthStencilAttachment = !depthStencilAttachments.empty() && (colorAttachmentCount == 0 || rng.getBool()); |
| std::vector<deUint32> subpassColorAttachments (colorAttachmentCount); |
| std::vector<deUint32> subpassInputAttachments (inputAttachmentCount); |
| Maybe<deUint32> depthStencilAttachment (useDepthStencilAttachment |
| ? just(chooseRandom(rng, depthStencilAttachments)) |
| : nothing<deUint32>()); |
| std::vector<deUint32> subpassPreserveAttachments; |
| |
| rng.choose(colorAttachments.begin(), colorAttachments.end(), subpassColorAttachments.begin(), colorAttachmentCount); |
| rng.choose(definedAttachments.begin(), definedAttachments.end(), subpassInputAttachments.begin(), inputAttachmentCount); |
| |
| for (size_t colorAttachmentNdx = 0; colorAttachmentNdx < subpassColorAttachments.size(); colorAttachmentNdx++) |
| definedAttachments.insert(subpassColorAttachments[colorAttachmentNdx]); |
| |
| if (depthStencilAttachment) |
| definedAttachments.insert(*depthStencilAttachment); |
| |
| { |
| std::vector<AttachmentReference> inputAttachmentReferences; |
| std::vector<AttachmentReference> colorAttachmentReferences; |
| AttachmentReference depthStencilAttachmentReference (VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL); |
| |
| for (size_t colorAttachmentNdx = 0; colorAttachmentNdx < subpassColorAttachments.size(); colorAttachmentNdx++) |
| { |
| const deUint32 colorAttachmentIndex = subpassColorAttachments[colorAttachmentNdx]; |
| |
| if (lastUseOfAttachment[colorAttachmentIndex]) |
| { |
| const bool byRegion = rng.getBool(); |
| |
| deps.push_back(SubpassDependency(*lastUseOfAttachment[colorAttachmentIndex], subpassIndex, |
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
| | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
| | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| |
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
| | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
| | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, |
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, |
| |
| byRegion ? (VkDependencyFlags)VK_DEPENDENCY_BY_REGION_BIT : 0u)); |
| } |
| |
| lastUseOfAttachment[colorAttachmentIndex] = just(subpassIndex); |
| |
| colorAttachmentReferences.push_back(AttachmentReference((deUint32)subpassColorAttachments[colorAttachmentNdx], VK_IMAGE_LAYOUT_GENERAL)); |
| } |
| |
| for (size_t inputAttachmentNdx = 0; inputAttachmentNdx < subpassInputAttachments.size(); inputAttachmentNdx++) |
| { |
| const deUint32 inputAttachmentIndex = subpassInputAttachments[inputAttachmentNdx]; |
| |
| if(lastUseOfAttachment[inputAttachmentIndex]) |
| { |
| const bool byRegion = (*lastUseOfAttachment[inputAttachmentIndex] == subpassIndex) || rng.getBool(); |
| |
| deps.push_back(SubpassDependency(*lastUseOfAttachment[inputAttachmentIndex], subpassIndex, |
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
| | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
| | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| |
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
| | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
| | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
| VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| |
| byRegion ? (VkDependencyFlags)VK_DEPENDENCY_BY_REGION_BIT : 0u)); |
| |
| lastUseOfAttachment[inputAttachmentIndex] = just(subpassIndex); |
| |
| VkImageAspectFlags aspect = 0u; |
| if (testConfigExternal.renderPassType == RENDERPASS_TYPE_RENDERPASS2) |
| { |
| bool col = colorAttachments.find(inputAttachmentIndex) != colorAttachments.end(); |
| aspect = col ? VK_IMAGE_ASPECT_COLOR_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; |
| } |
| inputAttachmentReferences.push_back(AttachmentReference((deUint32)subpassInputAttachments[inputAttachmentNdx], VK_IMAGE_LAYOUT_GENERAL, aspect)); |
| } |
| } |
| |
| if (depthStencilAttachment) |
| { |
| if (lastUseOfAttachment[*depthStencilAttachment]) |
| { |
| const bool byRegion = (*lastUseOfAttachment[*depthStencilAttachment] == subpassIndex) || rng.getBool(); |
| |
| deps.push_back(SubpassDependency(*lastUseOfAttachment[*depthStencilAttachment], subpassIndex, |
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
| | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
| | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| |
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
| | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
| | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
| VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| |
| byRegion ? (VkDependencyFlags)VK_DEPENDENCY_BY_REGION_BIT : 0u)); |
| } |
| |
| lastUseOfAttachment[*depthStencilAttachment] = just(subpassIndex); |
| depthStencilAttachmentReference = AttachmentReference(*depthStencilAttachment, VK_IMAGE_LAYOUT_GENERAL); |
| } |
| else |
| depthStencilAttachmentReference = AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL); |
| |
| vector<deUint32> preserveAttachments; |
| for (deUint32 attachmentIndex = 0; attachmentIndex < (deUint32)attachments.size(); attachmentIndex++) |
| { |
| if (lastUseOfAttachment[attachmentIndex] && (*lastUseOfAttachment[attachmentIndex]) != subpassIndex) |
| preserveAttachments.push_back(attachmentIndex); |
| } |
| |
| // Use random image layout when possible |
| for (size_t colorRefIdx = 0; colorRefIdx < colorAttachmentReferences.size(); ++colorRefIdx) |
| { |
| bool usedAsInput = false; |
| for (size_t inputRefIdx = 0; inputRefIdx < inputAttachmentReferences.size(); ++inputRefIdx) |
| if (colorAttachmentReferences[colorRefIdx].getAttachment() == inputAttachmentReferences[inputRefIdx].getAttachment()) |
| usedAsInput = true; |
| |
| if (!usedAsInput) |
| colorAttachmentReferences[colorRefIdx].setImageLayout(rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor))); |
| } |
| for (size_t inputRefIdx = 0; inputRefIdx < inputAttachmentReferences.size(); ++inputRefIdx) |
| { |
| bool usedAsDepthStencil = inputAttachmentReferences[inputRefIdx].getAttachment() == depthStencilAttachmentReference.getAttachment(); |
| bool usedAsColor = false; |
| for (size_t colorRefIdx = 0; colorRefIdx < colorAttachmentReferences.size(); ++colorRefIdx) |
| if (inputAttachmentReferences[inputRefIdx].getAttachment() == colorAttachmentReferences[colorRefIdx].getAttachment()) |
| usedAsColor = true; |
| |
| if (!usedAsColor && !usedAsDepthStencil) |
| inputAttachmentReferences[inputRefIdx].setImageLayout(rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsInput), DE_ARRAY_END(subpassLayoutsInput))); |
| } |
| { |
| bool usedAsInput = false; |
| for (size_t inputRefIdx = 0; inputRefIdx < inputAttachmentReferences.size(); ++inputRefIdx) |
| if (depthStencilAttachmentReference.getAttachment() == inputAttachmentReferences[inputRefIdx].getAttachment()) |
| usedAsInput = true; |
| |
| if (!usedAsInput) |
| depthStencilAttachmentReference.setImageLayout(rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsDepthStencil), DE_ARRAY_END(subpassLayoutsDepthStencil))); |
| } |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, |
| inputAttachmentReferences, |
| colorAttachmentReferences, |
| vector<AttachmentReference>(), |
| depthStencilAttachmentReference, |
| preserveAttachments)); |
| } |
| } |
| { |
| const TestConfig::RenderTypes render = rng.choose<TestConfig::RenderTypes>(DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands)); |
| const TestConfig::CommandBufferTypes commandBuffer = rng.choose<TestConfig::CommandBufferTypes>(DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers)); |
| const TestConfig::ImageMemory imageMemory = rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories)); |
| |
| const string testCaseName = de::toString(testCaseNdx); |
| const UVec2 targetSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes)); |
| const UVec2 renderPos = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions)); |
| const UVec2 renderSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes)); |
| |
| const RenderPass renderPass (attachments, subpasses, deps); |
| const TestConfig testConfig (renderPass, |
| render, |
| commandBuffer, |
| imageMemory, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 80329, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(allocationTypeGroup.get(), testCaseName.c_str(), testCaseName.c_str(), createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| else |
| { |
| const deUint32 attachmentCount = rng.choose<deUint32>(DE_ARRAY_BEGIN(attachmentCounts), DE_ARRAY_END(attachmentCounts)); |
| vector<Attachment> attachments; |
| vector<Subpass> subpasses; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++) |
| { |
| const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; |
| const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreColorFormats), DE_ARRAY_END(s_coreColorFormats)); |
| const VkAttachmentLoadOp loadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps)); |
| const VkAttachmentStoreOp storeOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps)); |
| |
| const VkImageLayout initialLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts)); |
| const VkImageLayout finalizeLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts)); |
| |
| const VkAttachmentLoadOp stencilLoadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps)); |
| const VkAttachmentStoreOp stencilStoreOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps)); |
| |
| attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout)); |
| } |
| |
| if (allocationType == ALLOCATIONTYPE_GROW) |
| { |
| for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++) |
| { |
| vector<AttachmentReference> colorAttachmentReferences; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < subpassNdx + 1; attachmentNdx++) |
| { |
| const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor)); |
| |
| colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout)); |
| } |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, |
| vector<AttachmentReference>(), |
| colorAttachmentReferences, |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| } |
| } |
| else if (allocationType == ALLOCATIONTYPE_SHRINK) |
| { |
| for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++) |
| { |
| vector<AttachmentReference> colorAttachmentReferences; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < (attachmentCount - subpassNdx); attachmentNdx++) |
| { |
| const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor)); |
| |
| colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout)); |
| } |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, |
| vector<AttachmentReference>(), |
| colorAttachmentReferences, |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| } |
| } |
| else if (allocationType == ALLOCATIONTYPE_ROLL) |
| { |
| for (size_t subpassNdx = 0; subpassNdx < attachmentCount / 2; subpassNdx++) |
| { |
| vector<AttachmentReference> colorAttachmentReferences; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount / 2; attachmentNdx++) |
| { |
| const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor)); |
| |
| colorAttachmentReferences.push_back(AttachmentReference((deUint32)(subpassNdx + attachmentNdx), subpassLayout)); |
| } |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, |
| vector<AttachmentReference>(), |
| colorAttachmentReferences, |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| } |
| } |
| else if (allocationType == ALLOCATIONTYPE_GROW_SHRINK) |
| { |
| for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++) |
| { |
| vector<AttachmentReference> colorAttachmentReferences; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < subpassNdx + 1; attachmentNdx++) |
| { |
| const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor)); |
| |
| colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout)); |
| } |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, |
| vector<AttachmentReference>(), |
| colorAttachmentReferences, |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| } |
| |
| for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++) |
| { |
| vector<AttachmentReference> colorAttachmentReferences; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < (attachmentCount - subpassNdx); attachmentNdx++) |
| { |
| const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor)); |
| |
| colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout)); |
| } |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, |
| vector<AttachmentReference>(), |
| colorAttachmentReferences, |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| } |
| } |
| else if (allocationType == ALLOCATIONTYPE_IO_CHAIN) |
| { |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(1, AttachmentReference(0, rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor)))), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| |
| for (size_t subpassNdx = 1; subpassNdx < attachmentCount; subpassNdx++) |
| { |
| const VkImageAspectFlags inputAttachmentAspectMask = (testConfigExternal.renderPassType == RENDERPASS_TYPE_RENDERPASS2) ? VK_IMAGE_ASPECT_COLOR_BIT : static_cast<VkImageAspectFlagBits>(0); |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, |
| vector<AttachmentReference>(1, AttachmentReference((deUint32)(subpassNdx - 1), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, inputAttachmentAspectMask)), |
| vector<AttachmentReference>(1, AttachmentReference((deUint32)(subpassNdx), rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor)))), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| } |
| } |
| else |
| DE_FATAL("Unknown allocation type"); |
| |
| { |
| const TestConfig::RenderTypes render = rng.choose<TestConfig::RenderTypes>(DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands)); |
| const TestConfig::CommandBufferTypes commandBuffer = rng.choose<TestConfig::CommandBufferTypes>(DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers)); |
| const TestConfig::ImageMemory imageMemory = rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories)); |
| |
| const string testCaseName = de::toString(testCaseNdx); |
| const UVec2 targetSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes)); |
| const UVec2 renderPos = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions)); |
| const UVec2 renderSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes)); |
| |
| vector<SubpassDependency> deps; |
| |
| for (size_t subpassNdx = 0; subpassNdx < subpasses.size() - 1; subpassNdx++) |
| { |
| const bool byRegion = rng.getBool(); |
| deps.push_back(SubpassDependency((deUint32)subpassNdx, (deUint32)subpassNdx + 1, |
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
| | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
| | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| |
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
| | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
| | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, |
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, |
| |
| byRegion ? (VkDependencyFlags)VK_DEPENDENCY_BY_REGION_BIT : 0u)); |
| } |
| |
| const RenderPass renderPass (attachments, subpasses, deps); |
| const TestConfig testConfig (renderPass, |
| render, |
| commandBuffer, |
| imageMemory, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 80329, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(allocationTypeGroup.get(), testCaseName.c_str(), testCaseName.c_str(), createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| } |
| group->addChild(allocationTypeGroup.release()); |
| } |
| } |
| |
| void addSimpleTests (tcu::TestCaseGroup* group, const TestConfigExternal testConfigExternal) |
| { |
| const UVec2 targetSize (64, 64); |
| const UVec2 renderPos (0, 0); |
| const UVec2 renderSize (64, 64); |
| |
| // color |
| { |
| const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_R8G8B8A8_UNORM, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())), |
| vector<SubpassDependency>()); |
| const TestConfig testConfig (renderPass, |
| TestConfig::RENDERTYPES_DRAW, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(group, "color", "Single color attachment case.", createTestShaders, renderPassTest, testConfig); |
| } |
| |
| // depth |
| { |
| const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_X8_D24_UNORM_PACK32, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)), |
| vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())), |
| vector<SubpassDependency>()); |
| const TestConfig testConfig (renderPass, |
| TestConfig::RENDERTYPES_DRAW, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(group, "depth", "Single depth attachment case.", createTestShaders, renderPassTest, testConfig); |
| } |
| |
| // stencil |
| { |
| const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_S8_UINT, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)), |
| vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())), |
| vector<SubpassDependency>()); |
| const TestConfig testConfig (renderPass, |
| TestConfig::RENDERTYPES_DRAW, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(group, "stencil", "Single stencil attachment case.", createTestShaders, renderPassTest, testConfig); |
| } |
| |
| // depth_stencil |
| { |
| const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_D24_UNORM_S8_UINT, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)), |
| vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())), |
| vector<SubpassDependency>()); |
| const TestConfig testConfig (renderPass, |
| TestConfig::RENDERTYPES_DRAW, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(group, "depth_stencil", "Single depth stencil attachment case.", createTestShaders, renderPassTest, testConfig); |
| } |
| |
| // color_depth |
| { |
| const Attachment attachments[] = |
| { |
| Attachment(VK_FORMAT_R8G8B8A8_UNORM, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL), |
| Attachment(VK_FORMAT_X8_D24_UNORM_PACK32, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| }; |
| |
| const RenderPass renderPass (vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)), |
| vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())), |
| vector<SubpassDependency>()); |
| const TestConfig testConfig (renderPass, |
| TestConfig::RENDERTYPES_DRAW, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(group, "color_depth", "Color and depth attachment case.", createTestShaders, renderPassTest, testConfig); |
| } |
| |
| // color_stencil |
| { |
| const Attachment attachments[] = |
| { |
| Attachment(VK_FORMAT_R8G8B8A8_UNORM, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL), |
| Attachment(VK_FORMAT_S8_UINT, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| }; |
| |
| const RenderPass renderPass (vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)), |
| vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())), |
| vector<SubpassDependency>()); |
| const TestConfig testConfig (renderPass, |
| TestConfig::RENDERTYPES_DRAW, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(group, "color_stencil", "Color and stencil attachment case.", createTestShaders, renderPassTest, testConfig); |
| } |
| |
| // color_depth_stencil |
| { |
| const Attachment attachments[] = |
| { |
| Attachment(VK_FORMAT_R8G8B8A8_UNORM, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL), |
| Attachment(VK_FORMAT_D24_UNORM_S8_UINT, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| }; |
| |
| const RenderPass renderPass (vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)), |
| vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())), |
| vector<SubpassDependency>()); |
| const TestConfig testConfig (renderPass, |
| TestConfig::RENDERTYPES_DRAW, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(group, "color_depth_stencil", "Color, depth and stencil attachment case.", createTestShaders, renderPassTest, testConfig); |
| } |
| |
| // no attachments |
| { |
| const RenderPass renderPass (vector<Attachment>(), |
| vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())), |
| vector<SubpassDependency>()); |
| const TestConfig testConfig (renderPass, |
| TestConfig::RENDERTYPES_DRAW, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(group, "no_attachments", "No attachments case.", createTestShaders, renderPassTest, testConfig); |
| } |
| |
| // color_unused_omit_blend_state |
| { |
| vector<Subpass> subpasses; |
| |
| // First subpass: use color attachment, create pipeline with color blend state |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>(), |
| false)); |
| |
| // Second subpass: don't use color attachment, create pipeline without color blend state |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(1, AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>(), |
| true)); |
| |
| const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_R8G8B8A8_UNORM, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_CLEAR, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| subpasses, |
| vector<SubpassDependency>()); |
| |
| const TestConfig testConfig (renderPass, |
| TestConfig::RENDERTYPES_DRAW, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| addFunctionCaseWithPrograms<TestConfig>(group, "color_unused_omit_blend_state", "Two unused color attachment case without blend state", createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| |
| std::string formatToName (VkFormat format) |
| { |
| const std::string formatStr = de::toString(format); |
| const std::string prefix = "VK_FORMAT_"; |
| |
| DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix); |
| |
| return de::toLower(formatStr.substr(prefix.length())); |
| } |
| |
| void addFormatTests (tcu::TestCaseGroup* group, const TestConfigExternal testConfigExternal) |
| { |
| tcu::TestContext& testCtx = group->getTestContext(); |
| |
| const UVec2 targetSize (64, 64); |
| const UVec2 renderPos (0, 0); |
| const UVec2 renderSize (64, 64); |
| |
| const struct |
| { |
| const char* const str; |
| const VkAttachmentStoreOp op; |
| } storeOps[] = |
| { |
| { "store", VK_ATTACHMENT_STORE_OP_STORE }, |
| { "dont_care", VK_ATTACHMENT_STORE_OP_DONT_CARE } |
| }; |
| |
| const struct |
| { |
| const char* const str; |
| const VkAttachmentLoadOp op; |
| } loadOps[] = |
| { |
| { "clear", VK_ATTACHMENT_LOAD_OP_CLEAR }, |
| { "load", VK_ATTACHMENT_LOAD_OP_LOAD }, |
| { "dont_care", VK_ATTACHMENT_LOAD_OP_DONT_CARE } |
| }; |
| |
| const struct |
| { |
| const char* const str; |
| const TestConfig::RenderTypes types; |
| } renderTypes[] = |
| { |
| { "clear", TestConfig::RENDERTYPES_CLEAR }, |
| { "draw", TestConfig::RENDERTYPES_DRAW }, |
| { "clear_draw", TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW } |
| }; |
| |
| // Color formats |
| for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_coreColorFormats); formatNdx++) |
| { |
| const VkFormat format = s_coreColorFormats[formatNdx]; |
| de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatToName(format).c_str(), de::toString(format).c_str())); |
| |
| for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++) |
| { |
| const VkAttachmentLoadOp loadOp = loadOps[loadOpNdx].op; |
| de::MovePtr<tcu::TestCaseGroup> loadOpGroup (new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str, loadOps[loadOpNdx].str)); |
| |
| for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++) |
| { |
| const RenderPass renderPass (vector<Attachment>(1, Attachment(format, |
| VK_SAMPLE_COUNT_1_BIT, |
| loadOp, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())), |
| vector<SubpassDependency>()); |
| const TestConfig testConfig (renderPass, |
| renderTypes[renderTypeNdx].types, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), renderTypes[renderTypeNdx].str, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, testConfig); |
| } |
| |
| formatGroup->addChild(loadOpGroup.release()); |
| } |
| |
| { |
| de::MovePtr<tcu::TestCaseGroup> inputGroup (new tcu::TestCaseGroup(testCtx, "input", "Test attachment format as input")); |
| |
| for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++) |
| { |
| const VkAttachmentLoadOp loadOp = loadOps[loadOpNdx].op; |
| de::MovePtr<tcu::TestCaseGroup> loadOpGroup (new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str, loadOps[loadOpNdx].str)); |
| |
| for (size_t storeOpNdx = 0; storeOpNdx < DE_LENGTH_OF_ARRAY(storeOps); storeOpNdx++) |
| { |
| const VkImageAspectFlags inputAttachmentAspectMask = (testConfigExternal.renderPassType == RENDERPASS_TYPE_RENDERPASS2) |
| ? static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT) |
| : static_cast<VkImageAspectFlags>(0); |
| const VkAttachmentStoreOp storeOp = storeOps[storeOpNdx].op; |
| de::MovePtr<tcu::TestCaseGroup> storeOpGroup (new tcu::TestCaseGroup(testCtx, storeOps[storeOpNdx].str, storeOps[storeOpNdx].str)); |
| |
| for (size_t useInputAspectNdx = 0; useInputAspectNdx < 2; useInputAspectNdx++) |
| { |
| const bool useInputAspect = useInputAspectNdx != 0; |
| |
| if (testConfigExternal.renderPassType == RENDERPASS_TYPE_RENDERPASS2 && useInputAspect) |
| continue; |
| |
| for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++) |
| { |
| { |
| vector<Attachment> attachments; |
| vector<Subpass> subpasses; |
| vector<SubpassDependency> deps; |
| vector<VkInputAttachmentAspectReference> inputAspects; |
| |
| attachments.push_back(Attachment(format, |
| VK_SAMPLE_COUNT_1_BIT, |
| loadOp, |
| storeOp, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); |
| |
| attachments.push_back(Attachment(vk::VK_FORMAT_R8G8B8A8_UNORM, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, inputAttachmentAspectMask)), |
| vector<AttachmentReference>(1, AttachmentReference(1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| |
| deps.push_back(SubpassDependency(0, 1, |
| |
| vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, |
| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| |
| vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, |
| vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| vk::VK_DEPENDENCY_BY_REGION_BIT)); |
| |
| if (useInputAspect) |
| { |
| const VkInputAttachmentAspectReference inputAspect = |
| { |
| 1u, |
| 0u, |
| VK_IMAGE_ASPECT_COLOR_BIT |
| }; |
| |
| inputAspects.push_back(inputAspect); |
| } |
| |
| { |
| const RenderPass renderPass (attachments, subpasses, deps, inputAspects); |
| const TestConfig testConfig (renderPass, |
| renderTypes[renderTypeNdx].types, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 89246, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| const string testName (renderTypes[renderTypeNdx].str + string(useInputAspect ? "_use_input_aspect" : "")); |
| |
| addFunctionCaseWithPrograms<TestConfig>(storeOpGroup.get(), testName, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| { |
| vector<Attachment> attachments; |
| vector<Subpass> subpasses; |
| vector<SubpassDependency> deps; |
| vector<VkInputAttachmentAspectReference> inputAspects; |
| |
| attachments.push_back(Attachment(format, |
| VK_SAMPLE_COUNT_1_BIT, |
| loadOp, |
| storeOp, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_GENERAL, inputAttachmentAspectMask)), |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_GENERAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| |
| deps.push_back(SubpassDependency(0, 1, |
| vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, |
| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| |
| vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, |
| vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| vk::VK_DEPENDENCY_BY_REGION_BIT)); |
| |
| deps.push_back(SubpassDependency(1, 1, |
| vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, |
| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| |
| vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, |
| vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| vk::VK_DEPENDENCY_BY_REGION_BIT)); |
| |
| if (useInputAspect) |
| { |
| const VkInputAttachmentAspectReference inputAspect = |
| { |
| 1u, |
| 0u, |
| VK_IMAGE_ASPECT_COLOR_BIT |
| }; |
| |
| inputAspects.push_back(inputAspect); |
| } |
| |
| { |
| const RenderPass renderPass (attachments, subpasses, deps, inputAspects); |
| const TestConfig testConfig (renderPass, |
| renderTypes[renderTypeNdx].types, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 89246, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| const string testName (string("self_dep_") + renderTypes[renderTypeNdx].str + (useInputAspect ? "_use_input_aspect" : "")); |
| |
| addFunctionCaseWithPrograms<TestConfig>(storeOpGroup.get(), testName, string("self_dep_") + renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| } |
| } |
| |
| loadOpGroup->addChild(storeOpGroup.release()); |
| } |
| |
| inputGroup->addChild(loadOpGroup.release()); |
| } |
| |
| formatGroup->addChild(inputGroup.release()); |
| } |
| |
| group->addChild(formatGroup.release()); |
| } |
| |
| // Depth stencil formats |
| for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_coreDepthStencilFormats); formatNdx++) |
| { |
| const VkFormat vkFormat = s_coreDepthStencilFormats[formatNdx]; |
| const tcu::TextureFormat format = mapVkFormat(vkFormat); |
| const bool isStencilAttachment = hasStencilComponent(format.order); |
| const bool isDepthAttachment = hasDepthComponent(format.order); |
| const VkImageAspectFlags formatAspectFlags = (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
| | (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT : 0u); |
| de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatToName(vkFormat).c_str(), de::toString(vkFormat).c_str())); |
| |
| for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++) |
| { |
| const VkAttachmentLoadOp loadOp = loadOps[loadOpNdx].op; |
| de::MovePtr<tcu::TestCaseGroup> loadOpGroup (new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str, loadOps[loadOpNdx].str)); |
| |
| for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++) |
| { |
| { |
| const RenderPass renderPass (vector<Attachment>(1, Attachment(vkFormat, |
| VK_SAMPLE_COUNT_1_BIT, |
| isDepthAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| isDepthAttachment ? VK_ATTACHMENT_STORE_OP_STORE :VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| isStencilAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| isStencilAttachment ? VK_ATTACHMENT_STORE_OP_STORE :VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)), |
| vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())), |
| vector<SubpassDependency>()); |
| const TestConfig testConfig (renderPass, |
| renderTypes[renderTypeNdx].types, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| |
| addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), renderTypes[renderTypeNdx].str, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, testConfig); |
| } |
| |
| if (isStencilAttachment && isDepthAttachment && loadOp != VK_ATTACHMENT_LOAD_OP_CLEAR) |
| { |
| { |
| const RenderPass renderPass (vector<Attachment>(1, Attachment(vkFormat, |
| VK_SAMPLE_COUNT_1_BIT, |
| isDepthAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| isDepthAttachment ? VK_ATTACHMENT_STORE_OP_STORE :VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| isStencilAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| isStencilAttachment ? VK_ATTACHMENT_STORE_OP_STORE :VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)), |
| vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())), |
| vector<SubpassDependency>()); |
| const TestConfig testConfig (renderPass, |
| renderTypes[renderTypeNdx].types, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| const string testName (string(renderTypes[renderTypeNdx].str) + "_depth_read_only"); |
| |
| addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), testName, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, testConfig); |
| } |
| |
| { |
| const RenderPass renderPass (vector<Attachment>(1, Attachment(vkFormat, |
| VK_SAMPLE_COUNT_1_BIT, |
| isDepthAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| isDepthAttachment ? VK_ATTACHMENT_STORE_OP_STORE :VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| isStencilAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| isStencilAttachment ? VK_ATTACHMENT_STORE_OP_STORE :VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)), |
| vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL), |
| vector<deUint32>())), |
| vector<SubpassDependency>()); |
| const TestConfig testConfig (renderPass, |
| renderTypes[renderTypeNdx].types, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 90239, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| const string testName (string(renderTypes[renderTypeNdx].str) + "_stencil_read_only"); |
| |
| addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), testName, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| } |
| |
| formatGroup->addChild(loadOpGroup.release()); |
| } |
| |
| { |
| de::MovePtr<tcu::TestCaseGroup> inputGroup (new tcu::TestCaseGroup(testCtx, "input", "Test attachment format as input")); |
| |
| for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++) |
| { |
| const VkAttachmentLoadOp loadOp = loadOps[loadOpNdx].op; |
| de::MovePtr<tcu::TestCaseGroup> loadOpGroup (new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str, loadOps[loadOpNdx].str)); |
| |
| for (size_t storeOpNdx = 0; storeOpNdx < DE_LENGTH_OF_ARRAY(storeOps); storeOpNdx++) |
| { |
| const VkImageAspectFlags inputAttachmentAspectMask = (testConfigExternal.renderPassType == RENDERPASS_TYPE_RENDERPASS2) |
| ? formatAspectFlags |
| : static_cast<VkImageAspectFlags>(0); |
| const VkAttachmentStoreOp storeOp = storeOps[storeOpNdx].op; |
| de::MovePtr<tcu::TestCaseGroup> storeOpGroup (new tcu::TestCaseGroup(testCtx, storeOps[storeOpNdx].str, storeOps[storeOpNdx].str)); |
| |
| for (size_t useInputAspectNdx = 0; useInputAspectNdx < 2; useInputAspectNdx++) |
| { |
| const bool useInputAspect = useInputAspectNdx != 0; |
| |
| if (testConfigExternal.renderPassType == RENDERPASS_TYPE_RENDERPASS2 && useInputAspect) |
| continue; |
| |
| for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++) |
| { |
| { |
| vector<Attachment> attachments; |
| vector<Subpass> subpasses; |
| vector<SubpassDependency> deps; |
| vector<VkInputAttachmentAspectReference> inputAspects; |
| |
| attachments.push_back(Attachment(vkFormat, |
| VK_SAMPLE_COUNT_1_BIT, |
| loadOp, |
| storeOp, |
| loadOp, |
| storeOp, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); |
| |
| attachments.push_back(Attachment(vk::VK_FORMAT_R8G8B8A8_UNORM, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())); |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, inputAttachmentAspectMask)), |
| vector<AttachmentReference>(1, AttachmentReference(1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| |
| deps.push_back(SubpassDependency(0, 1, |
| vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| |
| vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
| vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| 0u)); |
| |
| if (useInputAspect) |
| { |
| const VkInputAttachmentAspectReference inputAspect = |
| { |
| 1u, |
| 0u, |
| (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
| | (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT : 0u) |
| }; |
| |
| inputAspects.push_back(inputAspect); |
| } |
| |
| { |
| const RenderPass renderPass (attachments, subpasses, deps, inputAspects); |
| const TestConfig testConfig (renderPass, |
| renderTypes[renderTypeNdx].types, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 89246, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| const string testName (renderTypes[renderTypeNdx].str + string(useInputAspect ? "_use_input_aspect" : "")); |
| |
| addFunctionCaseWithPrograms<TestConfig>(storeOpGroup.get(), testName, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| { |
| vector<Attachment> attachments; |
| vector<Subpass> subpasses; |
| vector<SubpassDependency> deps; |
| vector<VkInputAttachmentAspectReference> inputAspects; |
| |
| attachments.push_back(Attachment(vkFormat, |
| VK_SAMPLE_COUNT_1_BIT, |
| loadOp, |
| storeOp, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())); |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_GENERAL, inputAttachmentAspectMask)), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| |
| deps.push_back(SubpassDependency(0, 1, |
| vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| |
| vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
| vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| vk::VK_DEPENDENCY_BY_REGION_BIT)); |
| |
| deps.push_back(SubpassDependency(1, 1, |
| vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
| vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| vk::VK_DEPENDENCY_BY_REGION_BIT)); |
| |
| |
| if (useInputAspect) |
| { |
| const VkInputAttachmentAspectReference inputAspect = |
| { |
| 1u, |
| 0u, |
| |
| (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
| | (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT : 0u) |
| }; |
| |
| inputAspects.push_back(inputAspect); |
| } |
| |
| { |
| const RenderPass renderPass (attachments, subpasses, deps, inputAspects); |
| const TestConfig testConfig (renderPass, |
| renderTypes[renderTypeNdx].types, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 89246, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| const string testName (string("self_dep_") + renderTypes[renderTypeNdx].str + (useInputAspect ? "_use_input_aspect" : "")); |
| |
| addFunctionCaseWithPrograms<TestConfig>(storeOpGroup.get(), testName, string("self_dep_") + renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| |
| if (isStencilAttachment && isDepthAttachment) |
| { |
| // Depth read only |
| { |
| vector<Attachment> attachments; |
| vector<Subpass> subpasses; |
| vector<SubpassDependency> deps; |
| vector<VkInputAttachmentAspectReference> inputAspects; |
| |
| attachments.push_back(Attachment(vkFormat, |
| VK_SAMPLE_COUNT_1_BIT, |
| loadOp, |
| storeOp, |
| loadOp, |
| storeOp, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); |
| |
| attachments.push_back(Attachment(vk::VK_FORMAT_R8G8B8A8_UNORM, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())); |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, inputAttachmentAspectMask)), |
| vector<AttachmentReference>(1, AttachmentReference(1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| |
| deps.push_back(SubpassDependency(0, 1, |
| vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| |
| vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
| vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| 0u)); |
| |
| if (useInputAspect) |
| { |
| const VkInputAttachmentAspectReference inputAspect = |
| { |
| 1u, |
| 0u, |
| |
| (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
| | (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT : 0u) |
| }; |
| |
| inputAspects.push_back(inputAspect); |
| } |
| |
| { |
| const RenderPass renderPass (attachments, subpasses, deps, inputAspects); |
| const TestConfig testConfig (renderPass, |
| renderTypes[renderTypeNdx].types, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 89246, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| const string testName (renderTypes[renderTypeNdx].str + string(useInputAspect ? "_use_input_aspect" : "") + "_depth_read_only"); |
| |
| addFunctionCaseWithPrograms<TestConfig>(storeOpGroup.get(), testName, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| { |
| vector<Attachment> attachments; |
| vector<Subpass> subpasses; |
| vector<SubpassDependency> deps; |
| vector<VkInputAttachmentAspectReference> inputAspects; |
| |
| attachments.push_back(Attachment(vkFormat, |
| VK_SAMPLE_COUNT_1_BIT, |
| loadOp, |
| storeOp, |
| loadOp, |
| storeOp, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())); |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, inputAttachmentAspectMask)), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())); |
| |
| deps.push_back(SubpassDependency(0, 1, |
| vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| |
| vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
| vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| vk::VK_DEPENDENCY_BY_REGION_BIT)); |
| |
| deps.push_back(SubpassDependency(1, 1, |
| vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| |
| vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
| vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| vk::VK_DEPENDENCY_BY_REGION_BIT)); |
| |
| if (useInputAspect) |
| { |
| const VkInputAttachmentAspectReference inputAspect = |
| { |
| 1u, |
| 0u, |
| |
| (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
| | (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT : 0u) |
| }; |
| |
| inputAspects.push_back(inputAspect); |
| } |
| |
| { |
| const RenderPass renderPass (attachments, subpasses, deps, inputAspects); |
| const TestConfig testConfig (renderPass, |
| renderTypes[renderTypeNdx].types, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 89246, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| const string testName (string("self_dep_") + renderTypes[renderTypeNdx].str + (useInputAspect ? "_use_input_aspect" : "") + "_depth_read_only"); |
| |
| addFunctionCaseWithPrograms<TestConfig>(storeOpGroup.get(), testName, string("self_dep_") + renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| // Stencil read only |
| { |
| vector<Attachment> attachments; |
| vector<Subpass> subpasses; |
| vector<SubpassDependency> deps; |
| vector<VkInputAttachmentAspectReference> inputAspects; |
| |
| attachments.push_back(Attachment(vkFormat, |
| VK_SAMPLE_COUNT_1_BIT, |
| loadOp, |
| storeOp, |
| loadOp, |
| storeOp, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); |
| |
| attachments.push_back(Attachment(vk::VK_FORMAT_R8G8B8A8_UNORM, |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_STORE, |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())); |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, inputAttachmentAspectMask)), |
| vector<AttachmentReference>(1, AttachmentReference(1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)), |
| vector<AttachmentReference>(), |
| AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), |
| vector<deUint32>())); |
| |
| deps.push_back(SubpassDependency(0, 1, |
| vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, |
| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| |
| vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
| vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| 0u)); |
| |
| if (useInputAspect) |
| { |
| const VkInputAttachmentAspectReference inputAspect = |
| { |
| 1u, |
| 0u, |
| |
| (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
| | (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT : 0u) |
| }; |
| |
| inputAspects.push_back(inputAspect); |
| } |
| |
| { |
| const RenderPass renderPass (attachments, subpasses, deps, inputAspects); |
| const TestConfig testConfig (renderPass, |
| renderTypes[renderTypeNdx].types, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 89246, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| const string testName (renderTypes[renderTypeNdx].str + string(useInputAspect ? "_use_input_aspect" : "") + "_stencil_read_only"); |
| |
| addFunctionCaseWithPrograms<TestConfig>(storeOpGroup.get(), testName, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| { |
| vector<Attachment> attachments; |
| vector<Subpass> subpasses; |
| vector<SubpassDependency> deps; |
| vector<VkInputAttachmentAspectReference> inputAspects; |
| |
| attachments.push_back(Attachment(vkFormat, |
| VK_SAMPLE_COUNT_1_BIT, |
| loadOp, |
| storeOp, |
| loadOp, |
| storeOp, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); |
| |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), |
| vector<deUint32>())); |
| subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 0u, |
| vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, inputAttachmentAspectMask)), |
| vector<AttachmentReference>(), |
| vector<AttachmentReference>(), |
| AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL), |
| vector<deUint32>())); |
| |
| deps.push_back(SubpassDependency(0, 1, |
| vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| |
| vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
| vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| vk::VK_DEPENDENCY_BY_REGION_BIT)); |
| |
| deps.push_back(SubpassDependency(1, 1, |
| vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, |
| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, |
| |
| vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
| vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, |
| vk::VK_DEPENDENCY_BY_REGION_BIT)); |
| |
| |
| if (useInputAspect) |
| { |
| const VkInputAttachmentAspectReference inputAspect = |
| { |
| 1u, |
| 0u, |
| |
| (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
| | (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT : 0u) |
| }; |
| |
| inputAspects.push_back(inputAspect); |
| } |
| |
| { |
| const RenderPass renderPass (attachments, subpasses, deps, inputAspects); |
| const TestConfig testConfig (renderPass, |
| renderTypes[renderTypeNdx].types, |
| TestConfig::COMMANDBUFFERTYPES_INLINE, |
| TestConfig::IMAGEMEMORY_STRICT, |
| targetSize, |
| renderPos, |
| renderSize, |
| DE_FALSE, |
| 89246, |
| 0, |
| testConfigExternal.allocationKind, |
| testConfigExternal.renderPassType); |
| const string testName (string("self_dep_") + renderTypes[renderTypeNdx].str + (useInputAspect ? "_use_input_aspect" : "") + "_stencil_read_only"); |
| |
| addFunctionCaseWithPrograms<TestConfig>(storeOpGroup.get(), testName, string("self_dep_") + renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, testConfig); |
| } |
| } |
| } |
| } |
| } |
| |
| loadOpGroup->addChild(storeOpGroup.release()); |
| } |
| |
| inputGroup->addChild(loadOpGroup.release()); |
| } |
| |
| formatGroup->addChild(inputGroup.release()); |
| } |
| |
| group->addChild(formatGroup.release()); |
| } |
| } |
| |
| void addRenderPassTests (tcu::TestCaseGroup* group, const AllocationKind allocationKind, const RenderPassType renderPassType) |
| { |
| const TestConfigExternal testConfigExternal (allocationKind, renderPassType); |
| |
| addTestGroup(group, "simple", "Simple basic render pass tests", addSimpleTests, testConfigExternal); |
| addTestGroup(group, "formats", "Tests for different image formats.", addFormatTests, testConfigExternal); |
| addTestGroup(group, "attachment", "Attachment format and count tests with load and store ops and image layouts", addAttachmentTests, testConfigExternal); |
| addTestGroup(group, "attachment_allocation", "Attachment allocation tests", addAttachmentAllocationTests, testConfigExternal); |
| addTestGroup(group, "attachment_write_mask", "Attachment write mask tests", addAttachmentWriteMaskTests, testConfigExternal); |
| } |
| |
| de::MovePtr<tcu::TestCaseGroup> createSuballocationTests(tcu::TestContext& testCtx, RenderPassType renderPassType) |
| { |
| de::MovePtr<tcu::TestCaseGroup> suballocationTestsGroup(new tcu::TestCaseGroup(testCtx, "suballocation", "Suballocation RenderPass Tests")); |
| |
| addRenderPassTests(suballocationTestsGroup.get(), ALLOCATION_KIND_SUBALLOCATED, renderPassType); |
| |
| return suballocationTestsGroup; |
| } |
| |
| de::MovePtr<tcu::TestCaseGroup> createDedicatedAllocationTests(tcu::TestContext& testCtx, RenderPassType renderPassType) |
| { |
| de::MovePtr<tcu::TestCaseGroup> dedicatedAllocationTestsGroup(new tcu::TestCaseGroup(testCtx, "dedicated_allocation", "RenderPass Tests For Dedicated Allocation")); |
| |
| addRenderPassTests(dedicatedAllocationTestsGroup.get(), ALLOCATION_KIND_DEDICATED, renderPassType); |
| |
| return dedicatedAllocationTestsGroup; |
| } |
| |
| tcu::TestCaseGroup* createRenderPassTestsInternal (tcu::TestContext& testCtx, RenderPassType renderPassType) |
| { |
| const char* renderpassTestsGroupName = (renderPassType == RENDERPASS_TYPE_LEGACY) ? "renderpass" : |
| (renderPassType == RENDERPASS_TYPE_RENDERPASS2) ? "renderpass2" : |
| ""; |
| const char* renderpassTestsGroupDescription = (renderPassType == RENDERPASS_TYPE_LEGACY) ? "RenderPass Tests" : |
| (renderPassType == RENDERPASS_TYPE_RENDERPASS2) ? "RenderPass2 Tests" : |
| ""; |
| de::MovePtr<tcu::TestCaseGroup> renderpassTests (new tcu::TestCaseGroup(testCtx, renderpassTestsGroupName, renderpassTestsGroupDescription)); |
| de::MovePtr<tcu::TestCaseGroup> suballocationTestGroup = createSuballocationTests(testCtx, renderPassType); |
| de::MovePtr<tcu::TestCaseGroup> dedicatedAllocationTestGroup = createDedicatedAllocationTests(testCtx, renderPassType); |
| |
| suballocationTestGroup->addChild((renderPassType == RENDERPASS_TYPE_LEGACY) ? createRenderPassMultisampleTests(testCtx) : createRenderPass2MultisampleTests(testCtx)); |
| suballocationTestGroup->addChild((renderPassType == RENDERPASS_TYPE_LEGACY) ? createRenderPassMultisampleResolveTests(testCtx) : createRenderPass2MultisampleResolveTests(testCtx)); |
| suballocationTestGroup->addChild((renderPassType == RENDERPASS_TYPE_LEGACY) ? createRenderPassSubpassDependencyTests(testCtx) : createRenderPass2SubpassDependencyTests(testCtx)); |
| suballocationTestGroup->addChild((renderPassType == RENDERPASS_TYPE_LEGACY) ? createRenderPassSampleReadTests(testCtx) : createRenderPass2SampleReadTests(testCtx)); |
| suballocationTestGroup->addChild((renderPassType == RENDERPASS_TYPE_LEGACY) ? createRenderPassSparseRenderTargetTests(testCtx) : createRenderPass2SparseRenderTargetTests(testCtx)); |
| suballocationTestGroup->addChild(createRenderPassUnusedAttachmentTests(testCtx, renderPassType)); |
| suballocationTestGroup->addChild(createRenderPassUnusedClearAttachmentTests(testCtx, renderPassType)); |
| suballocationTestGroup->addChild(createRenderPassUnusedAttachmentSparseFillingTests(testCtx, renderPassType)); |
| |
| renderpassTests->addChild(suballocationTestGroup.release()); |
| renderpassTests->addChild(dedicatedAllocationTestGroup.release()); |
| renderpassTests->addChild(createRenderPassMultipleSubpassesMultipleCommandBuffersTests(testCtx)); |
| |
| if (renderPassType != RENDERPASS_TYPE_LEGACY) |
| { |
| renderpassTests->addChild(createRenderPass2DepthStencilResolveTests(testCtx)); |
| renderpassTests->addChild(createFragmentDensityMapTests(testCtx)); |
| } |
| |
| return renderpassTests.release(); |
| } |
| |
| } // anonymous |
| |
| tcu::TestCaseGroup* createRenderPassTests (tcu::TestContext& testCtx) |
| { |
| return createRenderPassTestsInternal(testCtx, RENDERPASS_TYPE_LEGACY); |
| } |
| |
| tcu::TestCaseGroup* createRenderPass2Tests (tcu::TestContext& testCtx) |
| { |
| return createRenderPassTestsInternal(testCtx, RENDERPASS_TYPE_RENDERPASS2); |
| } |
| |
| } // vkt |