Check output depth in inverted depth range tests
authorRicardo Garcia <rgarcia@igalia.com>
Tue, 28 Jul 2020 16:38:22 +0000 (18:38 +0200)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Sat, 5 Sep 2020 07:42:59 +0000 (03:42 -0400)
This commit makes inverted depth range tests use a depth/stencil
attachment and checks values stored in it are correct after rendering,
which is specially important in the depth clamping case.

In addition, several magic constants and values have been given a name
and declared at the top, among other minor fixes.

tcu::dsThresholdCompare() has been fixed to use absolute values when
checking if depth value differences are above the given threshold. This
function is used in some copy and blitting tests.

Affected tests:
dEQP-VK.draw.inverted_depth_ranges.*
dEQP-VK.api.copy_and_blit.*.buffer_to_depthstencil.*

Components: Framework, Vulkan
VK-GL-CTS issue: 2446

Change-Id: I50568dce77d8bbf01ab50fd6e96e8aef7d1df685

external/vulkancts/modules/vulkan/draw/vktDrawInvertedDepthRangesTests.cpp
framework/common/tcuImageCompare.cpp

index 678fa1c..0b547c2 100644 (file)
 
 #include "deSharedPtr.hpp"
 
+#include <utility>
+#include <array>
+#include <vector>
+#include <iterator>
+
 namespace vkt
 {
 namespace Draw
@@ -59,19 +64,49 @@ struct TestParams
        float           maxDepth;
 };
 
+constexpr deUint32                     kImageDim               = 256u;
+const VkExtent3D                       kImageExtent    = makeExtent3D(kImageDim, kImageDim, 1u);
+const Vec4                                     kClearColor             (0.0f, 0.0f, 0.0f, 1.0f);
+constexpr float                                kClearDepth             = 1.0f;
+constexpr int                          kClearStencil   = 0;
+constexpr int                          kMaskedStencil  = 1;
+constexpr float                                kDepthEpsilon   = 0.00025f;     // Used to decide if a calculated depth passes the depth test.
+constexpr float                                kDepthThreshold = 0.0025f;      // Used when checking depth buffer values. Less than depth delta in each pixel (~= 1.4/205).
+constexpr float                                kMargin                 = 0.2f;         // Space between triangle and image border. See kVertices.
+constexpr float                                kDiagonalMargin = 0.00125f; // Makes sure the image diagonal falls inside the triangle. See kVertices.
+const Vec4                                     kVertexColor    (0.0f, 0.5f, 0.5f, 1.0f); // Note: the first component will vary.
+const std::array<Vec4, 3u>     kVertices               =
+{{
+       Vec4(-1.0f + kMargin,                   -1.0f + kMargin,                    -0.2f, 1.0f),       //  0-----2
+       Vec4(-1.0f + kMargin,                    1.0f - kMargin + kDiagonalMargin,   0.0f, 1.0f),       //   |  /
+       Vec4( 1.0f - kMargin + kDiagonalMargin, -1.0f + kMargin,                     1.2f, 1.0f),       //  1|/
+}};
+
+
 class InvertedDepthRangesTestInstance : public TestInstance
 {
 public:
-                                                                       InvertedDepthRangesTestInstance (Context& context, const TestParams& params);
-       tcu::TestStatus                                 iterate                                                 (void);
-       tcu::ConstPixelBufferAccess             draw                                                    (const VkViewport viewport);
-       MovePtr<tcu::TextureLevel>              generateReferenceImage                  (void) const;
+       enum class ReferenceImageType
+       {
+               COLOR = 0,
+               DEPTH,
+       };
+
+       using ColorAndDepth = std::pair<tcu::ConstPixelBufferAccess, tcu::ConstPixelBufferAccess>;
+
+                                                                                               InvertedDepthRangesTestInstance (Context& context, const TestParams& params);
+       tcu::TestStatus                                                         iterate                                                 (void);
+       ColorAndDepth                                                           draw                                                    (const VkViewport viewport);
+       MovePtr<tcu::TextureLevel>                                      generateReferenceImage                  (ReferenceImageType refType) const;
 
 private:
        const TestParams                                m_params;
        const VkFormat                                  m_colorAttachmentFormat;
+       const VkFormat                                  m_depthAttachmentFormat;
        SharedPtr<Image>                                m_colorTargetImage;
        Move<VkImageView>                               m_colorTargetView;
+       SharedPtr<Image>                                m_depthTargetImage;
+       Move<VkImageView>                               m_depthTargetView;
        SharedPtr<Buffer>                               m_vertexBuffer;
        Move<VkRenderPass>                              m_renderPass;
        Move<VkFramebuffer>                             m_framebuffer;
@@ -83,42 +118,51 @@ InvertedDepthRangesTestInstance::InvertedDepthRangesTestInstance (Context& conte
        : TestInstance                          (context)
        , m_params                                      (params)
        , m_colorAttachmentFormat       (VK_FORMAT_R8G8B8A8_UNORM)
+       , m_depthAttachmentFormat       (VK_FORMAT_D16_UNORM)
 {
        const DeviceInterface&  vk              = m_context.getDeviceInterface();
        const VkDevice                  device  = m_context.getDevice();
+       auto&                                   alloc   = m_context.getDefaultAllocator();
+       auto                                    qIndex  = m_context.getUniversalQueueFamilyIndex();
 
        // Vertex data
        {
-               std::vector<Vec4> vertexData;
-
-               vertexData.push_back(Vec4(-0.8f, -0.8f, -0.2f, 1.0f));  //  0-----2
-               vertexData.push_back(Vec4(-0.8f,  0.8f,  0.0f, 1.0f));  //   |  /
-               vertexData.push_back(Vec4( 0.8f, -0.8f,  1.2f, 1.0f));  //  1|/
-
-               const VkDeviceSize dataSize = vertexData.size() * sizeof(Vec4);
+               const auto dataSize = static_cast<VkDeviceSize>(kVertices.size() * sizeof(decltype(kVertices)::value_type));
                m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
-                                                                                               m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
+                                                                                               alloc, MemoryRequirement::HostVisible);
 
-               deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &vertexData[0], static_cast<std::size_t>(dataSize));
+               deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), kVertices.data(), static_cast<size_t>(dataSize));
                flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
        }
 
        // Render pass
        {
-               const VkExtent3D                targetImageExtent               = { 256, 256, 1 };
                const VkImageUsageFlags targetImageUsageFlags   = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+               const VkImageUsageFlags depthTargeUsageFlags    = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
 
                const ImageCreateInfo   targetImageCreateInfo(
                        VK_IMAGE_TYPE_2D,                                               // imageType,
                        m_colorAttachmentFormat,                                // format,
-                       targetImageExtent,                                              // extent,
+                       kImageExtent,                                                   // extent,
                        1u,                                                                             // mipLevels,
                        1u,                                                                             // arrayLayers,
                        VK_SAMPLE_COUNT_1_BIT,                                  // samples,
                        VK_IMAGE_TILING_OPTIMAL,                                // tiling,
                        targetImageUsageFlags);                                 // usage,
 
-               m_colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
+               m_colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, alloc, qIndex);
+
+               const ImageCreateInfo   depthTargetImageCreateInfo(
+                       VK_IMAGE_TYPE_2D,                                               // imageType,
+                       m_depthAttachmentFormat,                                // format,
+                       kImageExtent,                                                   // extent,
+                       1u,                                                                             // mipLevels,
+                       1u,                                                                             // arrayLayers,
+                       VK_SAMPLE_COUNT_1_BIT,                                  // samples,
+                       VK_IMAGE_TILING_OPTIMAL,                                // tiling,
+                       depthTargeUsageFlags);                                  // usage,
+
+               m_depthTargetImage = Image::createAndAlloc(vk, device, depthTargetImageCreateInfo, alloc, qIndex);
 
                RenderPassCreateInfo    renderPassCreateInfo;
                renderPassCreateInfo.addAttachment(AttachmentDescription(
@@ -131,12 +175,28 @@ InvertedDepthRangesTestInstance::InvertedDepthRangesTestInstance (Context& conte
                        VK_IMAGE_LAYOUT_GENERAL,                                // initialLayout
                        VK_IMAGE_LAYOUT_GENERAL));                              // finalLayout
 
+               renderPassCreateInfo.addAttachment(AttachmentDescription(
+                       m_depthAttachmentFormat,                                // format
+                       VK_SAMPLE_COUNT_1_BIT,                                  // samples
+                       VK_ATTACHMENT_LOAD_OP_LOAD,                             // loadOp
+                       VK_ATTACHMENT_STORE_OP_STORE,                   // storeOp
+                       VK_ATTACHMENT_LOAD_OP_DONT_CARE,                // stencilLoadOp
+                       VK_ATTACHMENT_STORE_OP_DONT_CARE,               // stencilStoreOp
+                       VK_IMAGE_LAYOUT_GENERAL,                                // initialLayout
+                       VK_IMAGE_LAYOUT_GENERAL));                              // finalLayout
+
                const VkAttachmentReference colorAttachmentReference =
                {
                        0u,
                        VK_IMAGE_LAYOUT_GENERAL
                };
 
+               const VkAttachmentReference depthAttachmentReference =
+               {
+                       1u,
+                       VK_IMAGE_LAYOUT_GENERAL
+               };
+
                renderPassCreateInfo.addSubpass(SubpassDescription(
                        VK_PIPELINE_BIND_POINT_GRAPHICS,                // pipelineBindPoint
                        (VkSubpassDescriptionFlags)0,                   // flags
@@ -145,7 +205,7 @@ InvertedDepthRangesTestInstance::InvertedDepthRangesTestInstance (Context& conte
                        1u,                                                                             // colorAttachmentCount
                        &colorAttachmentReference,                              // colorAttachments
                        DE_NULL,                                                                // resolveAttachments
-                       AttachmentReference(),                                  // depthStencilAttachment
+                       depthAttachmentReference,                               // depthStencilAttachment
                        0u,                                                                             // preserveAttachmentCount
                        DE_NULL));                                                              // preserveAttachments
 
@@ -157,10 +217,14 @@ InvertedDepthRangesTestInstance::InvertedDepthRangesTestInstance (Context& conte
                const ImageViewCreateInfo colorTargetViewInfo (m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
                m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
 
-               std::vector<VkImageView> colorAttachments(1);
-               colorAttachments[0] = *m_colorTargetView;
+               const ImageViewCreateInfo depthTargetViewInfo (m_depthTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_depthAttachmentFormat);
+               m_depthTargetView = createImageView(vk, device, &depthTargetViewInfo);
+
+               std::vector<VkImageView> fbAttachments(2);
+               fbAttachments[0] = *m_colorTargetView;
+               fbAttachments[1] = *m_depthTargetView;
 
-               const FramebufferCreateInfo     framebufferCreateInfo(*m_renderPass, colorAttachments, 256, 256, 1);
+               const FramebufferCreateInfo     framebufferCreateInfo(*m_renderPass, fbAttachments, kImageExtent.width, kImageExtent.height, 1u);
                m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
        }
 
@@ -186,7 +250,7 @@ InvertedDepthRangesTestInstance::InvertedDepthRangesTestInstance (Context& conte
 
        // Graphics pipeline
 
-       const VkRect2D scissor = makeRect2D(256u, 256u);
+       const auto scissor = makeRect2D(kImageExtent);
 
        std::vector<VkDynamicState>             dynamicStates;
        dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
@@ -206,7 +270,7 @@ InvertedDepthRangesTestInstance::InvertedDepthRangesTestInstance (Context& conte
        pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
        pipelineCreateInfo.addState (PipelineCreateInfo::ColorBlendState        (1, &colorBlendAttachmentState));
        pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState          (1, std::vector<VkViewport>(), std::vector<VkRect2D>(1, scissor)));
-       pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState      ());
+       pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState      (true, true));
        pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState        (
                m_params.depthClampEnable,      // depthClampEnable
                VK_FALSE,                                       // rasterizerDiscardEnable
@@ -224,12 +288,13 @@ InvertedDepthRangesTestInstance::InvertedDepthRangesTestInstance (Context& conte
        m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
 }
 
-tcu::ConstPixelBufferAccess InvertedDepthRangesTestInstance::draw (const VkViewport viewport)
+InvertedDepthRangesTestInstance::ColorAndDepth InvertedDepthRangesTestInstance::draw (const VkViewport viewport)
 {
        const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
        const VkDevice                  device                          = m_context.getDevice();
        const VkQueue                   queue                           = m_context.getUniversalQueue();
        const deUint32                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+       auto&                                   alloc                           = m_context.getDefaultAllocator();
 
        // Command buffer
 
@@ -244,11 +309,16 @@ tcu::ConstPixelBufferAccess InvertedDepthRangesTestInstance::draw (const VkViewp
        vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport);
 
        {
-               const VkClearColorValue         clearColor                      = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f).color;
-               const ImageSubresourceRange subresourceRange    (VK_IMAGE_ASPECT_COLOR_BIT);
+               const VkClearColorValue                 clearColor                              = makeClearValueColor(kClearColor).color;
+               const ImageSubresourceRange             subresourceRange                (VK_IMAGE_ASPECT_COLOR_BIT);
+
+               const VkClearDepthStencilValue  clearDepth                              = makeClearValueDepthStencil(kClearDepth, 0u).depthStencil;
+               const ImageSubresourceRange             depthSubresourceRange   (VK_IMAGE_ASPECT_DEPTH_BIT);
 
                initialTransitionColor2DImage(vk, *cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+               initialTransitionDepth2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
                vk.cmdClearColorImage(*cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
+               vk.cmdClearDepthStencilImage(*cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, &clearDepth, 1u, &depthSubresourceRange);
        }
        {
                const VkMemoryBarrier memBarrier =
@@ -259,10 +329,19 @@ tcu::ConstPixelBufferAccess InvertedDepthRangesTestInstance::draw (const VkViewp
                        VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT              // VkAccessFlags      dstAccessMask;
                };
 
+               const VkMemoryBarrier depthBarrier =
+               {
+                       VK_STRUCTURE_TYPE_MEMORY_BARRIER,                                                                                               // VkStructureType    sType;
+                       DE_NULL,                                                                                                                                                // const void*        pNext;
+                       VK_ACCESS_TRANSFER_WRITE_BIT,                                                                                                   // VkAccessFlags      srcAccessMask;
+                       VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT              // VkAccessFlags      dstAccessMask;
+               };
+
                vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
+               vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT), 0, 1, &depthBarrier, 0, DE_NULL, 0, DE_NULL);
        }
 
-       beginRenderPass(vk, *cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, 256u, 256u));
+       beginRenderPass(vk, *cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(kImageExtent));
 
        {
                const VkDeviceSize      offset  = 0;
@@ -281,36 +360,87 @@ tcu::ConstPixelBufferAccess InvertedDepthRangesTestInstance::draw (const VkViewp
 
        // Get result
        {
-               const VkOffset3D zeroOffset = { 0, 0, 0 };
-               return m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_GENERAL, zeroOffset, 256, 256, VK_IMAGE_ASPECT_COLOR_BIT);
+               const auto zeroOffset   = makeOffset3D(0, 0, 0);
+               const auto iWidth               = static_cast<int>(kImageExtent.width);
+               const auto iHeight              = static_cast<int>(kImageExtent.height);
+               const auto colorPixels  = m_colorTargetImage->readSurface(queue, alloc, VK_IMAGE_LAYOUT_GENERAL, zeroOffset, iWidth, iHeight, VK_IMAGE_ASPECT_COLOR_BIT);
+               const auto depthPixels  = m_depthTargetImage->readSurface(queue, alloc, VK_IMAGE_LAYOUT_GENERAL, zeroOffset, iWidth, iHeight, VK_IMAGE_ASPECT_DEPTH_BIT);
+
+               return ColorAndDepth(colorPixels, depthPixels);
        }
 }
 
-MovePtr<tcu::TextureLevel> InvertedDepthRangesTestInstance::generateReferenceImage (void) const
+MovePtr<tcu::TextureLevel> InvertedDepthRangesTestInstance::generateReferenceImage (ReferenceImageType refType) const
 {
-       MovePtr<tcu::TextureLevel>              image                   (new tcu::TextureLevel(mapVkFormat(m_colorAttachmentFormat), 256, 256));
+       const auto                                              iWidth                  = static_cast<int>(kImageExtent.width);
+       const auto                                              iHeight                 = static_cast<int>(kImageExtent.height);
+       const bool                                              color                   = (refType == ReferenceImageType::COLOR);
+       const auto                                              tcuFormat               = mapVkFormat(color ? m_colorAttachmentFormat : VK_FORMAT_D16_UNORM_S8_UINT);
+       MovePtr<tcu::TextureLevel>              image                   (new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
        const tcu::PixelBufferAccess    access                  (image->getAccess());
-       const Vec4                                              black                   (0.0f, 0.0f, 0.0f, 1.0f);
-       const int                                               p1                              = static_cast<int>(256.0f * 0.2f / 2.0f);
-       const int                                               p2                              = static_cast<int>(256.0f * 1.8f / 2.0f);
-       const float                                             delta                   = 256.0f * 1.6f / 2.0f;
-       const float                                             depthValues[]   = { -0.2f, 0.0f, 1.2f };
+       const float                                             fImageDim               = static_cast<float>(kImageDim);
+       const float                                             p1f                             = fImageDim * kMargin / 2.0f;
+       const float                                             p2f                             = fImageDim * (2.0f - kMargin + kDiagonalMargin) / 2.0f;
+       const float                                             triangleSide    = fImageDim * (2.0f - (2.0f*kMargin - kDiagonalMargin)) / 2.0f;
+       const float                                             clampMin                = de::min(m_params.minDepth, m_params.maxDepth);
+       const float                                             clampMax                = de::max(m_params.minDepth, m_params.maxDepth);
+       std::array<float, 3>                    depthValues;
+
+       // Depth value of each vertex in kVertices.
+       DE_ASSERT(depthValues.size() == kVertices.size());
+       std::transform(begin(kVertices), end(kVertices), begin(depthValues), [](const Vec4& coord) { return coord.z(); });
+
+       if (color)
+               tcu::clear(access, kClearColor);
+       else
+       {
+               tcu::clearDepth(access, kClearDepth);
+               tcu::clearStencil(access, kClearStencil);
+       }
+
+       for (int y = 0; y < iHeight; ++y)
+       for (int x = 0; x < iWidth; ++x)
+       {
+               const float xcoord = static_cast<float>(x) + 0.5f;
+               const float ycoord = static_cast<float>(y) + 0.5f;
+
+               if (xcoord < p1f || xcoord > p2f)
+                       continue;
+
+               if (ycoord < p1f || ycoord > p2f)
+                       continue;
+
+               if (ycoord > -xcoord + fImageDim)
+                       continue;
+
+               // Interpolate depth value taking the 3 triangle corners into account.
+               const float b                           = (ycoord - p1f) / triangleSide;
+               const float c                           = (xcoord - p1f) / triangleSide;
+               const float a                           = 1.0f - b - c;
+               const float     depth                   = a * depthValues[0] + b * depthValues[1] + c * depthValues[2];
 
-       tcu::clear(access, black);
+               const float     depthClamped    = de::clamp(depth, 0.0f, 1.0f);
+               const float     depthFinal              = depthClamped * m_params.maxDepth + (1.0f - depthClamped) * m_params.minDepth;
+               const float     storedDepth             = (m_params.depthClampEnable ? de::clamp(depthFinal, clampMin, clampMax) : depthFinal);
 
-       for (int y = p1; y <= p2; ++y)
-               for (int x = p1; x <  256 - y;  ++x)
+               if (m_params.depthClampEnable || de::inRange(depth, -kDepthEpsilon, 1.0f + kDepthEpsilon))
                {
-                       const float     a = static_cast<float>(p2 - x + p1 - y) / delta;
-                       const float     b = static_cast<float>(y - p1) / delta;
-                       const float     c = 1.0f - a - b;
-                       const float     depth = a * depthValues[0] + b * depthValues[1] + c * depthValues[2];
-                       const float     depthClamped = de::clamp(depth, 0.0f, 1.0f);
-                       const float     depthFinal = depthClamped * m_params.maxDepth + (1.0f - depthClamped) * m_params.minDepth;
-
-                       if (m_params.depthClampEnable || (depth >= 0.0f && depth <= 1.0f))
-                               access.setPixel(Vec4(depthFinal, 0.5f, 0.5f, 1.0f), x, y);
+                       if (color)
+                               access.setPixel(Vec4(depthFinal, kVertexColor.y(), kVertexColor.z(), kVertexColor.w()), x, y);
+                       else
+                       {
+                               if (!m_params.depthClampEnable &&
+                                       (de::inRange(depth, -kDepthEpsilon, kDepthEpsilon) ||
+                                        de::inRange(depth, 1.0f - kDepthEpsilon, 1.0f + kDepthEpsilon)))
+                               {
+                                       // We should avoid comparing this pixel due to possible rounding problems.
+                                       // Pixels that should not be compared will be marked in the stencil aspect.
+                                       access.setPixStencil(kMaskedStencil, x, y);
+                               }
+                               access.setPixDepth(storedDepth, x, y);
+                       }
                }
+       }
 
        return image;
 }
@@ -321,25 +451,65 @@ tcu::TestStatus InvertedDepthRangesTestInstance::iterate (void)
 
        const VkViewport viewport =
        {
-               0.0f,                           // float    x;
-               0.0f,                           // float    y;
-               256.0f,                         // float    width;
-               256.0f,                         // float    height;
-               m_params.minDepth,      // float    minDepth;
-               m_params.maxDepth,      // float    maxDepth;
+               0.0f,                                                                           // float    x;
+               0.0f,                                                                           // float    y;
+               static_cast<float>(kImageExtent.width),         // float    width;
+               static_cast<float>(kImageExtent.height),        // float    height;
+               m_params.minDepth,                                                      // float    minDepth;
+               m_params.maxDepth,                                                      // float    maxDepth;
        };
 
-       const tcu::ConstPixelBufferAccess       resultImage     = draw(viewport);
-
-       // Verify the results
+       ColorAndDepth   results         = draw(viewport);
+       auto&                   resultImage     = results.first;
+       auto&                   resultDepth     = results.second;
 
-       tcu::TestLog&                           log                             = m_context.getTestContext().getLog();
-       MovePtr<tcu::TextureLevel>      referenceImage  = generateReferenceImage();
+       // Verify results
+       auto&   log                             = m_context.getTestContext().getLog();
+       auto    referenceImage  = generateReferenceImage(ReferenceImageType::COLOR);
+       auto    referenceDepth  = generateReferenceImage(ReferenceImageType::DEPTH);
 
+       // Color aspect.
        if (!tcu::fuzzyCompare(log, "Image compare", "Image compare", referenceImage->getAccess(), resultImage, 0.02f, tcu::COMPARE_LOG_RESULT))
                return tcu::TestStatus::fail("Rendered image is incorrect");
-       else
-               return tcu::TestStatus::pass("Pass");
+
+       // Depth aspect.
+       const auto refWidth                     = referenceDepth->getWidth();
+       const auto refHeight            = referenceDepth->getHeight();
+       const auto refAccess            = referenceDepth->getAccess();
+
+       tcu::TextureLevel errorMask     (mapVkFormat(VK_FORMAT_R8G8B8_UNORM), refWidth, refHeight);
+       auto errorAccess                        = errorMask.getAccess();
+       const tcu::Vec4 kGreen          (0.0f, 1.0f, 0.0f, 1.0f);
+       const tcu::Vec4 kRed            (1.0f, 0.0f, 0.0f, 1.0f);
+
+       bool fail = false;
+       tcu::clear(errorAccess, kGreen);
+
+       for (int y = 0; y < refHeight; ++y)
+       for (int x = 0; x < refWidth; ++x)
+       {
+               // Ignore pixels that could be too close to having or not having coverage.
+               const auto stencil = refAccess.getPixStencil(x, y);
+               if (stencil == kMaskedStencil)
+                       continue;
+
+               // Compare the rest using a known threshold.
+               const auto refValue = refAccess.getPixDepth(x, y);
+               const auto resValue = resultDepth.getPixDepth(x, y);
+               if (!de::inRange(resValue, refValue - kDepthThreshold, refValue + kDepthThreshold))
+               {
+                       fail = true;
+                       errorAccess.setPixel(kRed, x, y);
+               }
+       }
+
+       if (fail)
+       {
+               log << tcu::TestLog::Image("ErrorMask", "Error mask", errorAccess);
+               return tcu::TestStatus::fail("Result depth buffer is incorrect");
+       }
+
+       return tcu::TestStatus::pass("Pass");
 }
 
 class InvertedDepthRangesTest : public TestCase
@@ -358,10 +528,10 @@ public:
                        std::ostringstream src;
                        src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
                                << "\n"
-                               << "layout(location = 0) in vec4 in_position;\n"
+                               << "layout(location = 0) in highp vec4 in_position;\n"
                                << "\n"
                                << "out gl_PerVertex {\n"
-                               << "    vec4  gl_Position;\n"
+                               << "    highp vec4 gl_Position;\n"
                                << "};\n"
                                << "\n"
                                << "void main(void)\n"
@@ -377,11 +547,11 @@ public:
                        std::ostringstream src;
                        src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
                                << "\n"
-                               << "layout(location = 0) out vec4 out_color;\n"
+                               << "layout(location = 0) out highp vec4 out_color;\n"
                                << "\n"
                                << "void main(void)\n"
                                << "{\n"
-                               << "    out_color = vec4(gl_FragCoord.z, 0.5, 0.5, 1.0);\n"
+                               << "    out_color = vec4(gl_FragCoord.z, " << kVertexColor.y() << ", " << kVertexColor.z() << ", " << kVertexColor.w() << ");\n"
                                << "}\n";
 
                        programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
index b3907ef..bc2549c 100644 (file)
@@ -851,10 +851,10 @@ bool dsThresholdCompare(TestLog& log, const char* imageSetName, const char* imag
 
                                if (hasDepth)
                                {
-                                       float   refDepth = reference.getPixDepth(x, y, z);
-                                       float   cmpDepth = result.getPixDepth(x, y, z);
+                                       float refDepth  = reference.getPixDepth(x, y, z);
+                                       float cmpDepth  = result.getPixDepth(x, y, z);
+                                       float diff              = de::abs(refDepth - cmpDepth);
 
-                                       float   diff = refDepth - cmpDepth;
                                        isOk = diff <= threshold;
                                        maxDiff = (float) deMax(maxDiff, diff);
                                }