| /*------------------------------------------------------------------------- |
| * 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 "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 "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> |
| |
| 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 |
| { |
| 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)]; |
| } |
| |
| // Utility functions using flattened structs |
| Move<VkFence> createFence (const DeviceInterface& vk, VkDevice device, VkFenceCreateFlags flags) |
| { |
| const VkFenceCreateInfo pCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, |
| DE_NULL, |
| |
| flags |
| }; |
| return createFence(vk, device, &pCreateInfo); |
| } |
| |
| 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); |
| } |
| |
| Move<VkCommandPool> createCommandPool (const DeviceInterface& vk, |
| VkDevice device, |
| VkCommandPoolCreateFlags pCreateInfo_flags, |
| deUint32 pCreateInfo_queueFamilyIndex) |
| { |
| const VkCommandPoolCreateInfo pCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, |
| DE_NULL, |
| pCreateInfo_flags, |
| pCreateInfo_queueFamilyIndex, |
| }; |
| return createCommandPool(vk, device, &pCreateInfo); |
| } |
| |
| void cmdBeginRenderPass (const DeviceInterface& vk, |
| VkCommandBuffer cmdBuffer, |
| VkRenderPass pRenderPassBegin_renderPass, |
| VkFramebuffer pRenderPassBegin_framebuffer, |
| VkRect2D pRenderPassBegin_renderArea, |
| deUint32 pRenderPassBegin_clearValueCount, |
| const VkClearValue* pRenderPassBegin_pAttachmentClearValues, |
| VkSubpassContents contents) |
| { |
| const VkRenderPassBeginInfo pRenderPassBegin = |
| { |
| VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, |
| DE_NULL, |
| pRenderPassBegin_renderPass, |
| pRenderPassBegin_framebuffer, |
| pRenderPassBegin_renderArea, |
| pRenderPassBegin_clearValueCount, |
| pRenderPassBegin_pAttachmentClearValues, |
| }; |
| vk.cmdBeginRenderPass(cmdBuffer, &pRenderPassBegin, contents); |
| } |
| |
| Move<VkCommandBuffer> allocateCommandBuffer (const DeviceInterface& vk, |
| VkDevice device, |
| VkCommandPool pCreateInfo_commandPool, |
| VkCommandBufferLevel pCreateInfo_level) |
| { |
| const VkCommandBufferAllocateInfo pAllocateInfo = |
| { |
| VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, |
| DE_NULL, |
| pCreateInfo_commandPool, |
| pCreateInfo_level, |
| 1u, // bufferCount |
| }; |
| return allocateCommandBuffer(vk, device, &pAllocateInfo); |
| } |
| |
| void beginCommandBuffer (const DeviceInterface& vk, |
| VkCommandBuffer cmdBuffer, |
| VkCommandBufferUsageFlags pBeginInfo_flags, |
| VkRenderPass pInheritanceInfo_renderPass, |
| deUint32 pInheritanceInfo_subpass, |
| VkFramebuffer pInheritanceInfo_framebuffer, |
| VkBool32 pInheritanceInfo_occlusionQueryEnable, |
| VkQueryControlFlags pInheritanceInfo_queryFlags, |
| VkQueryPipelineStatisticFlags pInheritanceInfo_pipelineStatistics) |
| { |
| const VkCommandBufferInheritanceInfo pInheritanceInfo = |
| { |
| VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, |
| DE_NULL, |
| pInheritanceInfo_renderPass, |
| pInheritanceInfo_subpass, |
| pInheritanceInfo_framebuffer, |
| pInheritanceInfo_occlusionQueryEnable, |
| pInheritanceInfo_queryFlags, |
| pInheritanceInfo_pipelineStatistics, |
| }; |
| const VkCommandBufferBeginInfo pBeginInfo = |
| { |
| VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, |
| DE_NULL, |
| pBeginInfo_flags, |
| &pInheritanceInfo, |
| }; |
| VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &pBeginInfo)); |
| } |
| |
| void endCommandBuffer (const DeviceInterface& vk, VkCommandBuffer cmdBuffer) |
| { |
| VK_CHECK(vk.endCommandBuffer(cmdBuffer)); |
| } |
| |
| void queueSubmit (const DeviceInterface& vk, VkQueue queue, deUint32 cmdBufferCount, const VkCommandBuffer* pCmdBuffers, VkFence fence) |
| { |
| const VkSubmitInfo submitInfo = |
| { |
| VK_STRUCTURE_TYPE_SUBMIT_INFO, |
| DE_NULL, |
| 0u, // waitSemaphoreCount |
| (const VkSemaphore*)DE_NULL, // pWaitSemaphores |
| (const VkPipelineStageFlags*)DE_NULL, |
| cmdBufferCount, // commandBufferCount |
| pCmdBuffers, |
| 0u, // signalSemaphoreCount |
| (const VkSemaphore*)DE_NULL, // pSignalSemaphores |
| }; |
| VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence)); |
| } |
| |
| void waitForFences (const DeviceInterface& vk, VkDevice device, deUint32 fenceCount, const VkFence* pFences, VkBool32 waitAll, deUint64 timeout) |
| { |
| VK_CHECK(vk.waitForFences(device, fenceCount, pFences, waitAll, timeout)); |
| } |
| |
| VkImageAspectFlags getImageAspectFlags (VkFormat vkFormat) |
| { |
| const tcu::TextureFormat format = mapVkFormat(vkFormat); |
| |
| DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 21); |
| |
| switch (format.order) |
| { |
| case tcu::TextureFormat::DS: |
| return VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; |
| |
| case tcu::TextureFormat::D: |
| return VK_IMAGE_ASPECT_DEPTH_BIT; |
| |
| case tcu::TextureFormat::S: |
| return VK_IMAGE_ASPECT_STENCIL_BIT; |
| |
| default: |
| return VK_IMAGE_ASPECT_COLOR_BIT; |
| } |
| } |
| |
| VkAccessFlags getAllMemoryReadFlags (void) |
| { |
| return VK_ACCESS_TRANSFER_READ_BIT |
| | VK_ACCESS_UNIFORM_READ_BIT |
| | VK_ACCESS_HOST_READ_BIT |
| | VK_ACCESS_INDEX_READ_BIT |
| | VK_ACCESS_SHADER_READ_BIT |
| | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
| | VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
| | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
| | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
| | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; |
| } |
| |
| VkAccessFlags getAllMemoryWriteFlags (void) |
| { |
| return VK_ACCESS_TRANSFER_WRITE_BIT |
| | VK_ACCESS_HOST_WRITE_BIT |
| | VK_ACCESS_SHADER_WRITE_BIT |
| | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
| | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; |
| } |
| |
| VkAccessFlags getMemoryFlagsForLayout (const VkImageLayout layout) |
| { |
| switch (layout) |
| { |
| case VK_IMAGE_LAYOUT_GENERAL: return getAllMemoryReadFlags() | getAllMemoryWriteFlags(); |
| case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; |
| case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; |
| case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; |
| case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: return VK_ACCESS_SHADER_READ_BIT; |
| case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: return VK_ACCESS_TRANSFER_READ_BIT; |
| case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: return VK_ACCESS_TRANSFER_WRITE_BIT; |
| |
| default: |
| return (VkAccessFlags)0; |
| } |
| } |
| |
| VkPipelineStageFlags getAllPipelineStageFlags (void) |
| { |
| return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
| | VK_PIPELINE_STAGE_TRANSFER_BIT |
| | VK_PIPELINE_STAGE_GEOMETRY_SHADER_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_TESSELLATION_CONTROL_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; |
| } |
| |
| class AttachmentReference |
| { |
| public: |
| AttachmentReference (deUint32 attachment, |
| VkImageLayout layout) |
| : m_attachment (attachment) |
| , m_layout (layout) |
| { |
| } |
| |
| deUint32 getAttachment (void) const { return m_attachment; } |
| VkImageLayout getImageLayout (void) const { return m_layout; } |
| |
| private: |
| deUint32 m_attachment; |
| VkImageLayout m_layout; |
| }; |
| |
| 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) |
| : m_pipelineBindPoint (pipelineBindPoint) |
| , m_flags (flags) |
| , m_inputAttachments (inputAttachments) |
| , m_colorAttachments (colorAttachments) |
| , m_resolveAttachments (resolveAttachments) |
| , m_depthStencilAttachment (depthStencilAttachment) |
| , m_preserveAttachments (preserveAttachments) |
| { |
| } |
| |
| 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; } |
| |
| 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; |
| }; |
| |
| class SubpassDependency |
| { |
| public: |
| SubpassDependency (deUint32 srcPass, |
| deUint32 dstPass, |
| |
| VkPipelineStageFlags srcStageMask, |
| VkPipelineStageFlags dstStageMask, |
| |
| VkAccessFlags outputMask, |
| VkAccessFlags inputMask, |
| |
| VkDependencyFlags flags) |
| : m_srcPass (srcPass) |
| , m_dstPass (dstPass) |
| |
| , m_srcStageMask (srcStageMask) |
| , m_dstStageMask (dstStageMask) |
| |
| , m_outputMask (outputMask) |
| , m_inputMask (inputMask) |
| , 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 getOutputMask (void) const { return m_outputMask; } |
| VkAccessFlags getInputMask (void) const { return m_inputMask; } |
| |
| VkDependencyFlags getFlags (void) const { return m_flags; } |
| |
| private: |
| deUint32 m_srcPass; |
| deUint32 m_dstPass; |
| |
| VkPipelineStageFlags m_srcStageMask; |
| VkPipelineStageFlags m_dstStageMask; |
| |
| VkAccessFlags m_outputMask; |
| VkAccessFlags m_inputMask; |
| 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) |
| : m_attachments (attachments) |
| , m_subpasses (subpasses) |
| , m_dependencies (dependencies) |
| { |
| } |
| |
| 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; } |
| |
| private: |
| const vector<Attachment> m_attachments; |
| const vector<Subpass> m_subpasses; |
| const vector<SubpassDependency> m_dependencies; |
| }; |
| |
| 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_, |
| deUint32 seed_) |
| : renderPass (renderPass_) |
| , renderTypes (renderTypes_) |
| , commandBufferTypes (commandBufferTypes_) |
| , imageMemory (imageMemory_) |
| , targetSize (targetSize_) |
| , renderPos (renderPos_) |
| , renderSize (renderSize_) |
| , seed (seed_) |
| { |
| } |
| |
| RenderPass renderPass; |
| RenderTypes renderTypes; |
| CommandBufferTypes commandBufferTypes; |
| ImageMemory imageMemory; |
| UVec2 targetSize; |
| UVec2 renderPos; |
| UVec2 renderSize; |
| deUint32 seed; |
| }; |
| |
| 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 logRenderPassInfo (TestLog& log, |
| const RenderPass& renderPass) |
| { |
| 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; |
| } |
| } |
| |
| { |
| 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 (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.getInputMask() << TestLog::EndMessage; |
| log << TestLog::Message << "Output Mask: " << dep.getOutputMask() << TestLog::EndMessage; |
| log << TestLog::Message << "Dependency Flags: " << getDependencyFlagsStr(dep.getFlags()) << TestLog::EndMessage; |
| } |
| } |
| } |
| |
| std::string clearColorToString (VkFormat vkFormat, VkClearColorValue value) |
| { |
| const tcu::TextureFormat format = mapVkFormat(vkFormat); |
| const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type); |
| const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(format); |
| |
| std::ostringstream stream; |
| |
| stream << "("; |
| |
| switch (channelClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| for (int i = 0; i < 4; i++) |
| { |
| if (i > 0) |
| stream << ", "; |
| |
| if (channelMask[i]) |
| stream << value.int32[i]; |
| else |
| stream << "Undef"; |
| } |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| for (int i = 0; i < 4; 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 (int i = 0; i < 4; 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) |
| { |
| 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); |
| } |
| |
| VkClearColorValue randomColorClearValue (const Attachment& attachment, de::Random& rng) |
| { |
| 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); |
| VkClearColorValue clearColor; |
| |
| switch (channelClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| { |
| for (int ndx = 0; ndx < 4; 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 (int ndx = 0; ndx < 4; 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 (int ndx = 0; ndx < 4; 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; |
| } |
| |
| VkAttachmentDescription createAttachmentDescription (const Attachment& attachment) |
| { |
| const VkAttachmentDescription attachmentDescription = |
| { |
| 0, // flags |
| |
| attachment.getFormat(), // format |
| attachment.getSamples(), // samples |
| |
| attachment.getLoadOp(), // loadOp |
| attachment.getStoreOp(), // storeOp |
| |
| attachment.getStencilLoadOp(), // stencilLoadOp |
| attachment.getStencilStoreOp(), // stencilStoreOp |
| |
| attachment.getInitialLayout(), // initialLayout |
| attachment.getFinalLayout(), // finalLayout |
| }; |
| |
| return attachmentDescription; |
| } |
| |
| VkAttachmentReference createAttachmentReference (const AttachmentReference& referenceInfo) |
| { |
| const VkAttachmentReference reference = |
| { |
| referenceInfo.getAttachment(), // attachment; |
| referenceInfo.getImageLayout() // layout; |
| }; |
| |
| return reference; |
| } |
| |
| VkSubpassDescription createSubpassDescription (const Subpass& subpass, |
| vector<VkAttachmentReference>* attachmentReferenceLists, |
| vector<deUint32>* preserveAttachmentReferences) |
| { |
| vector<VkAttachmentReference>& inputAttachmentReferences = attachmentReferenceLists[0]; |
| vector<VkAttachmentReference>& colorAttachmentReferences = attachmentReferenceLists[1]; |
| vector<VkAttachmentReference>& resolveAttachmentReferences = attachmentReferenceLists[2]; |
| vector<VkAttachmentReference>& depthStencilAttachmentReferences = attachmentReferenceLists[3]; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++) |
| colorAttachmentReferences.push_back(createAttachmentReference(subpass.getColorAttachments()[attachmentNdx])); |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++) |
| inputAttachmentReferences.push_back(createAttachmentReference(subpass.getInputAttachments()[attachmentNdx])); |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < subpass.getResolveAttachments().size(); attachmentNdx++) |
| resolveAttachmentReferences.push_back(createAttachmentReference(subpass.getResolveAttachments()[attachmentNdx])); |
| |
| depthStencilAttachmentReferences.push_back(createAttachmentReference(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 VkSubpassDescription subpassDescription = |
| { |
| subpass.getFlags(), // flags; |
| subpass.getPipelineBindPoint(), // pipelineBindPoint; |
| |
| (deUint32)inputAttachmentReferences.size(), // inputCount; |
| inputAttachmentReferences.empty() ? DE_NULL : &inputAttachmentReferences[0], // inputAttachments; |
| |
| (deUint32)colorAttachmentReferences.size(), // colorCount; |
| colorAttachmentReferences.empty() ? DE_NULL : &colorAttachmentReferences[0], // colorAttachments; |
| resolveAttachmentReferences.empty() ? DE_NULL : &resolveAttachmentReferences[0], // resolveAttachments; |
| |
| &depthStencilAttachmentReferences[0], // pDepthStencilAttachment; |
| (deUint32)preserveAttachmentReferences->size(), // preserveCount; |
| preserveAttachmentReferences->empty() ? DE_NULL : &(*preserveAttachmentReferences)[0] // preserveAttachments; |
| }; |
| |
| return subpassDescription; |
| } |
| } |
| |
| VkSubpassDependency createSubpassDependency (const SubpassDependency& dependencyInfo) |
| { |
| const VkSubpassDependency dependency = |
| { |
| dependencyInfo.getSrcPass(), // srcSubpass; |
| dependencyInfo.getDstPass(), // destSubpass; |
| |
| dependencyInfo.getSrcStageMask(), // srcStageMask; |
| dependencyInfo.getDstStageMask(), // destStageMask; |
| |
| dependencyInfo.getOutputMask(), // outputMask; |
| dependencyInfo.getInputMask(), // inputMask; |
| |
| dependencyInfo.getFlags() // dependencyFlags; |
| }; |
| |
| return dependency; |
| } |
| |
| Move<VkRenderPass> createRenderPass (const DeviceInterface& vk, |
| VkDevice device, |
| const RenderPass& renderPassInfo) |
| { |
| const size_t perSubpassAttachmentReferenceLists = 4; |
| vector<VkAttachmentDescription> attachments; |
| vector<VkSubpassDescription> subpasses; |
| vector<VkSubpassDependency> dependencies; |
| vector<vector<VkAttachmentReference> > attachmentReferenceLists(renderPassInfo.getSubpasses().size() * perSubpassAttachmentReferenceLists); |
| vector<vector<deUint32> > preserveAttachments(renderPassInfo.getSubpasses().size()); |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++) |
| attachments.push_back(createAttachmentDescription(renderPassInfo.getAttachments()[attachmentNdx])); |
| |
| for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++) |
| subpasses.push_back(createSubpassDescription(renderPassInfo.getSubpasses()[subpassNdx], &(attachmentReferenceLists[subpassNdx * perSubpassAttachmentReferenceLists]), &preserveAttachments[subpassNdx])); |
| |
| for (size_t depNdx = 0; depNdx < renderPassInfo.getDependencies().size(); depNdx++) |
| dependencies.push_back(createSubpassDependency(renderPassInfo.getDependencies()[depNdx])); |
| |
| { |
| const VkRenderPassCreateInfo createInfo = |
| { |
| VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, |
| DE_NULL, |
| (VkRenderPassCreateFlags)0u, |
| (deUint32)attachments.size(), |
| (attachments.empty() ? DE_NULL : &attachments[0]), |
| (deUint32)subpasses.size(), |
| (subpasses.empty() ? DE_NULL : &subpasses[0]), |
| (deUint32)dependencies.size(), |
| (dependencies.empty() ? DE_NULL : &dependencies[0]) |
| }; |
| |
| return createRenderPass(vk, device, &createInfo); |
| } |
| } |
| |
| 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 DeviceInterface& vk, |
| VkDevice device, |
| Allocator& allocator, |
| VkImage image, |
| bool lazy) |
| { |
| de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), lazy ? MemoryRequirement::LazilyAllocated : MemoryRequirement::Any)); |
| 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) |
| { |
| 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 = rng.getBool() |
| ? 1.0f |
| : 0.0f; |
| |
| return clearValue; |
| } |
| else |
| { |
| VkClearValue clearValue; |
| |
| clearValue.color = randomColorClearValue(attachment, rng); |
| |
| return clearValue; |
| } |
| } |
| |
| class AttachmentResources |
| { |
| public: |
| AttachmentResources (const DeviceInterface& vk, |
| VkDevice device, |
| Allocator& allocator, |
| deUint32 queueIndex, |
| const UVec2& size, |
| const Attachment& attachmentInfo, |
| VkImageUsageFlags usageFlags) |
| : m_image (createAttachmentImage(vk, device, queueIndex, size, attachmentInfo.getFormat(), attachmentInfo.getSamples(), usageFlags, VK_IMAGE_LAYOUT_UNDEFINED)) |
| , m_imageMemory (createImageMemory(vk, device, allocator, *m_image, ((usageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) != 0))) |
| , 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 = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible); |
| |
| 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 = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_secondaryBuffer), MemoryRequirement::HostVisible); |
| |
| 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 = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible); |
| |
| 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) |
| { |
| const VkMappedMemoryRange range = |
| { |
| VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType; |
| DE_NULL, // pNext; |
| memory.getMemory(), // mem; |
| memory.getOffset(), // offset; |
| (VkDeviceSize)size // size; |
| }; |
| void* const ptr = memory.getHostPtr(); |
| |
| deMemcpy(ptr, data, size); |
| VK_CHECK(vk.flushMappedMemoryRanges(device, 1, &range)); |
| } |
| |
| VkImageAspectFlagBits getPrimaryImageAspect (tcu::TextureFormat::ChannelOrder order) |
| { |
| DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 21); |
| |
| switch (order) |
| { |
| case tcu::TextureFormat::D: |
| case tcu::TextureFormat::DS: |
| return VK_IMAGE_ASPECT_DEPTH_BIT; |
| |
| case tcu::TextureFormat::S: |
| return VK_IMAGE_ASPECT_STENCIL_BIT; |
| |
| default: |
| return VK_IMAGE_ASPECT_COLOR_BIT; |
| } |
| } |
| |
| 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, |
| |
| bool isSecondary_, |
| |
| 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_isSecondary (isSecondary_) |
| , 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()[m_colorAttachments[attachmentNdx].getAttachment()]); |
| |
| 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; } |
| bool isSecondary (void) const { return m_isSecondary; } |
| |
| 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; |
| bool m_isSecondary; |
| VkSubpassDescriptionFlags m_flags; |
| |
| Maybe<RenderQuad> m_renderQuad; |
| vector<ColorClear> m_colorClears; |
| Maybe<DepthStencilClear> m_depthStencilClear; |
| |
| vector<AttachmentReference> m_colorAttachments; |
| vector<Attachment> m_colorAttachmentInfo; |
| |
| Maybe<AttachmentReference> m_depthStencilAttachment; |
| Maybe<Attachment> m_depthStencilAttachmentInfo; |
| |
| vector<AttachmentReference> m_inputAttachments; |
| }; |
| |
| Move<VkPipeline> createSubpassPipeline (const DeviceInterface& vk, |
| VkDevice device, |
| VkRenderPass renderPass, |
| VkShaderModule vertexShaderModule, |
| VkShaderModule fragmentShaderModule, |
| VkPipelineLayout pipelineLayout, |
| const SubpassRenderInfo& renderInfo) |
| { |
| const VkSpecializationInfo emptyShaderSpecializations = |
| { |
| 0u, // mapEntryCount |
| DE_NULL, // pMap |
| 0u, // dataSize |
| DE_NULL, // pData |
| }; |
| |
| 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 |
| 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 VkPipelineShaderStageCreateInfo shaderStages[2] = |
| { |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (VkPipelineShaderStageCreateFlags)0u, |
| VK_SHADER_STAGE_VERTEX_BIT, // stage |
| vertexShaderModule, // shader |
| "main", |
| &emptyShaderSpecializations |
| }, |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (VkPipelineShaderStageCreateFlags)0u, |
| VK_SHADER_STAGE_FRAGMENT_BIT, // stage |
| fragmentShaderModule, // shader |
| "main", |
| &emptyShaderSpecializations |
| } |
| }; |
| 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, // sType |
| DE_NULL, // pNext |
| (VkPipelineInputAssemblyStateCreateFlags)0u, |
| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // topology |
| VK_FALSE, // 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, |
| DE_NULL, |
| (VkPipelineViewportStateCreateFlags)0u, |
| 1u, |
| &viewport, |
| 1u, |
| &scissor |
| }; |
| const VkPipelineRasterizationStateCreateInfo rasterState = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (VkPipelineRasterizationStateCreateFlags)0u, |
| VK_TRUE, // depthClipEnable |
| VK_FALSE, // rasterizerDiscardEnable |
| VK_POLYGON_MODE_FILL, // fillMode |
| VK_CULL_MODE_NONE, // cullMode |
| VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace |
| VK_FALSE, // depthBiasEnable |
| 0.0f, // depthBias |
| 0.0f, // depthBiasClamp |
| 0.0f, // slopeScaledDepthBias |
| 1.0f // 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 VkPipelineDepthStencilStateCreateInfo depthStencilState = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (VkPipelineDepthStencilStateCreateFlags)0u, |
| VK_TRUE, // depthTestEnable |
| VK_TRUE, // depthWriteEnable |
| VK_COMPARE_OP_ALWAYS, // depthCompareOp |
| VK_FALSE, // depthBoundsEnable |
| VK_TRUE, // 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 |
| }; |
| const VkGraphicsPipelineCreateInfo createInfo = |
| { |
| VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (VkPipelineCreateFlags)0u, |
| |
| 2, // stageCount |
| shaderStages, // pStages |
| |
| &vertexInputState, // pVertexInputState |
| &inputAssemblyState, // pInputAssemblyState |
| DE_NULL, // pTessellationState |
| &viewportState, // pViewportState |
| &rasterState, // pRasterState |
| &multisampleState, // pMultisampleState |
| &depthStencilState, // pDepthStencilState |
| &blendState, // pColorBlendState |
| (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // pDynamicState |
| pipelineLayout, // layout |
| |
| renderPass, // renderPass |
| renderInfo.getSubpassIndex(), // subpass |
| DE_NULL, // basePipelineHandle |
| 0u // basePipelineIndex |
| }; |
| |
| return createGraphicsPipeline(vk, device, DE_NULL, &createInfo); |
| } |
| |
| 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) |
| : m_renderInfo (renderInfo) |
| { |
| const deUint32 subpassIndex = renderInfo.getSubpassIndex(); |
| vector<VkDescriptorSetLayoutBinding> bindings; |
| |
| for (deUint32 colorAttachmentNdx = 0; colorAttachmentNdx < renderInfo.getColorAttachmentCount(); colorAttachmentNdx++) |
| m_colorAttachmentImages.push_back(attachmentImages[renderInfo.getColorAttachmentIndex(colorAttachmentNdx)]); |
| |
| 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 tcu::TextureFormat format = mapVkFormat(attachmentInfo.getFormat()); |
| const bool isDepthFormat = tcu::hasDepthComponent(format.order); |
| const bool isStencilFormat = tcu::hasStencilComponent(format.order); |
| const deUint32 bindingCount = isDepthFormat && isStencilFormat ? 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); |
| |
| m_vertexBuffer = createBuffer(vk, device, 0u, (VkDeviceSize)renderQuad.getVertexDataSize(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE, 1u, &queueFamilyIndex); |
| m_vertexBufferMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_vertexBuffer), MemoryRequirement::HostVisible); |
| |
| bindBufferMemory(vk, device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset()); |
| uploadBufferData(vk, device, *m_vertexBufferMemory, renderQuad.getVertexDataSize(), renderQuad.getVertexPointer()); |
| |
| 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) |
| { |
| { |
| 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++; |
| } |
| } |
| { |
| const VkDescriptorImageInfo imageInfo = |
| { |
| (VkSampler)0, |
| attachmentViews[renderInfo.getInputAttachmentIndex(inputAttachmentNdx)].second, |
| inputAttachmentLayout |
| }; |
| imageInfos[bindingIndex] = imageInfo; |
| |
| { |
| const VkWriteDescriptorSet write = |
| { |
| VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, |
| DE_NULL, |
| |
| *m_descriptorSet, |
| bindingIndex, |
| 0u, |
| 1u, |
| VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, |
| &imageInfos[bindingIndex], |
| DE_NULL, |
| DE_NULL |
| }; |
| writes[bindingIndex] = write; |
| |
| bindingIndex++; |
| } |
| } |
| } |
| else |
| { |
| const VkDescriptorImageInfo imageInfo = |
| { |
| (VkSampler)0, |
| attachmentViews[renderInfo.getInputAttachmentIndex(inputAttachmentNdx)].first, |
| inputAttachmentLayout |
| }; |
| imageInfos[bindingIndex] = imageInfo; |
| |
| { |
| const VkWriteDescriptorSet write = |
| { |
| VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, |
| DE_NULL, |
| |
| *m_descriptorSet, |
| bindingIndex, |
| 0u, |
| 1u, |
| VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, |
| &imageInfos[bindingIndex], |
| DE_NULL, |
| DE_NULL |
| }; |
| writes[bindingIndex] = write; |
| |
| bindingIndex++; |
| } |
| } |
| } |
| |
| vk.updateDescriptorSets(device, (deUint32)writes.size(), &writes[0], 0u, DE_NULL); |
| } |
| } |
| } |
| |
| if (renderInfo.isSecondary()) |
| { |
| m_commandBuffer = allocateCommandBuffer(vk, device, commandBufferPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); |
| |
| beginCommandBuffer(vk, *m_commandBuffer, vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, renderPass, subpassIndex, framebuffer, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0); |
| pushRenderCommands(vk, *m_commandBuffer); |
| endCommandBuffer(vk, *m_commandBuffer); |
| } |
| } |
| |
| bool isSecondary (void) const |
| { |
| return m_commandBuffer; |
| } |
| |
| VkCommandBuffer getCommandBuffer (void) const |
| { |
| DE_ASSERT(isSecondary()); |
| return *m_commandBuffer; |
| } |
| |
| void pushRenderCommands (const DeviceInterface& vk, |
| VkCommandBuffer commandBuffer) |
| { |
| if (!m_renderInfo.getColorClears().empty()) |
| { |
| const vector<ColorClear>& colorClears (m_renderInfo.getColorClears()); |
| |
| for (deUint32 attachmentNdx = 0; attachmentNdx < m_renderInfo.getColorAttachmentCount(); attachmentNdx++) |
| { |
| const ColorClear& colorClear = colorClears[attachmentNdx]; |
| const VkClearAttachment attachment = |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, |
| attachmentNdx, |
| makeClearValue(colorClear.getColor()), |
| }; |
| const VkClearRect rect = |
| { |
| { |
| { (deInt32)colorClear.getOffset().x(), (deInt32)colorClear.getOffset().y() }, |
| { colorClear.getSize().x(), colorClear.getSize().y() } |
| }, // rect |
| 0u, // baseArrayLayer |
| 1u, // layerCount |
| }; |
| |
| vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect); |
| } |
| } |
| |
| if (m_renderInfo.getDepthStencilClear()) |
| { |
| const DepthStencilClear& depthStencilClear = *m_renderInfo.getDepthStencilClear(); |
| const deUint32 attachmentNdx = m_renderInfo.getColorAttachmentCount(); |
| tcu::TextureFormat format = mapVkFormat(m_renderInfo.getDepthStencilAttachment()->getFormat()); |
| const VkClearAttachment attachment = |
| { |
| (VkImageAspectFlags)((hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) |
| | (hasStencilComponent(format.order) ? 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 |
| }; |
| |
| 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 |
| |
| VK_IMAGE_LAYOUT_GENERAL, // oldLayout |
| VK_IMAGE_LAYOUT_GENERAL, // 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()) |
| 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_TOP_OF_PIPE_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; |
| |
| (oldLayout != VK_IMAGE_LAYOUT_UNDEFINED ? getAllMemoryWriteFlags() : (VkAccessFlags)0), // 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_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, |
| 0, (const VkMemoryBarrier*)DE_NULL, |
| 0, (const VkBufferMemoryBarrier*)DE_NULL, |
| (deUint32)renderPassLayouts.size(), &renderPassLayouts[0]); |
| } |
| } |
| |
| 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; |
| |
| 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; |
| |
| if (subpassNdx == 0) |
| cmdBeginRenderPass(vk, commandBuffer, renderPass, framebuffer, renderArea, (deUint32)attachmentClearValues.size(), attachmentClearValues.empty() ? DE_NULL : &attachmentClearValues[0], contents); |
| else |
| vk.cmdNextSubpass(commandBuffer, contents); |
| |
| 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"); |
| } |
| } |
| |
| vk.cmdEndRenderPass(commandBuffer); |
| } |
| } |
| |
| void pushReadImagesToBuffers (const DeviceInterface& vk, |
| VkCommandBuffer commandBuffer, |
| deUint32 queueIndex, |
| |
| const vector<de::SharedPtr<AttachmentResources> >& attachmentResources, |
| const vector<Attachment>& attachmentInfo, |
| const vector<bool>& isLazy, |
| |
| const UVec2& targetSize) |
| { |
| { |
| vector<VkImageMemoryBarrier> imageBarriers; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++) |
| { |
| if (isLazy[attachmentNdx]) |
| continue; |
| |
| const VkImageLayout oldLayout = attachmentInfo[attachmentNdx].getFinalLayout(); |
| const VkImageMemoryBarrier barrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType |
| DE_NULL, // pNext |
| |
| getAllMemoryWriteFlags() | getMemoryFlagsForLayout(oldLayout), // srcAccessMask |
| getAllMemoryReadFlags(), // dstAccessMask |
| |
| oldLayout, // oldLayout |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout |
| |
| queueIndex, // srcQueueFamilyIndex |
| queueIndex, // destQueueFamilyIndex |
| |
| attachmentResources[attachmentNdx]->getImage(), // image |
| { // subresourceRange |
| getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect; |
| 0, // baseMipLevel |
| 1, // mipLevels |
| 0, // baseArraySlice |
| 1 // arraySize |
| } |
| }; |
| |
| imageBarriers.push_back(barrier); |
| } |
| |
| if (!imageBarriers.empty()) |
| vk.cmdPipelineBarrier(commandBuffer, |
| getAllPipelineStageFlags(), |
| getAllPipelineStageFlags(), |
| (VkDependencyFlags)0, |
| 0, (const VkMemoryBarrier*)DE_NULL, |
| 0, (const VkBufferMemoryBarrier*)DE_NULL, |
| (deUint32)imageBarriers.size(), &imageBarriers[0]); |
| } |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++) |
| { |
| if (isLazy[attachmentNdx]) |
| continue; |
| |
| const tcu::TextureFormat::ChannelOrder order = mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order; |
| const VkBufferImageCopy rect = |
| { |
| 0, // bufferOffset |
| 0, // bufferRowLength |
| 0, // bufferImageHeight |
| { // imageSubresource |
| (vk::VkImageAspectFlags)getPrimaryImageAspect(mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order), // aspect |
| 0, // mipLevel |
| 0, // arraySlice |
| 1 // arraySize |
| }, |
| { 0, 0, 0 }, // imageOffset |
| { targetSize.x(), targetSize.y(), 1u } // imageExtent |
| }; |
| |
| vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getBuffer(), 1, &rect); |
| |
| if (tcu::TextureFormat::DS == order) |
| { |
| const VkBufferImageCopy stencilRect = |
| { |
| 0, // bufferOffset |
| 0, // bufferRowLength |
| 0, // bufferImageHeight |
| { // imageSubresource |
| VK_IMAGE_ASPECT_STENCIL_BIT, // aspect |
| 0, // mipLevel |
| 0, // arraySlice |
| 1 // arraySize |
| }, |
| { 0, 0, 0 }, // imageOffset |
| { targetSize.x(), targetSize.y(), 1u } // imageExtent |
| }; |
| |
| vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getSecondaryBuffer(), 1, &stencilRect); |
| } |
| } |
| |
| { |
| vector<VkBufferMemoryBarrier> bufferBarriers; |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++) |
| { |
| if (isLazy[attachmentNdx]) |
| continue; |
| |
| const tcu::TextureFormat::ChannelOrder order = mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order; |
| const VkBufferMemoryBarrier bufferBarrier = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, |
| DE_NULL, |
| |
| getAllMemoryWriteFlags(), |
| getAllMemoryReadFlags(), |
| |
| queueIndex, |
| queueIndex, |
| |
| attachmentResources[attachmentNdx]->getBuffer(), |
| 0, |
| attachmentResources[attachmentNdx]->getBufferSize() |
| }; |
| |
| bufferBarriers.push_back(bufferBarrier); |
| |
| if (tcu::TextureFormat::DS == order) |
| { |
| const VkBufferMemoryBarrier secondaryBufferBarrier = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, |
| DE_NULL, |
| |
| getAllMemoryWriteFlags(), |
| getAllMemoryReadFlags(), |
| |
| queueIndex, |
| queueIndex, |
| |
| attachmentResources[attachmentNdx]->getSecondaryBuffer(), |
| 0, |
| attachmentResources[attachmentNdx]->getSecondaryBufferSize() |
| }; |
| |
| bufferBarriers.push_back(secondaryBufferBarrier); |
| } |
| } |
| |
| if (!bufferBarriers.empty()) |
| vk.cmdPipelineBarrier(commandBuffer, |
| getAllPipelineStageFlags(), |
| getAllPipelineStageFlags(), |
| (VkDependencyFlags)0, |
| 0, (const VkMemoryBarrier*)DE_NULL, |
| (deUint32)bufferBarriers.size(), &bufferBarriers[0], |
| 0, (const VkImageMemoryBarrier*)DE_NULL); |
| } |
| } |
| |
| class PixelValue |
| { |
| public: |
| PixelValue (const Maybe<bool>& x = nothing<bool>(), |
| const Maybe<bool>& y = nothing<bool>(), |
| const Maybe<bool>& z = nothing<bool>(), |
| const Maybe<bool>& w = nothing<bool>()); |
| |
| void setUndefined (size_t ndx); |
| void setValue (size_t ndx, bool value); |
| Maybe<bool> getValue (size_t ndx) const; |
| |
| private: |
| deUint16 m_status; |
| }; |
| |
| PixelValue::PixelValue (const Maybe<bool>& x, |
| const Maybe<bool>& y, |
| const Maybe<bool>& z, |
| const Maybe<bool>& w) |
| : m_status (0) |
| { |
| const Maybe<bool> values[] = |
| { |
| x, y, z, w |
| }; |
| |
| for (size_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(values); ndx++) |
| { |
| if (values[ndx]) |
| setValue(ndx, *values[ndx]); |
| else |
| setUndefined(ndx); |
| } |
| |
| DE_ASSERT(m_status <= 0xFFu); |
| } |
| |
| void PixelValue::setUndefined (size_t ndx) |
| { |
| DE_ASSERT(ndx < 4); |
| DE_ASSERT(m_status <= 0xFFu); |
| |
| m_status &= (deUint16)~(0x1u << (deUint16)(ndx * 2)); |
| DE_ASSERT(m_status <= 0xFFu); |
| } |
| |
| void PixelValue::setValue (size_t ndx, bool value) |
| { |
| DE_ASSERT(ndx < 4); |
| DE_ASSERT(m_status <= 0xFFu); |
| |
| m_status |= (deUint16)(0x1u << (ndx * 2)); |
| |
| if (value) |
| m_status |= (deUint16)(0x1u << (ndx * 2 + 1)); |
| else |
| m_status &= (deUint16)~(0x1u << (deUint16)(ndx * 2 + 1)); |
| |
| DE_ASSERT(m_status <= 0xFFu); |
| } |
| |
| Maybe<bool> PixelValue::getValue (size_t ndx) const |
| { |
| DE_ASSERT(ndx < 4); |
| DE_ASSERT(m_status <= 0xFFu); |
| |
| if ((m_status & (0x1u << (deUint16)(ndx * 2))) != 0) |
| { |
| return just((m_status & (0x1u << (deUint32)(ndx * 2 + 1))) != 0); |
| } |
| else |
| return nothing<bool>(); |
| } |
| |
| void clearReferenceValues (vector<PixelValue>& values, |
| const UVec2& targetSize, |
| const UVec2& offset, |
| const UVec2& size, |
| const BVec4& mask, |
| const PixelValue& value) |
| { |
| DE_ASSERT(targetSize.x() * targetSize.y() == (deUint32)values.size()); |
| DE_ASSERT(offset.x() + size.x() <= targetSize.x()); |
| DE_ASSERT(offset.y() + size.y() <= targetSize.y()); |
| |
| for (deUint32 y = offset.y(); y < offset.y() + size.y(); y++) |
| for (deUint32 x = offset.x(); x < offset.x() + size.x(); x++) |
| { |
| for (int compNdx = 0; compNdx < 4; compNdx++) |
| { |
| if (mask[compNdx]) |
| { |
| if (value.getValue(compNdx)) |
| values[x + y * targetSize.x()].setValue(compNdx, *value.getValue(compNdx)); |
| else |
| values[x + y * targetSize.x()].setUndefined(compNdx); |
| } |
| } |
| } |
| } |
| |
| void markUndefined (vector<PixelValue>& values, |
| const BVec4& mask, |
| const UVec2& targetSize, |
| const UVec2& offset, |
| const UVec2& size) |
| { |
| DE_ASSERT(targetSize.x() * targetSize.y() == (deUint32)values.size()); |
| |
| for (deUint32 y = offset.y(); y < offset.y() + size.y(); y++) |
| for (deUint32 x = offset.x(); x < offset.x() + size.x(); x++) |
| { |
| for (int compNdx = 0; compNdx < 4; compNdx++) |
| { |
| if (mask[compNdx]) |
| values[x + y * targetSize.x()].setUndefined(compNdx); |
| } |
| } |
| } |
| |
| PixelValue clearValueToPixelValue (const VkClearValue& value, |
| const tcu::TextureFormat& format) |
| { |
| const bool isDepthAttachment = hasDepthComponent(format.order); |
| const bool isStencilAttachment = hasStencilComponent(format.order); |
| const bool isDepthOrStencilAttachment = isDepthAttachment || isStencilAttachment; |
| PixelValue pixelValue; |
| |
| if (isDepthOrStencilAttachment) |
| { |
| if (isDepthAttachment) |
| { |
| if (value.depthStencil.depth == 1.0f) |
| pixelValue.setValue(0, true); |
| else if (value.depthStencil.depth == 0.0f) |
| pixelValue.setValue(0, false); |
| else |
| DE_FATAL("Unknown depth value"); |
| } |
| |
| if (isStencilAttachment) |
| { |
| if (value.depthStencil.stencil == 0xFFu) |
| pixelValue.setValue(1, true); |
| else if (value.depthStencil.stencil == 0x0u) |
| pixelValue.setValue(1, false); |
| else |
| DE_FATAL("Unknown stencil value"); |
| } |
| } |
| else |
| { |
| const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type); |
| const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(format); |
| |
| switch (channelClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| for (int i = 0; i < 4; i++) |
| { |
| if (channelMask[i]) |
| { |
| if (value.color.int32[i] == 1) |
| pixelValue.setValue(i, true); |
| else if (value.color.int32[i] == 0) |
| pixelValue.setValue(i, false); |
| else |
| DE_FATAL("Unknown clear color value"); |
| } |
| } |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| for (int i = 0; i < 4; i++) |
| { |
| if (channelMask[i]) |
| { |
| if (value.color.uint32[i] == 1u) |
| pixelValue.setValue(i, true); |
| else if (value.color.uint32[i] == 0u) |
| pixelValue.setValue(i, false); |
| else |
| DE_FATAL("Unknown clear color value"); |
| } |
| } |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| for (int i = 0; i < 4; i++) |
| { |
| if (channelMask[i]) |
| { |
| if (value.color.float32[i] == 1.0f) |
| pixelValue.setValue(i, true); |
| else if (value.color.float32[i] == 0.0f) |
| pixelValue.setValue(i, false); |
| else |
| DE_FATAL("Unknown clear color value"); |
| } |
| } |
| break; |
| |
| default: |
| DE_FATAL("Unknown channel class"); |
| } |
| } |
| |
| return pixelValue; |
| } |
| |
| void renderReferenceValues (vector<vector<PixelValue> >& referenceAttachments, |
| const RenderPass& renderPassInfo, |
| const UVec2& targetSize, |
| const vector<Maybe<VkClearValue> >& imageClearValues, |
| const vector<Maybe<VkClearValue> >& renderPassClearValues, |
| const vector<SubpassRenderInfo>& subpassRenderInfo, |
| const UVec2& renderPos, |
| const UVec2& renderSize) |
| { |
| const vector<Subpass>& subpasses = renderPassInfo.getSubpasses(); |
| vector<bool> attachmentUsed (renderPassInfo.getAttachments().size(), false); |
| |
| referenceAttachments.resize(renderPassInfo.getAttachments().size()); |
| |
| for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++) |
| { |
| const Attachment attachment = renderPassInfo.getAttachments()[attachmentNdx]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| vector<PixelValue>& reference = referenceAttachments[attachmentNdx]; |
| |
| reference.resize(targetSize.x() * targetSize.y()); |
| |
| if (imageClearValues[attachmentNdx]) |
| clearReferenceValues(reference, targetSize, UVec2(0, 0), targetSize, BVec4(true), clearValueToPixelValue(*imageClearValues[attachmentNdx], format)); |
| } |
| |
| for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++) |
| { |
| const Subpass& subpass = subpasses[subpassNdx]; |
| const SubpassRenderInfo& renderInfo = subpassRenderInfo[subpassNdx]; |
| const vector<AttachmentReference>& colorAttachments = subpass.getColorAttachments(); |
| |
| // Apply load op if attachment was used for the first time |
| for (size_t attachmentNdx = 0; attachmentNdx < colorAttachments.size(); attachmentNdx++) |
| { |
| const deUint32 attachmentIndex = colorAttachments[attachmentNdx].getAttachment(); |
| |
| if (!attachmentUsed[attachmentIndex]) |
| { |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| vector<PixelValue>& reference = referenceAttachments[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| |
| DE_ASSERT(!tcu::hasDepthComponent(format.order)); |
| DE_ASSERT(!tcu::hasStencilComponent(format.order)); |
| |
| if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR) |
| clearReferenceValues(reference, targetSize, renderPos, renderSize, BVec4(true), clearValueToPixelValue(*renderPassClearValues[attachmentIndex], format)); |
| else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE) |
| markUndefined(reference, BVec4(true), targetSize, renderPos, renderSize); |
| |
| attachmentUsed[attachmentIndex] = true; |
| } |
| } |
| |
| // Apply load op to depth/stencil attachment if it was used for the first time |
| if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED) |
| { |
| const deUint32 attachmentIndex = subpass.getDepthStencilAttachment().getAttachment(); |
| |
| // Apply load op if attachment was used for the first time |
| if (!attachmentUsed[attachmentIndex]) |
| { |
| const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex]; |
| vector<PixelValue>& reference = referenceAttachments[attachmentIndex]; |
| const tcu::TextureFormat format = mapVkFormat(attachment.getFormat()); |
| |
| if (tcu::hasDepthComponent(format.order)) |
| { |
| if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR) |
| clearReferenceValues(reference, targetSize, renderPos, renderSize, BVec4(true, false, false, false), clearValueToPixelValue(*renderPassClearValues[attachmentIndex], format)); |
| else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE) |
| markUndefined(reference, BVec4(true, false, false, false), targetSize, renderPos, renderSize); |
| } |
| |
| if (tcu::hasStencilComponent(format.order)) |
| |