#include "deUniquePtr.hpp"
#include "deSharedPtr.hpp"
#include "deMath.h"
+
#include <limits>
+#include <map>
using namespace vk;
deUint8 stencilExpectedValue;
bool separateDepthStencilLayouts;
bool unusedResolve;
+ tcu::Maybe<VkFormat> compatibleFormat;
+ bool sampleMask;
+};
+
+// Auxiliar class to group depth formats by compatibility in bit size and format. Note there is at most one alternative format for
+// each given format as of the time this comment is being written, and the alternative (compatible) format for a given format can
+// only remove aspects but not add them. That is, we cannot use a depth/stencil attachment to resolve a depth-only attachment.
+//
+// See:
+// * VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03181
+// * VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03182
+class DepthCompatibilityManager
+{
+public:
+ DepthCompatibilityManager ()
+ : m_compatibleFormats()
+ {
+ m_compatibleFormats[VK_FORMAT_D32_SFLOAT_S8_UINT] = VK_FORMAT_D32_SFLOAT;
+ m_compatibleFormats[VK_FORMAT_D16_UNORM_S8_UINT] = VK_FORMAT_D16_UNORM;
+ m_compatibleFormats[VK_FORMAT_D24_UNORM_S8_UINT] = VK_FORMAT_X8_D24_UNORM_PACK32;
+ }
+
+ VkFormat getAlternativeFormat (VkFormat format) const
+ {
+ const auto itr = m_compatibleFormats.find(format);
+ if (itr != end(m_compatibleFormats))
+ return itr->second;
+ return VK_FORMAT_UNDEFINED;
+ }
+
+private:
+ std::map<VkFormat, VkFormat> m_compatibleFormats;
};
float get16bitDepthComponent(deUint8* pixelPtr)
protected:
bool isFeaturesSupported (void);
+ bool isSupportedFormat (Context& context, VkFormat format) const;
VkSampleCountFlagBits sampleCountBitFromSampleCount (deUint32 count) const;
VkImageSp createImage (deUint32 sampleCount, VkImageUsageFlags additionalUsage = 0u);
AllocationSp createBufferMemory (void);
VkBufferSp createBuffer (void);
- Move<VkRenderPass> createRenderPass (void);
+ Move<VkRenderPass> createRenderPass (VkFormat vkformat, deUint32 renderPassNo);
+ Move<VkRenderPass> createRenderPassCompatible (void);
Move<VkFramebuffer> createFramebuffer (VkRenderPass renderPass, VkImageViewSp multisampleImageView, VkImageViewSp singlesampleImageView);
Move<VkPipelineLayout> createRenderPipelineLayout (void);
- Move<VkPipeline> createRenderPipeline (VkRenderPass renderPass, VkPipelineLayout renderPipelineLayout);
+ Move<VkPipeline> createRenderPipeline (VkRenderPass renderPass, deUint32 renderPassNo, VkPipelineLayout renderPipelineLayout);
void submit (void);
bool verifyDepth (void);
VkBufferSp m_buffer;
AllocationSp m_bufferMemory;
- Unique<VkRenderPass> m_renderPass;
- Unique<VkFramebuffer> m_framebuffer;
+ deUint32 m_numRenderPasses;
+ std::vector<Move<VkRenderPass>> m_renderPass;
+ Unique<VkRenderPass> m_renderPassCompatible;
+ Move<VkFramebuffer> m_framebuffer;
Unique<VkPipelineLayout> m_renderPipelineLayout;
- Unique<VkPipeline> m_renderPipeline;
+ std::vector<Move<VkPipeline>> m_renderPipeline;
};
DepthStencilResolveTest::DepthStencilResolveTest (Context& context, TestConfig config)
, m_buffer (createBuffer())
, m_bufferMemory (createBufferMemory())
- , m_renderPass (createRenderPass())
- , m_framebuffer (createFramebuffer(*m_renderPass, m_multisampleImageView, m_singlesampleImageView))
+ , m_numRenderPasses ((m_config.verifyBuffer == VB_DEPTH || !m_config.sampleMask) ? 1u : m_config.sampleCount)
+ , m_renderPassCompatible (createRenderPassCompatible())
, m_renderPipelineLayout (createRenderPipelineLayout())
- , m_renderPipeline (createRenderPipeline(*m_renderPass, *m_renderPipelineLayout))
{
+ for (deUint32 i = 0; i < m_numRenderPasses; i++)
+ {
+ m_renderPass.push_back(createRenderPass(m_config.format, i));
+ m_renderPipeline.push_back(createRenderPipeline(*m_renderPass[i], i, *m_renderPipelineLayout));
+ }
+ m_framebuffer = createFramebuffer(*m_renderPass[0], m_multisampleImageView, m_singlesampleImageView);
}
DepthStencilResolveTest::~DepthStencilResolveTest (void)
// check if both modes are supported
VkResolveModeFlagBits depthResolveMode = m_config.depthResolveMode;
- VkResolveModeFlagBits stencilResolveMode = m_config.stencilResolveMode;
+ VkResolveModeFlagBits stencilResolveMode = m_config.stencilResolveMode;
+
if ((depthResolveMode != VK_RESOLVE_MODE_NONE) &&
!(depthResolveMode & dsResolveProperties.supportedDepthResolveModes))
TCU_THROW(NotSupportedError, "Depth resolve mode not supported");
+
if ((stencilResolveMode != VK_RESOLVE_MODE_NONE) &&
!(stencilResolveMode & dsResolveProperties.supportedStencilResolveModes))
TCU_THROW(NotSupportedError, "Stencil resolve mode not supported");
TCU_THROW(NotSupportedError, "Implementation doesn't support diferent resolve modes");
}
+ // Check alternative format support if needed.
+ if (m_config.compatibleFormat)
+ {
+ if (! isSupportedFormat(m_context, m_config.compatibleFormat.get()))
+ TCU_THROW(NotSupportedError, "Alternative image format for compatibility test not supported");
+ }
+
return true;
}
return safeSharedPtr(new Unique<VkImageView>(vk::createImageView(m_vkd, m_device, &pCreateInfo)));
}
-Move<VkRenderPass> DepthStencilResolveTest::createRenderPass (void)
+Move<VkRenderPass> DepthStencilResolveTest::createRenderPass(VkFormat vkformat, deUint32 renderPassNo)
{
- // When the depth/stencil resolve attachment is unused, it needs to be cleared outside the render pass so it has the expected values.
- if (m_config.unusedResolve)
- {
- const tcu::TextureFormat format (mapVkFormat(m_config.format));
- const Unique<VkCommandBuffer> commandBuffer (allocateCommandBuffer(m_vkd, m_device, *m_commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
- const vk::VkImageSubresourceRange imageRange =
- {
- ((tcu::hasDepthComponent(format.order) ? static_cast<vk::VkImageAspectFlags>(vk::VK_IMAGE_ASPECT_DEPTH_BIT) : 0u) |
- (tcu::hasStencilComponent(format.order) ? static_cast<vk::VkImageAspectFlags>(vk::VK_IMAGE_ASPECT_STENCIL_BIT) : 0u)),
- 0u,
- VK_REMAINING_MIP_LEVELS,
- 0u,
- VK_REMAINING_ARRAY_LAYERS,
- };
- const vk::VkImageMemoryBarrier preBarrier =
- {
- vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
- nullptr,
-
- // src and dst access masks.
- 0,
- vk::VK_ACCESS_TRANSFER_WRITE_BIT,
-
- // old and new layouts.
- vk::VK_IMAGE_LAYOUT_UNDEFINED,
- vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-
- VK_QUEUE_FAMILY_IGNORED,
- VK_QUEUE_FAMILY_IGNORED,
-
- **m_singlesampleImage,
- imageRange,
- };
- const vk::VkImageMemoryBarrier postBarrier =
- {
- vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
- nullptr,
-
- // src and dst access masks.
- vk::VK_ACCESS_TRANSFER_WRITE_BIT,
- 0,
-
- // old and new layouts.
- vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
-
- VK_QUEUE_FAMILY_IGNORED,
- VK_QUEUE_FAMILY_IGNORED,
-
- **m_singlesampleImage,
- imageRange,
- };
-
- vk::beginCommandBuffer(m_vkd, commandBuffer.get());
- m_vkd.cmdPipelineBarrier(commandBuffer.get(), vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preBarrier);
- m_vkd.cmdClearDepthStencilImage(commandBuffer.get(), **m_singlesampleImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_config.clearValue, 1u, &imageRange);
- m_vkd.cmdPipelineBarrier(commandBuffer.get(), vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &postBarrier);
- vk::endCommandBuffer(m_vkd, commandBuffer.get());
-
- vk::submitCommandsAndWait(m_vkd, m_device, m_context.getUniversalQueue(), commandBuffer.get());
- }
-
const VkSampleCountFlagBits samples(sampleCountBitFromSampleCount(m_config.sampleCount));
VkImageLayout layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
};
void * attachmentRefStencil = DE_NULL;
VkImageLayout finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
- VkAttachmentDescriptionStencilLayoutKHR stencilFinalLayout =
+ VkAttachmentDescriptionStencilLayoutKHR multisampleStencilFinalLayout =
+ {
+ VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR,
+ DE_NULL,
+ VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ };
+ VkAttachmentDescriptionStencilLayoutKHR singlesampleStencilFinalLayout =
{
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR,
DE_NULL,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
};
- void * attachmentDescriptionStencil = DE_NULL;
+ void * multisampleAttachmentDescriptionStencil = DE_NULL;
+ void * singlesampleAttachmentDescriptionStencil = DE_NULL;
if (m_config.separateDepthStencilLayouts)
{
layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR;
stencilLayout.stencilLayout = VK_IMAGE_LAYOUT_GENERAL;
finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
- stencilFinalLayout.stencilFinalLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR; // This aspect should be unused.
+ multisampleStencilFinalLayout.stencilFinalLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR; // This aspect should be unused.
+ singlesampleStencilFinalLayout.stencilFinalLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR; // This aspect should be unused.
}
else
{
- layout = VK_IMAGE_LAYOUT_GENERAL;
+ layout = m_config.sampleMask ? VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR : VK_IMAGE_LAYOUT_GENERAL;
stencilLayout.stencilLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
- finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR; // This aspect should be unused.
- stencilFinalLayout.stencilFinalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ finalLayout = VK_IMAGE_LAYOUT_GENERAL; // This aspect should be unused.
+ multisampleStencilFinalLayout.stencilFinalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ singlesampleStencilFinalLayout.stencilFinalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
}
attachmentRefStencil = &stencilLayout;
- attachmentDescriptionStencil = &stencilFinalLayout;
+ multisampleAttachmentDescriptionStencil = &multisampleStencilFinalLayout;
+ singlesampleAttachmentDescriptionStencil = &singlesampleStencilFinalLayout;
+ }
+
+ if (renderPassNo != 0)
+ {
+ multisampleStencilFinalLayout.stencilInitialLayout = stencilLayout.stencilLayout;
+ singlesampleStencilFinalLayout.stencilInitialLayout = stencilLayout.stencilLayout;
+ }
+
+ if (renderPassNo != m_numRenderPasses - 1)
+ {
+ finalLayout = layout;
+ multisampleStencilFinalLayout.stencilFinalLayout = layout;
+ singlesampleStencilFinalLayout.stencilFinalLayout = layout;
}
const AttachmentDescription2 multisampleAttachment // VkAttachmentDescription2
(
// VkStructureType sType;
- attachmentDescriptionStencil, // const void* pNext;
+ multisampleAttachmentDescriptionStencil, // const void* pNext;
0u, // VkAttachmentDescriptionFlags flags;
m_config.format, // VkFormat format;
samples, // VkSampleCountFlagBits samples;
- VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
- VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp;
- VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
- VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
- VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ (renderPassNo == 0) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
+ VK_ATTACHMENT_STORE_OP_STORE,
+ (renderPassNo == 0) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp stencilLoadOp;
+ VK_ATTACHMENT_STORE_OP_STORE,
+ (renderPassNo == 0) ? VK_IMAGE_LAYOUT_UNDEFINED : layout, // VkImageLayout initialLayout;
finalLayout // VkImageLayout finalLayout;
);
const AttachmentReference2 multisampleAttachmentRef // VkAttachmentReference2
attachmentRefStencil, // const void* pNext;
0u, // deUint32 attachment;
layout, // VkImageLayout layout;
- 0u // VkImageAspectFlags aspectMask;
+ m_config.aspectFlag // VkImageAspectFlags aspectMask;
);
- const vk::VkImageLayout singleSampleInitialLayout = (m_config.unusedResolve ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED);
+ vk::VkImageLayout singleSampleInitialLayout = (m_config.unusedResolve ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED);
+ if (renderPassNo != 0)
+ singleSampleInitialLayout = layout;
+ if (m_config.separateDepthStencilLayouts && m_config.verifyBuffer == VB_STENCIL)
+ singlesampleStencilFinalLayout.stencilInitialLayout = singleSampleInitialLayout;
+
+ const tcu::TextureFormat format (mapVkFormat(vkformat));
+ VkImageAspectFlags aspectFlags =
+ ((tcu::hasDepthComponent(format.order) ? static_cast<vk::VkImageAspectFlags>(vk::VK_IMAGE_ASPECT_DEPTH_BIT) : 0u) |
+ (tcu::hasStencilComponent(format.order) ? static_cast<vk::VkImageAspectFlags>(vk::VK_IMAGE_ASPECT_STENCIL_BIT) : 0u));
const AttachmentDescription2 singlesampleAttachment // VkAttachmentDescription2
(
// VkStructureType sType;
- attachmentDescriptionStencil, // const void* pNext;
+ singlesampleAttachmentDescriptionStencil, // const void* pNext;
0u, // VkAttachmentDescriptionFlags flags;
- m_config.format, // VkFormat format;
+ vkformat, // VkFormat format;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
AttachmentReference2 singlesampleAttachmentRef // VkAttachmentReference2
(
// VkStructureType sType;
- DE_NULL, // const void* pNext;
- (m_config.unusedResolve ? VK_ATTACHMENT_UNUSED : 1u), // deUint32 attachment;
+ attachmentRefStencil, // const void* pNext;
+ ((m_config.unusedResolve || renderPassNo != m_numRenderPasses - 1) ? VK_ATTACHMENT_UNUSED : 1u), // deUint32 attachment;
layout, // VkImageLayout layout;
- 0u // VkImageAspectFlags aspectMask;
+ aspectFlags // VkImageAspectFlags aspectMask;
);
std::vector<AttachmentDescription2> attachments;
const SubpassDescription2 subpass // VkSubpassDescription2
(
// VkStructureType sType;
- &dsResolveDescription, // const void* pNext;
+ renderPassNo == m_numRenderPasses - 1 ? &dsResolveDescription : DE_NULL, // const void* pNext;
(VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
0u, // deUint32 viewMask;
return renderPassCreator.createRenderPass(m_vkd, m_device);
}
+// Checks format support.
+// Note: we need the context because this is called from the constructor only after m_config has been set.
+bool DepthStencilResolveTest::isSupportedFormat (Context& context, VkFormat format) const
+{
+ const VkImageUsageFlags usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
+ | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
+ | (m_config.unusedResolve ? VK_IMAGE_USAGE_TRANSFER_DST_BIT : static_cast<vk::VkImageUsageFlagBits>(0u));
+ VkImageFormatProperties props;
+
+ const auto& vki = context.getInstanceInterface();
+ const auto physicalDevice = context.getPhysicalDevice();
+ const auto formatCheck = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, 0u, &props);
+
+ return (formatCheck == VK_SUCCESS);
+}
+
+Move<VkRenderPass> DepthStencilResolveTest::createRenderPassCompatible (void)
+{
+ // Early exit if we are not testing compatibility.
+ if (! m_config.compatibleFormat)
+ return {};
+
+ return createRenderPass(m_config.compatibleFormat.get(), 0);
+}
+
Move<VkFramebuffer> DepthStencilResolveTest::createFramebuffer (VkRenderPass renderPass, VkImageViewSp multisampleImageView, VkImageViewSp singlesampleImageView)
{
std::vector<VkImageView> attachments;
return vk::createPipelineLayout(m_vkd, m_device, &createInfo);
}
-Move<VkPipeline> DepthStencilResolveTest::createRenderPipeline (VkRenderPass renderPass, VkPipelineLayout renderPipelineLayout)
+Move<VkPipeline> DepthStencilResolveTest::createRenderPipeline (VkRenderPass renderPass, deUint32 renderPassNo, VkPipelineLayout renderPipelineLayout)
{
const bool testingStencil = (m_config.verifyBuffer == VB_STENCIL);
const vk::BinaryCollection& binaryCollection = m_context.getBinaryCollection();
const tcu::UVec2 view (m_config.width, m_config.height);
const std::vector<VkViewport> viewports (1, makeViewport(view));
const std::vector<VkRect2D> scissors (1, m_config.renderArea);
+ const VkSampleMask samplemask[2] = {
+ renderPassNo < 32 ? (1u << renderPassNo) : 0,
+ renderPassNo < 32 ? 0 : (1u << (renderPassNo - 32)) };
const VkPipelineMultisampleStateCreateInfo multisampleState =
{
sampleCountBitFromSampleCount(m_config.sampleCount),
VK_FALSE,
0.0f,
- DE_NULL,
+ (m_config.sampleMask) ? &samplemask[0] : DE_NULL,
VK_FALSE,
VK_FALSE,
};
{
const DeviceInterface& vkd (m_context.getDeviceInterface());
const VkDevice device (m_context.getDevice());
- const Unique<VkCommandBuffer> commandBuffer (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
- const RenderpassSubpass2::SubpassBeginInfo subpassBeginInfo (DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
- const RenderpassSubpass2::SubpassEndInfo subpassEndInfo (DE_NULL);
-
- beginCommandBuffer(vkd, *commandBuffer);
+ // When the depth/stencil resolve attachment is unused, it needs to be cleared outside
+ // the render pass so it has the expected values.
+ if (m_config.unusedResolve)
{
- VkClearValue clearValues[2];
- clearValues[0].depthStencil = m_config.clearValue;
- clearValues[1].depthStencil = m_config.clearValue;
+ const tcu::TextureFormat format (mapVkFormat(m_config.format));
+ const Unique<VkCommandBuffer> commandBuffer (allocateCommandBuffer(m_vkd, m_device, *m_commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+ const vk::VkImageSubresourceRange imageRange =
+ {
+ ((tcu::hasDepthComponent(format.order) ? static_cast<vk::VkImageAspectFlags>(vk::VK_IMAGE_ASPECT_DEPTH_BIT) : 0u) |
+ (tcu::hasStencilComponent(format.order) ? static_cast<vk::VkImageAspectFlags>(vk::VK_IMAGE_ASPECT_STENCIL_BIT) : 0u)),
+ 0u,
+ VK_REMAINING_MIP_LEVELS,
+ 0u,
+ VK_REMAINING_ARRAY_LAYERS,
+ };
+ const vk::VkImageMemoryBarrier preBarrier =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ nullptr,
+
+ // src and dst access masks.
+ 0,
+ vk::VK_ACCESS_TRANSFER_WRITE_BIT,
+
+ // old and new layouts.
+ vk::VK_IMAGE_LAYOUT_UNDEFINED,
+ vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+
+ VK_QUEUE_FAMILY_IGNORED,
+ VK_QUEUE_FAMILY_IGNORED,
- const VkRenderPassBeginInfo beginInfo =
+ **m_singlesampleImage,
+ imageRange,
+ };
+ const vk::VkImageMemoryBarrier postBarrier =
{
- VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
- DE_NULL,
+ vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ nullptr,
- *m_renderPass,
- *m_framebuffer,
+ // src and dst access masks.
+ vk::VK_ACCESS_TRANSFER_WRITE_BIT,
+ 0,
- {
- { 0u, 0u },
- { m_config.width, m_config.height }
- },
+ // old and new layouts.
+ vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- 2u,
- clearValues
+ VK_QUEUE_FAMILY_IGNORED,
+ VK_QUEUE_FAMILY_IGNORED,
+
+ **m_singlesampleImage,
+ imageRange,
};
- RenderpassSubpass2::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
+
+ vk::beginCommandBuffer(m_vkd, commandBuffer.get());
+ m_vkd.cmdPipelineBarrier(commandBuffer.get(), vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preBarrier);
+ m_vkd.cmdClearDepthStencilImage(commandBuffer.get(), **m_singlesampleImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_config.clearValue, 1u, &imageRange);
+ m_vkd.cmdPipelineBarrier(commandBuffer.get(), vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &postBarrier);
+ vk::endCommandBuffer(m_vkd, commandBuffer.get());
+
+ vk::submitCommandsAndWait(m_vkd, m_device, m_context.getUniversalQueue(), commandBuffer.get());
}
- // Render
+ const Unique<VkCommandBuffer> commandBuffer(allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+ const RenderpassSubpass2::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
+ const RenderpassSubpass2::SubpassEndInfo subpassEndInfo(DE_NULL);
+
+ beginCommandBuffer(vkd, *commandBuffer);
bool testingDepth = (m_config.verifyBuffer == VB_DEPTH);
if (testingDepth)
{
- vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
+ {
+ VkClearValue clearValues[2];
+ clearValues[0].depthStencil = m_config.clearValue;
+ clearValues[1].depthStencil = m_config.clearValue;
+
+ const VkRenderPassBeginInfo beginInfo =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ DE_NULL,
+
+ (m_config.compatibleFormat ? *m_renderPassCompatible : *m_renderPass[0]),
+ *m_framebuffer,
+
+ {
+ { 0u, 0u },
+ { m_config.width, m_config.height }
+ },
+
+ 2u,
+ clearValues
+ };
+ RenderpassSubpass2::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
+ }
+
+ // Render
+ vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline[0]);
vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
+ RenderpassSubpass2::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
}
else
{
- // For stencil we can set reference value for just one sample at a time
- // so we need to do as many passes as there are samples, first half
- // of samples is initialized with 1 and second half with 255
- const deUint32 halfOfSamples = m_config.sampleCount >> 1;
- for (deUint32 renderPass = 0 ; renderPass < m_config.sampleCount ; renderPass++)
+ // Stencil
+ for (deUint32 i = 0; i < m_config.sampleCount; i++)
{
- deUint32 stencilReference = 1 + 254 * (renderPass >= halfOfSamples);
- vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
- vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(renderPass), &renderPass);
+ if (i == 0 || m_config.sampleMask)
+ {
+ VkClearValue clearValues[2];
+ clearValues[0].depthStencil = m_config.clearValue;
+ clearValues[1].depthStencil = m_config.clearValue;
+
+ const VkRenderPassBeginInfo beginInfo =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ DE_NULL,
+
+ (m_config.compatibleFormat ? *m_renderPassCompatible : *m_renderPass[i]),
+ *m_framebuffer,
+
+ {
+ { 0u, 0u },
+ { m_config.width, m_config.height }
+ },
+
+ 2u,
+ clearValues
+ };
+ vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, 0, 0, 0, 0, 0);
+ RenderpassSubpass2::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
+ }
+ // For stencil we can set reference value for just one sample at a time
+ // so we need to do as many passes as there are samples, first half
+ // of samples is initialized with 1 and second half with 255
+ const deUint32 halfOfSamples = m_config.sampleCount >> 1;
+
+ deUint32 stencilReference = 1 + 254 * (i >= halfOfSamples);
+ vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline[m_config.sampleMask ? i : 0]);
+ vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(i), &i);
vkd.cmdSetStencilReference(*commandBuffer, VK_STENCIL_FRONT_AND_BACK, stencilReference);
vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
+ if (i == m_config.sampleCount - 1 || m_config.sampleMask)
+ RenderpassSubpass2::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
}
}
- RenderpassSubpass2::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
-
// Memory barriers between rendering and copying
{
const VkImageMemoryBarrier barrier =
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
DE_NULL,
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+ // Note: as per the spec, depth/stencil *resolve* operations are synchronized using the color attachment write access.
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
}
else
{
- dst.glslSources.add("quad-frag") << glu::FragmentSource(
- "#version 450\n"
- "precision highp float;\n"
- "precision highp int;\n"
- "layout(push_constant) uniform PushConstant {\n"
- " highp int sampleID;\n"
- "} pushConstants;\n"
- "void main (void)\n"
- "{\n"
- " if(gl_SampleID != pushConstants.sampleID)\n"
- " discard;\n"
- " gl_FragDepth = 0.5;\n"
- "}\n");
+ if (config.sampleMask)
+ {
+ dst.glslSources.add("quad-frag") << glu::FragmentSource(
+ "#version 450\n"
+ "precision highp float;\n"
+ "precision highp int;\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_FragDepth = 0.5;\n"
+ "}\n");
+ }
+ else
+ {
+ dst.glslSources.add("quad-frag") << glu::FragmentSource(
+ "#version 450\n"
+ "precision highp float;\n"
+ "precision highp int;\n"
+ "layout(push_constant) uniform PushConstant {\n"
+ " highp int sampleID;\n"
+ "} pushConstants;\n"
+ "void main (void)\n"
+ "{\n"
+ " if(gl_SampleID != pushConstants.sampleID)\n"
+ " discard;\n"
+ " gl_FragDepth = 0.5;\n"
+ "}\n");
+ }
}
}
};
{ 255u, 255u, 255u, 255u, 255u, 255u }, // RESOLVE_MODE_MAX_BIT
};
+ const DepthCompatibilityManager compatManager;
+
tcu::TestContext& testCtx(group->getTestContext());
// Misc tests.
0u,
useSeparateDepthStencilLayouts,
unusedResolve,
+ tcu::nothing<VkFormat>(),
+ false
};
formatGroup->addChild(new DSResolveTestInstance(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName, testName, testConfig));
+
+ if (sampleCountNdx == 0 && imageDataNdx == 0)
+ {
+ const auto compatibleFormat = compatManager.getAlternativeFormat(format);
+
+ if (compatibleFormat != VK_FORMAT_UNDEFINED)
+ {
+ std::string compatibilityTestName = "compatibility_" + name;
+ TestConfig compatibilityTestConfig = testConfig;
+ compatibilityTestConfig.compatibleFormat = tcu::just(compatibleFormat);
+
+ formatGroup->addChild(new DSResolveTestInstance(testCtx, tcu::NODETYPE_SELF_VALIDATE, compatibilityTestName.c_str(), compatibilityTestName.c_str(), compatibilityTestConfig));
+ }
+ }
}
if (hasStencil)
{
expectedValue,
useSeparateDepthStencilLayouts,
unusedResolve,
+ tcu::nothing<VkFormat>(),
+ false
};
formatGroup->addChild(new DSResolveTestInstance(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName, testName, testConfig));
+
+ if (dResolve.flag == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
+ {
+ std::string samplemaskTestName = name + "_samplemask";
+ TestConfig samplemaskTestConfig = testConfig;
+ samplemaskTestConfig.sampleMask = true;
+ formatGroup->addChild(new DSResolveTestInstance(testCtx, tcu::NODETYPE_SELF_VALIDATE, samplemaskTestName.c_str(), samplemaskTestName.c_str(), samplemaskTestConfig));
+ }
+
+ // All formats with stencil and depth aspects have incompatible formats and sizes in the depth
+ // aspect, so their only alternative is the VK_FORMAT_S8_UINT format. Finally, that stencil-only
+ // format has no compatible formats that can be used.
+ if (sampleCountNdx == 0 && imageDataNdx == 0 && hasDepth)
+ {
+ std::string compatibilityTestName = "compatibility_" + name;
+ TestConfig compatibilityTestConfig = testConfig;
+ compatibilityTestConfig.compatibleFormat = tcu::just(VK_FORMAT_S8_UINT);
+
+ formatGroup->addChild(new DSResolveTestInstance(testCtx, tcu::NODETYPE_SELF_VALIDATE, compatibilityTestName.c_str(), compatibilityTestName.c_str(), compatibilityTestConfig));
+ }
}
}
}
0u,
useSeparateDepthStencilLayouts,
unusedResolve,
+ tcu::nothing<VkFormat>(),
+ false
};
formatGroup->addChild(new DSResolveTestInstance(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName, testName, testConfig));
}
expectedValue,
useSeparateDepthStencilLayouts,
unusedResolve,
+ tcu::nothing<VkFormat>(),
+ false
};
formatGroup->addChild(new DSResolveTestInstance(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName, testName, testConfig));
}