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