Add geometry layered readback tests
authorBoris Zanin <boris.zanin@mobica.com>
Tue, 31 Oct 2017 15:17:30 +0000 (16:17 +0100)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Thu, 30 Nov 2017 09:38:54 +0000 (04:38 -0500)
Add geometry layered readback tests for following image types:
 * 1d_array (color and depth/stencil)
 * 2d_array (color and depth/stencil)
 * cube (color and depth/stencil)
 * cube_array (color and depth/stencil)
 * 3d (color only)

Add tests:
 * dEQP-VK.geometry.layered.*.readback

Components: Vulkan

VK-GL-CTS issue: #790

Change-Id: Ifcc5b686816b167ae7fb5157fdc7bd3464968eda

android/cts/master/vk-master.txt
external/vulkancts/modules/vulkan/geometry/vktGeometryLayeredRenderingTests.cpp
external/vulkancts/modules/vulkan/geometry/vktGeometryTestsUtil.cpp
external/vulkancts/modules/vulkan/geometry/vktGeometryTestsUtil.hpp
external/vulkancts/mustpass/1.1.0/vk-default.txt

index b13274c..f35e0ff 100755 (executable)
@@ -251188,6 +251188,7 @@ dEQP-VK.geometry.layered.1d_array.render_different_content
 dEQP-VK.geometry.layered.1d_array.fragment_layer
 dEQP-VK.geometry.layered.1d_array.invocation_per_layer
 dEQP-VK.geometry.layered.1d_array.multiple_layers_per_invocation
+dEQP-VK.geometry.layered.1d_array.readback
 dEQP-VK.geometry.layered.2d_array.render_to_default_layer
 dEQP-VK.geometry.layered.2d_array.render_to_one
 dEQP-VK.geometry.layered.2d_array.render_to_all
@@ -251195,6 +251196,7 @@ dEQP-VK.geometry.layered.2d_array.render_different_content
 dEQP-VK.geometry.layered.2d_array.fragment_layer
 dEQP-VK.geometry.layered.2d_array.invocation_per_layer
 dEQP-VK.geometry.layered.2d_array.multiple_layers_per_invocation
+dEQP-VK.geometry.layered.2d_array.readback
 dEQP-VK.geometry.layered.cube.render_to_default_layer
 dEQP-VK.geometry.layered.cube.render_to_one
 dEQP-VK.geometry.layered.cube.render_to_all
@@ -251202,6 +251204,7 @@ dEQP-VK.geometry.layered.cube.render_different_content
 dEQP-VK.geometry.layered.cube.fragment_layer
 dEQP-VK.geometry.layered.cube.invocation_per_layer
 dEQP-VK.geometry.layered.cube.multiple_layers_per_invocation
+dEQP-VK.geometry.layered.cube.readback
 dEQP-VK.geometry.layered.cube_array.render_to_default_layer
 dEQP-VK.geometry.layered.cube_array.render_to_one
 dEQP-VK.geometry.layered.cube_array.render_to_all
@@ -251209,6 +251212,7 @@ dEQP-VK.geometry.layered.cube_array.render_different_content
 dEQP-VK.geometry.layered.cube_array.fragment_layer
 dEQP-VK.geometry.layered.cube_array.invocation_per_layer
 dEQP-VK.geometry.layered.cube_array.multiple_layers_per_invocation
+dEQP-VK.geometry.layered.cube_array.readback
 dEQP-VK.geometry.layered.3d.render_to_default_layer
 dEQP-VK.geometry.layered.3d.render_to_one
 dEQP-VK.geometry.layered.3d.render_to_all
@@ -251216,6 +251220,7 @@ dEQP-VK.geometry.layered.3d.render_different_content
 dEQP-VK.geometry.layered.3d.fragment_layer
 dEQP-VK.geometry.layered.3d.invocation_per_layer
 dEQP-VK.geometry.layered.3d.multiple_layers_per_invocation
+dEQP-VK.geometry.layered.3d.readback
 dEQP-VK.geometry.instanced.draw_1_instances_1_geometry_invocations
 dEQP-VK.geometry.instanced.draw_1_instances_2_geometry_invocations
 dEQP-VK.geometry.instanced.draw_1_instances_8_geometry_invocations
index 30edc64..980014f 100644 (file)
@@ -34,6 +34,7 @@
 #include "vkRefUtil.hpp"
 #include "vkTypeUtil.hpp"
 #include "vkImageUtil.hpp"
+#include "vkBuilderUtil.hpp"
 
 #include "deStringUtil.hpp"
 #include "deUniquePtr.hpp"
@@ -63,6 +64,7 @@ enum TestType
        TEST_TYPE_LAYER_ID,                                                     // !< draw to all layers, verify gl_Layer fragment input
        TEST_TYPE_INVOCATION_PER_LAYER,                         // !< draw to all layers, one invocation per layer
        TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,       // !< draw to all layers, multiple invocations write to multiple layers
+       TEST_TYPE_LAYERED_READBACK,                                     // !< draw to two layers multiple times
 };
 
 struct ImageParams
@@ -88,6 +90,14 @@ static const float s_colors[][4] =
        { 1.0f, 0.0f, 1.0f, 1.0f },             // magenta
 };
 
+tcu::Vec4 scaleColor(const tcu::Vec4& color, float factor)
+{
+       return tcu::Vec4(color[0] * factor,
+                                        color[1] * factor,
+                                        color[2] * factor,
+                                        color[3]);
+}
+
 deUint32 getTargetLayer (const ImageParams& imageParams)
 {
        if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D)
@@ -125,11 +135,48 @@ VkImageType getImageType (const VkImageViewType viewType)
        }
 }
 
+VkFormat getStencilBufferFormat(VkFormat depthStencilImageFormat)
+{
+       const tcu::TextureFormat tcuFormat = mapVkFormat(depthStencilImageFormat);
+       const VkFormat result = (tcuFormat.order == tcu::TextureFormat::S || tcuFormat.order == tcu::TextureFormat::DS) ? VK_FORMAT_S8_UINT : VK_FORMAT_UNDEFINED;
+
+       DE_ASSERT(result != VK_FORMAT_UNDEFINED);
+
+       return result;
+}
+
 inline bool isCubeImageViewType (const VkImageViewType viewType)
 {
        return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
 }
 
+void checkImageFormatProperties (const InstanceInterface&      vki,
+                                                                const VkPhysicalDevice&        physDevice,
+                                                                const VkImageType&                     imageType,
+                                                                const VkImageTiling&           imageTiling,
+                                                                const VkImageUsageFlags        imageUsageFlags,
+                                                                const VkImageCreateFlags       imageCreateFlags,
+                                                                const VkFormat                         format,
+                                                                const VkExtent3D&                      requiredSize,
+                                                                const deUint32                         requiredLayers)
+{
+       VkImageFormatProperties imageFormatProperties;
+       VkResult                                result;
+
+       deMemset(&imageFormatProperties, 0, sizeof(imageFormatProperties));
+
+       result = vki.getPhysicalDeviceImageFormatProperties(physDevice, format, imageType, imageTiling, imageUsageFlags, imageCreateFlags, &imageFormatProperties);
+
+       if (result                                                                      != VK_SUCCESS                   ||
+               imageFormatProperties.maxArrayLayers    <  requiredLayers               ||
+               imageFormatProperties.maxExtent.height  <  requiredSize.height  ||
+               imageFormatProperties.maxExtent.width   <  requiredSize.width   ||
+               imageFormatProperties.maxExtent.depth   <  requiredSize.depth)
+       {
+               TCU_THROW(NotSupportedError, "Depth/stencil format is not supported");
+       }
+}
+
 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage)
 {
        const VkImageCreateInfo imageParams =
@@ -206,6 +253,80 @@ Move<VkRenderPass> makeRenderPass (const DeviceInterface&  vk,
        return createRenderPass(vk, device, &renderPassInfo);
 }
 
+Move<VkRenderPass> makeRenderPass (const DeviceInterface&      vk,
+                                                                  const VkDevice                       device,
+                                                                  const VkFormat                       colorFormat,
+                                                                  const VkFormat                       dsFormat,
+                                                                  const bool                           useDepthStencil)
+{
+       const VkAttachmentDescription   attachmentDescriptions[]        =
+       {
+               // Color attachment
+               {
+                       (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
+                       colorFormat,                                                                            // VkFormat                                                     format;
+                       VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
+                       VK_ATTACHMENT_LOAD_OP_LOAD,                                                     // VkAttachmentLoadOp                           loadOp;
+                       VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
+                       VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
+                       VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        finalLayout;
+               },
+               // Depth/stencil attachment
+               {
+                       (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
+                       dsFormat,                                                                                       // VkFormat                                                     format;
+                       VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
+                       VK_ATTACHMENT_LOAD_OP_LOAD,                                                     // VkAttachmentLoadOp                           loadOp;
+                       VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
+                       VK_ATTACHMENT_LOAD_OP_LOAD,                                                     // VkAttachmentLoadOp                           stencilLoadOp;
+                       VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          stencilStoreOp;
+                       VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        initialLayout;
+                       VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        finalLayout;
+               }
+       };
+       const deUint32                                  attachmentDescriptionsCount     = useDepthStencil ? DE_LENGTH_OF_ARRAY(attachmentDescriptions) : 1u;
+       const VkAttachmentReference             colorAttachmentRef                      =
+       {
+               0u,                                                                                                             // deUint32                     attachment;
+               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                                // VkImageLayout        layout;
+       };
+       const VkAttachmentReference             dsAttachmentRef                         =
+       {
+               1u,                                                                                                             // deUint32                     attachment;
+               VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL                // VkImageLayout        layout;
+       };
+       const VkSubpassDescription              subpassDescription                      =
+       {
+               (VkSubpassDescriptionFlags)0,                                                   // VkSubpassDescriptionFlags            flags;
+               VK_PIPELINE_BIND_POINT_GRAPHICS,                                                // VkPipelineBindPoint                          pipelineBindPoint;
+               0u,                                                                                                             // deUint32                                                     inputAttachmentCount;
+               DE_NULL,                                                                                                // const VkAttachmentReference*         pInputAttachments;
+               1u,                                                                                                             // deUint32                                                     colorAttachmentCount;
+               &colorAttachmentRef,                                                                    // const VkAttachmentReference*         pColorAttachments;
+               DE_NULL,                                                                                                // const VkAttachmentReference*         pResolveAttachments;
+               useDepthStencil ? &dsAttachmentRef : DE_NULL,                   // const VkAttachmentReference*         pDepthStencilAttachment;
+               0u,                                                                                                             // deUint32                                                     preserveAttachmentCount;
+               DE_NULL                                                                                                 // const deUint32*                                      pPreserveAttachments;
+       };
+       const VkRenderPassCreateInfo    renderPassInfo                          =
+       {
+               VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                              // VkStructureType                                      sType;
+               DE_NULL,                                                                                                // const void*                                          pNext;
+               (VkRenderPassCreateFlags)0,                                                             // VkRenderPassCreateFlags                      flags;
+               attachmentDescriptionsCount,                                                    // deUint32                                                     attachmentCount;
+               attachmentDescriptions,                                                                 // const VkAttachmentDescription*       pAttachments;
+               1u,                                                                                                             // deUint32                                                     subpassCount;
+               &subpassDescription,                                                                    // const VkSubpassDescription*          pSubpasses;
+               0u,                                                                                                             // deUint32                                                     dependencyCount;
+               DE_NULL                                                                                                 // const VkSubpassDependency*           pDependencies;
+       };
+
+       return createRenderPass(vk, device, &renderPassInfo);
+}
+
+
 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&          vk,
                                                                           const VkDevice                               device,
                                                                           const VkPipelineLayout               pipelineLayout,
@@ -213,7 +334,8 @@ Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&               vk,
                                                                           const VkShaderModule                 vertexModule,
                                                                           const VkShaderModule                 geometryModule,
                                                                           const VkShaderModule                 fragmentModule,
-                                                                          const VkExtent2D                             renderSize)
+                                                                          const VkExtent2D                             renderSize,
+                                                                          const bool                                   useDepthStencil = false)
 {
        const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
        {
@@ -287,24 +409,24 @@ Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&             vk,
        };
 
        const VkStencilOpState stencilOpState = makeStencilOpState(
-               VK_STENCIL_OP_KEEP,                             // stencil fail
-               VK_STENCIL_OP_KEEP,                             // depth & stencil pass
-               VK_STENCIL_OP_KEEP,                             // depth only fail
-               VK_COMPARE_OP_ALWAYS,                   // compare op
-               0u,                                                             // compare mask
-               0u,                                                             // write mask
-               0u);                                                    // reference
+               VK_STENCIL_OP_KEEP,                                     // stencil fail
+               VK_STENCIL_OP_INCREMENT_AND_CLAMP,      // depth & stencil pass
+               VK_STENCIL_OP_KEEP,                                     // depth only fail
+               VK_COMPARE_OP_ALWAYS,                           // compare op
+               ~0u,                                                            // compare mask
+               ~0u,                                                            // write mask
+               0u);                                                            // reference
 
        VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
        {
                VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
                DE_NULL,                                                                                                                // const void*                                                          pNext;
                (VkPipelineDepthStencilStateCreateFlags)0,                                              // VkPipelineDepthStencilStateCreateFlags       flags;
-               VK_FALSE,                                                                                                               // VkBool32                                                                     depthTestEnable;
-               VK_FALSE,                                                                                                               // VkBool32                                                                     depthWriteEnable;
+               useDepthStencil ? VK_TRUE : VK_FALSE,                                                   // VkBool32                                                                     depthTestEnable;
+               useDepthStencil ? VK_TRUE : VK_FALSE,                                                   // VkBool32                                                                     depthWriteEnable;
                VK_COMPARE_OP_LESS,                                                                                             // VkCompareOp                                                          depthCompareOp;
                VK_FALSE,                                                                                                               // VkBool32                                                                     depthBoundsTestEnable;
-               VK_FALSE,                                                                                                               // VkBool32                                                                     stencilTestEnable;
+               useDepthStencil ? VK_TRUE : VK_FALSE,                                                   // VkBool32                                                                     stencilTestEnable;
                stencilOpState,                                                                                                 // VkStencilOpState                                                     front;
                stencilOpState,                                                                                                 // VkStencilOpState                                                     back;
                0.0f,                                                                                                                   // float                                                                        minDepthBounds;
@@ -393,6 +515,30 @@ Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&              vk,
        return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
 }
 
+Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&    vk,
+                                                                        const VkDevice                 device,
+                                                                        const VkRenderPass             renderPass,
+                                                                        const VkImageView*             pAttachments,
+                                                                        const deUint32                 attachmentsCount,
+                                                                        const deUint32                 width,
+                                                                        const deUint32                 height,
+                                                                        const deUint32                 layers)
+{
+       const VkFramebufferCreateInfo framebufferInfo = {
+               VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,              // VkStructureType                             sType;
+               DE_NULL,                                                                                // const void*                                 pNext;
+               (VkFramebufferCreateFlags)0,                                    // VkFramebufferCreateFlags                    flags;
+               renderPass,                                                                             // VkRenderPass                                renderPass;
+               attachmentsCount,                                                               // uint32_t                                    attachmentCount;
+               pAttachments,                                                                   // const VkImageView*                          pAttachments;
+               width,                                                                                  // uint32_t                                    width;
+               height,                                                                                 // uint32_t                                    height;
+               layers,                                                                                 // uint32_t                                    layers;
+       };
+
+       return createFramebuffer(vk, device, &framebufferInfo);
+}
+
 //! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way.
 class LayeredImageAccess
 {
@@ -516,6 +662,134 @@ bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBuffer
        return allPixelsOk;
 }
 
+static bool verifyImageMultipleBars (tcu::TestLog&                                             log,
+                                                                        const tcu::ConstPixelBufferAccess      image,
+                                                                        const float*                                           barWidthRatios,
+                                                                        const tcu::Vec4*                                       barValues,
+                                                                        const int                                                      barsCount,
+                                                                        const int                                                      numUsedChannels,
+                                                                        const std::string&                                     imageTypeName)
+{
+       const Vec4                                      green                           (0.0f, 1.0f, 0.0f, 1.0f);
+       const Vec4                                      red                                     (1.0f, 0.0f, 0.0f, 1.0f);
+       const Vec4                                      threshold                       (0.02f);
+       const tcu::TextureFormat        errorMaskFormat         (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8));
+       tcu::TextureLevel                       errorMask                       (errorMaskFormat, image.getWidth(), image.getHeight());
+       tcu::PixelBufferAccess          errorMaskAccess         = errorMask.getAccess();
+       bool                                            allPixelsOk                     = true;
+
+       DE_ASSERT(barsCount > 0);
+
+       tcu::clear(errorMask.getAccess(), green);
+
+       // Format information message
+       {
+               int                                     leftBorder      = 0;
+               int                                     rightBorder     = 0;
+               std::ostringstream      str;
+
+               for (int barNdx = 0; barNdx < barsCount; ++barNdx)
+               {
+                       leftBorder      = rightBorder;
+                       rightBorder     = static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
+
+                       DE_ASSERT(leftBorder < rightBorder);
+
+                       str << std::endl << " [" << leftBorder << "," <<rightBorder << "): ";
+
+                       switch (numUsedChannels)
+                       {
+                               case 1: str << barValues[barNdx][0];    break;
+                               case 4: str << barValues[barNdx];               break;
+                               default: DE_ASSERT(false);                              break;
+                       }
+               }
+
+               log << tcu::TestLog::Message
+                       << "Expecting " + imageTypeName + " values depending x-axis position to be of following values: "
+                       << str.str()
+                       << tcu::TestLog::EndMessage;
+       }
+
+       for (int x = 0; x < image.getWidth();  ++x)
+       {
+               tcu::Vec4       expectedValue   = barValues[0];
+
+               for (int barNdx = 0; barNdx < barsCount; ++barNdx)
+               {
+                       const int rightBorder   = static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
+
+                       if (x < rightBorder)
+                       {
+                               expectedValue = barValues[barNdx];
+
+                               break;
+                       }
+               }
+
+               for (int y = 0; y < image.getHeight(); ++y)
+               {
+                       const tcu::Vec4 realValue       = image.getPixel(x, y);
+                       bool                    isOk            = false;
+
+                       switch (numUsedChannels)
+                       {
+                               case 1: isOk = fabs(realValue[0] - expectedValue[0]) < threshold[0];    break;
+                               case 4: isOk = compareColors(realValue, expectedValue, threshold);              break;
+                               default: DE_ASSERT(false);                                                                                              break;
+                       }
+
+                       if (!isOk)
+                               errorMaskAccess.setPixel(red, x, y);
+
+                       allPixelsOk = allPixelsOk && isOk;
+               }
+       }
+
+       if (allPixelsOk)
+       {
+               log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
+                       << tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
+                       << tcu::TestLog::Image("Layer", "Layer", image)
+                       << tcu::TestLog::EndImageSet;
+       }
+       else
+       {
+               log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
+                       << tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
+                       << tcu::TestLog::Image("Layer",         "Layer",        image)
+                       << tcu::TestLog::Image("ErrorMask",     "Errors",       errorMask)
+                       << tcu::TestLog::EndImageSet;
+       }
+
+       return allPixelsOk;
+}
+
+static void convertDepthToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage)
+{
+       for (int y = 0; y < inputImage.getHeight(); y++)
+       for (int x = 0; x < inputImage.getWidth(); x++)
+       {
+               const float             depth   = inputImage.getPixDepth(x, y);
+               const tcu::Vec4 color   = tcu::Vec4(depth, depth, depth, 1.0f);
+
+               outputImage.setPixel(color, x, y);
+       }
+}
+
+static void convertStencilToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage, int maxValue)
+{
+       for (int y = 0; y < inputImage.getHeight(); y++)
+       for (int x = 0; x < inputImage.getWidth(); x++)
+       {
+               const int               stencilInt      = inputImage.getPixStencil(x, y);
+               const float             stencil         = (stencilInt < maxValue) ? float(stencilInt) / float(maxValue) : 1.0f;
+               const tcu::Vec4 color           = tcu::Vec4(stencil, stencil, stencil, 1.0f);
+
+               outputImage.setPixel(color, x, y);
+       }
+}
+
 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
 {
        log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
@@ -545,7 +819,7 @@ bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess imag
        return true;
 }
 
-bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers)
+bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers, const bool depthCheck, const bool stencilCheck)
 {
        const Vec4      white                           (1.0f, 1.0f, 1.0f, 1.0f);
        const int       targetLayer                     = numLayers / 2;
@@ -586,6 +860,54 @@ bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::
                        return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
                }
 
+               case TEST_TYPE_LAYERED_READBACK:
+               {
+                       const float     barWidthRatios[]        = { 0.25f, 0.5f, 1.0f };
+                       const int       barsCount                       = DE_LENGTH_OF_ARRAY(barWidthRatios);
+                       bool            result                          = false;
+
+                       if (depthCheck)
+                       {
+                               const std::string               checkType                               = "Depth";
+                               const float                             pass0depth                              = static_cast<float>(layerNdx + 1) / static_cast<float>(2 * numLayers);
+                               const float                             pass1depth                              = static_cast<float>(layerNdx + 0) / static_cast<float>(2 * numLayers);
+                               const tcu::Vec4                 barDepths[barsCount]    = { tcu::Vec4(pass1depth), tcu::Vec4(pass0depth), tcu::Vec4(1.0f) };
+                               tcu::TextureLevel               depthAsColorBuffer              (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
+                               tcu::PixelBufferAccess  depthAsColor                    (depthAsColorBuffer);
+                               const int                               numUsedChannels                 (tcu::getNumUsedChannels(depthAsColor.getFormat().order));
+
+                               convertDepthToColorBufferAccess(image, depthAsColor);
+
+                               result = verifyImageMultipleBars(log, depthAsColor, barWidthRatios, barDepths, barsCount, numUsedChannels, checkType);
+                       }
+                       else if (stencilCheck)
+                       {
+                               const std::string               checkType                               = "Stencil";
+                               const int                               maxStencilValue                 = 4;
+                               const float                             pass0stencil                    = static_cast<float>(1.0f / maxStencilValue);
+                               const float                             pass1stencil                    = static_cast<float>(2.0f / maxStencilValue);
+                               const tcu::Vec4                 barStencils[barsCount]  = { tcu::Vec4(pass1stencil), tcu::Vec4(pass0stencil), tcu::Vec4(0.0f) };
+                               tcu::TextureLevel               stencilAsColorBuffer    (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
+                               tcu::PixelBufferAccess  stencilAsColor                  (stencilAsColorBuffer);
+                               const int                               numUsedChannels                 (tcu::getNumUsedChannels(stencilAsColor.getFormat().order));
+
+                               convertStencilToColorBufferAccess(image, stencilAsColor, maxStencilValue);
+
+                               result = verifyImageMultipleBars(log, stencilAsColor, barWidthRatios, barStencils, barsCount, numUsedChannels, checkType);
+                       }
+                       else
+                       {
+                               const std::string               checkType                               = "Color";
+                               const tcu::Vec4                 baseColor                               (s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
+                               const tcu::Vec4                 barColors[barsCount]    = { scaleColor(baseColor, 1.00f), scaleColor(baseColor, 0.50f), scaleColor(baseColor, 0.25f) };
+                               const int                               numUsedChannels                 (tcu::getNumUsedChannels(image.getFormat().order));
+
+                               result = verifyImageMultipleBars(log, image, barWidthRatios, barColors, barsCount, numUsedChannels, checkType);
+                       }
+
+                       return result;
+               }
+
                default:
                        DE_ASSERT(0);
                        return false;
@@ -607,9 +929,9 @@ std::string getLayerDescription (const VkImageViewType viewType, const int layer
        return str.str();
 }
 
-bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat colorFormat, const void* resultData)
+bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat imageFormat, const void* resultData, const bool depthCheck = false, const bool stencilCheck = false)
 {
-       const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), colorFormat, params.image.size, params.image.numLayers, resultData);
+       const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), imageFormat, params.image.size, params.image.numLayers, resultData);
 
        int numGoodLayers = 0;
 
@@ -619,7 +941,7 @@ bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat
 
                log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
 
-               if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices()))
+               if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices(), depthCheck, stencilCheck))
                        ++numGoodLayers;
        }
 
@@ -638,7 +960,7 @@ std::string toGlsl (const Vec4& v)
 
 void initPrograms (SourceCollections& programCollection, const TestParams params)
 {
-       const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER);
+       const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_LAYERED_READBACK);
 
        // Vertex shader
        {
@@ -656,14 +978,19 @@ void initPrograms (SourceCollections& programCollection, const TestParams params
        {
                const int numLayers             = static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
 
-               const int maxVertices   = (params.testType == TEST_TYPE_DIFFERENT_CONTENT)                                                                              ? (numLayers + 1) * numLayers :
-                                                                 (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_LAYER_ID   ? numLayers * 4 :
-                                                                 (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)                                                 ? 6 : 4;
+               const int maxVertices   = (params.testType == TEST_TYPE_DIFFERENT_CONTENT)                                                                                                                                                                              ? (numLayers + 1) * numLayers :
+                                                                 (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_LAYER_ID || params.testType == TEST_TYPE_LAYERED_READBACK)   ? numLayers * 4 :
+                                                                 (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)                                                                                                                                                 ? 6 : 4;
 
                std::ostringstream src;
                src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
                        << "\n";
 
+               if (params.testType == TEST_TYPE_LAYERED_READBACK)
+                       src << "layout(binding = 0) readonly uniform Input {\n"
+                               << "    int pass;\n"
+                               << "} uInput;\n\n";
+
                if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
                        src << "layout(points, invocations = " << numLayers << ") in;\n";
                else
@@ -853,6 +1180,39 @@ void initPrograms (SourceCollections& programCollection, const TestParams params
                                << "    EmitVertex();\n"
                                << "    EndPrimitive();\n";
                }
+               else if (params.testType == TEST_TYPE_LAYERED_READBACK)
+               {
+                       src << colorTable.str()
+                               << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
+                               << "        const int   colorNdx   = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
+                               << "        const vec3  passColor0 = (uInput.pass == 0 ? 0.5 :  1.0) * vec3(colors[colorNdx]);\n"
+                               << "        const vec4  passColor  = vec4(passColor0, 1.0);\n"
+                               << "        const float posX       = (uInput.pass == 0 ? 0.0 : -0.5);\n"
+                               << "        const float posZ       = float(layerNdx + 1 - uInput.pass) / float(" << 2*numLayers << ");\n"
+                               << "\n"
+                               << "        gl_Position = vec4(-1.0, -1.0, posZ, 1.0);\n"
+                               << "        gl_Layer    = layerNdx;\n"
+                               << "        vert_color  = passColor;\n"
+                               << "        EmitVertex();\n"
+                               << "\n"
+                               << "        gl_Position = vec4(-1.0,  1.0, posZ, 1.0);\n"
+                               << "        gl_Layer    = layerNdx;\n"
+                               << "        vert_color  = passColor;\n"
+                               << "        EmitVertex();\n"
+                               << "\n"
+                               << "        gl_Position = vec4(posX, -1.0, posZ, 1.0);\n"
+                               << "        gl_Layer    = layerNdx;\n"
+                               << "        vert_color  = passColor;\n"
+                               << "        EmitVertex();\n"
+                               << "\n"
+                               << "        gl_Position = vec4(posX,  1.0, posZ, 1.0);\n"
+                               << "        gl_Layer    = layerNdx;\n"
+                               << "        vert_color  = passColor;\n"
+                               << "        EmitVertex();\n"
+                               << "\n"
+                               << "        EndPrimitive();\n"
+                               << "    }\n";
+               }
                else
                        DE_ASSERT(0);
 
@@ -928,7 +1288,7 @@ tcu::TestStatus test (Context& context, const TestParams params)
        const Unique<VkShaderModule>    fragmentModule                  (createShaderModule             (vk, device, context.getBinaryCollection().get("frag"), 0u));
 
        const Unique<VkRenderPass>              renderPass                              (makeRenderPass                 (vk, device, colorFormat));
-       const Unique<VkFramebuffer>             framebuffer                             (makeFramebuffer                (vk, device, *renderPass, *colorAttachment, params.image.size.width,  params.image.size.height, numLayers));
+       const Unique<VkFramebuffer>             framebuffer                             (makeFramebuffer                (vk, device, *renderPass, &*colorAttachment, 1u, params.image.size.width,  params.image.size.height, numLayers));
        const Unique<VkPipelineLayout>  pipelineLayout                  (makePipelineLayout             (vk, device));
        const Unique<VkPipeline>                pipeline                                (makeGraphicsPipeline   (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
                                                                                                                                                                         makeExtent2D(params.image.size.width, params.image.size.height)));
@@ -1029,6 +1389,288 @@ tcu::TestStatus test (Context& context, const TestParams params)
                return tcu::TestStatus::pass("OK");
 }
 
+tcu::TestStatus testLayeredReadBack (Context& context, const TestParams params)
+{
+       if (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType &&
+               (!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance1")))
+               TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
+
+       const DeviceInterface&                          vk                                      = context.getDeviceInterface();
+       const InstanceInterface&                        vki                                     = context.getInstanceInterface();
+       const VkDevice                                          device                          = context.getDevice();
+       const VkPhysicalDevice                          physDevice                      = context.getPhysicalDevice();
+       const deUint32                                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
+       const VkQueue                                           queue                           = context.getUniversalQueue();
+       Allocator&                                                      allocator                       = context.getDefaultAllocator();
+
+       checkGeometryShaderSupport(vki, physDevice);
+
+       const size_t                                            passCount                       = 2;
+       const deUint32                                          numLayers                       = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
+       const VkImageCreateFlags                        imageCreateFlags        = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
+                                                                                                                         (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
+       const VkImageViewType                           viewType                        = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
+       const VkImageType                                       imageType                       = getImageType(params.image.viewType);
+       const VkExtent2D                                        imageExtent2D           = makeExtent2D(params.image.size.width, params.image.size.height);
+
+       const VkFormat                                          colorFormat                     = VK_FORMAT_R8G8B8A8_UNORM;
+       const deUint32                                          colorImagePixelSize     = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
+       const VkDeviceSize                                      colorBufferSize         = params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * colorImagePixelSize;
+       const VkImageUsageFlags                         colorImageUsage         = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+       const bool                                                      dsUsed                          = (VK_IMAGE_VIEW_TYPE_3D != params.image.viewType);
+       const VkFormat                                          dsFormat                        = VK_FORMAT_D24_UNORM_S8_UINT;
+       const deUint32                                          dsImagePixelSize        = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(dsFormat)));
+       const VkImageUsageFlags                         dsImageUsage            = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+       const VkImageAspectFlags                        dsAspectFlags           = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+       const VkDeviceSize                                      depthBufferSize         = params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * dsImagePixelSize;
+
+       const VkFormat                                          stencilBufferFormat     = getStencilBufferFormat(dsFormat);
+       const deUint32                                          stencilPixelSize        = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(stencilBufferFormat)));
+       const VkDeviceSize                                      stencilBufferSize       = params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * stencilPixelSize;
+
+       checkImageFormatProperties(vki, physDevice, imageType, VK_IMAGE_TILING_OPTIMAL, dsImageUsage, imageCreateFlags, dsFormat, params.image.size, params.image.numLayers);
+
+       const Unique<VkImage>                           colorImage                      (makeImage                              (vk, device, makeImageCreateInfo(imageCreateFlags, imageType, colorFormat, params.image.size, params.image.numLayers, colorImageUsage)));
+       const UniquePtr<Allocation>                     colorImageAlloc         (bindImage                              (vk, device, allocator, *colorImage, MemoryRequirement::Any));
+       const Unique<VkImageView>                       colorAttachment         (makeImageView                  (vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
+       const Unique<VkBuffer>                          colorBuffer                     (makeBuffer                             (vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
+       const UniquePtr<Allocation>                     colorBufferAlloc        (bindBuffer                             (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
+
+       const Unique<VkImage>                           dsImage                         (makeImage                              (vk, device, makeImageCreateInfo(imageCreateFlags, imageType, dsFormat, params.image.size, params.image.numLayers, dsImageUsage)));
+       const UniquePtr<Allocation>                     dsImageAlloc            (bindImage                              (vk, device, allocator, *dsImage, MemoryRequirement::Any));
+       const Unique<VkImageView>                       dsAttachment            (makeImageView                  (vk, device, *dsImage, viewType, dsFormat, makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers)));
+       const Unique<VkBuffer>                          depthBuffer                     (makeBuffer                             (vk, device, makeBufferCreateInfo(depthBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
+       const UniquePtr<Allocation>                     depthBufferAlloc        (bindBuffer                             (vk, device, allocator, *depthBuffer, MemoryRequirement::HostVisible));
+       const Unique<VkBuffer>                          stencilBuffer           (makeBuffer                             (vk, device, makeBufferCreateInfo(stencilBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
+       const UniquePtr<Allocation>                     stencilBufferAlloc      (bindBuffer                             (vk, device, allocator, *stencilBuffer, MemoryRequirement::HostVisible));
+
+       const VkImageView                                       attachments[]           = {*colorAttachment, *dsAttachment};
+       const deUint32                                          attachmentsCount        = dsUsed ? DE_LENGTH_OF_ARRAY(attachments) : 1u;
+
+       const Unique<VkShaderModule>            vertexModule            (createShaderModule             (vk, device, context.getBinaryCollection().get("vert"), 0u));
+       const Unique<VkShaderModule>            geometryModule          (createShaderModule             (vk, device, context.getBinaryCollection().get("geom"), 0u));
+       const Unique<VkShaderModule>            fragmentModule          (createShaderModule             (vk, device, context.getBinaryCollection().get("frag"), 0u));
+
+       const Unique<VkRenderPass>                      renderPass                      (makeRenderPass                 (vk, device, colorFormat, dsFormat, dsUsed));
+       const Unique<VkFramebuffer>                     framebuffer                     (makeFramebuffer                (vk, device, *renderPass, attachments, attachmentsCount, params.image.size.width, params.image.size.height, numLayers));
+
+       const Move<VkDescriptorPool>            descriptorPool          = DescriptorPoolBuilder()
+                                                                                                                         .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, passCount)
+                                                                                                                         .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, passCount);
+       const Move<VkDescriptorSetLayout>       descriptorSetLayout     = DescriptorSetLayoutBuilder()
+                                                                                                                         .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
+                                                                                                                         .build(vk, device);
+       const Move<VkDescriptorSet>                     descriptorSet[]         =
+       {
+               makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
+               makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
+       };
+
+       const size_t                                            uniformBufSize          = sizeof(deUint32);
+       const VkBufferCreateInfo                        uniformBufCI            = makeBufferCreateInfo(uniformBufSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
+       const Move<VkBuffer>                            uniformBuf[]            = { createBuffer(vk, device, &uniformBufCI), createBuffer(vk, device, &uniformBufCI) };
+       const MovePtr<Allocation>                       uniformBufAlloc[]       =
+       {
+               allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[0]), MemoryRequirement::HostVisible),
+               allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[1]), MemoryRequirement::HostVisible),
+       };
+       const VkDescriptorBufferInfo            uniformBufDesc[]        =
+       {
+               makeDescriptorBufferInfo(*uniformBuf[0], 0ull, uniformBufSize),
+               makeDescriptorBufferInfo(*uniformBuf[1], 0ull, uniformBufSize),
+       };
+
+       const Unique<VkPipelineLayout>          pipelineLayout          (makePipelineLayout             (vk, device, *descriptorSetLayout));
+       const Unique<VkPipeline>                        pipeline                        (makeGraphicsPipeline   (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, imageExtent2D, dsUsed));
+       const Unique<VkCommandPool>                     cmdPool                         (createCommandPool              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
+       const Unique<VkCommandBuffer>           cmdBuffer                       (allocateCommandBuffer  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+       const VkRect2D                                          renderArea                      =
+       {
+               makeOffset2D(0, 0),
+               imageExtent2D,
+       };
+       const VkRenderPassBeginInfo                     renderPassBeginInfo     =
+       {
+               VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType                      sType;
+               DE_NULL,                                                                                // const void*                          pNext;
+               *renderPass,                                                                    // VkRenderPass                         renderPass;
+               *framebuffer,                                                                   // VkFramebuffer                        framebuffer;
+               renderArea,                                                                             // VkRect2D                                     renderArea;
+               0u,                                                                                             // uint32_t                                     clearValueCount;
+               DE_NULL,                                                                                // const VkClearValue*          pClearValues;
+       };
+       const VkImageSubresourceRange           colorSubresRange        = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
+       const VkImageSubresourceRange           dsSubresRange           = makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, params.image.numLayers);
+       const VkImageMemoryBarrier                      colorPassBarrier        = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                                                                                                                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
+       const VkImageMemoryBarrier                      dsPassBarrier           = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+                                                                                                                               VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
+       std::string                                                     result;
+
+       beginCommandBuffer(vk, *cmdBuffer);
+       {
+               const VkImageMemoryBarrier              colorBarrier    = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
+                                                                                                                                                                VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *colorImage, colorSubresRange);
+               const VkImageMemoryBarrier              dsBarrier               = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
+                                                                                                                                                                VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *dsImage, dsSubresRange);
+
+               vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
+
+               if (dsUsed)
+                       vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
+
+               for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
+               {
+                       const deUint32          imageDepth      = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx :       0u;
+                       const deUint32          layer           = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ?       0u : layerNdx;
+                       const VkOffset3D        imageOffset = makeOffset3D(0u, 0u, imageDepth);
+                       const VkExtent3D        imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
+
+                       // Clear color image with initial value
+                       {
+                               const tcu::Vec4                                 clearColor                              = scaleColor(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)], 0.25f);
+                               const deUint32                                  bufferSliceSize                 = params.image.size.width * params.image.size.height * colorImagePixelSize;
+                               const VkDeviceSize                              bufferOffset                    = layerNdx * bufferSliceSize;
+                               const VkImageSubresourceLayers  imageSubresource                = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
+                               const VkBufferImageCopy                 bufferImageCopyRegion   = makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
+
+                               fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, clearColor);
+                               vk.cmdCopyBufferToImage(*cmdBuffer, *colorBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
+                       }
+
+                       // Clear depth image with initial value
+                       if (dsUsed)
+                       {
+                               const float                                             depthValue                              = 1.0f;
+                               const deUint32                                  bufferSliceSize                 = params.image.size.width * params.image.size.height * dsImagePixelSize;
+                               const VkDeviceSize                              bufferOffset                    = layerNdx * bufferSliceSize;
+                               const VkImageSubresourceLayers  imageSubresource                = makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, layer, 1u);
+                               const VkBufferImageCopy                 bufferImageCopyRegion   = makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
+
+                               fillBuffer(vk, device, *depthBufferAlloc, bufferOffset, bufferSliceSize, dsFormat, depthValue);
+                               vk.cmdCopyBufferToImage(*cmdBuffer, *depthBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
+                       }
+
+                       // Clear stencil image with initial value
+                       if (dsUsed)
+                       {
+                               const deUint8                                   stencilValue                    = 0;
+                               const deUint32                                  bufferSliceSize                 = params.image.size.width * params.image.size.height * stencilPixelSize;
+                               const VkDeviceSize                              bufferOffset                    = layerNdx * bufferSliceSize;
+                               const VkImageSubresourceLayers  imageSubresource                = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, layer, 1u);
+                               const VkBufferImageCopy                 bufferImageCopyRegion   = makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
+                               deUint8*                                                bufferStart                             = static_cast<deUint8*>((*stencilBufferAlloc).getHostPtr());
+                               deUint8*                                                bufferLayerStart                = &bufferStart[bufferOffset];
+
+                               deMemset(bufferLayerStart, stencilValue, bufferSliceSize);
+                               flushMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset() + bufferOffset, bufferSliceSize);
+                               vk.cmdCopyBufferToImage(*cmdBuffer, *stencilBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
+                       }
+               }
+       }
+       // Change images layouts
+       {
+               const VkImageMemoryBarrier              colorBarrier    = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                                                                                                                                                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
+               const VkImageMemoryBarrier              dsBarrier               = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+                                                                                                                                                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
+
+               vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
+
+               if (dsUsed)
+                       vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
+       }
+
+       for (deUint32 pass = 0; pass < passCount; ++pass)
+       {
+               DE_ASSERT(sizeof(pass) == uniformBufSize);
+
+               VK_CHECK(vk.bindBufferMemory(device, *uniformBuf[pass], uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset()));
+               deMemcpy(uniformBufAlloc[pass]->getHostPtr(), &pass, uniformBufSize);
+               flushMappedMemoryRange(vk, device, uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset(), uniformBufSize);
+
+               DescriptorSetUpdateBuilder()
+                       .writeSingle(*descriptorSet[pass], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufDesc[pass])
+                       .update(vk, device);
+
+               vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet[pass], 0u, DE_NULL);
+
+               vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+               vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
+               vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
+               vk.cmdEndRenderPass(*cmdBuffer);
+
+               vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorPassBarrier);
+
+               if (dsUsed)
+                       vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsPassBarrier);
+       }
+       VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+       submitCommandsAndWait(vk, device, queue, *cmdBuffer);
+
+       zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
+       zeroBuffer(vk, device, *depthBufferAlloc, depthBufferSize);
+       zeroBuffer(vk, device, *stencilBufferAlloc, stencilBufferSize);
+
+       beginCommandBuffer(vk, *cmdBuffer);
+       {
+               // Copy color image
+               {
+                       const VkImageMemoryBarrier      preCopyBarrier  = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
+                                                                                                                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorImage, colorSubresRange);
+                       const VkBufferImageCopy         region                  = makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers));
+                       const VkBufferMemoryBarrier     postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
+
+                       vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
+                       vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
+                       vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
+               }
+
+               // Depth/Stencil image copy
+               if (dsUsed)
+               {
+                       const VkImageMemoryBarrier      preCopyBarrier          = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
+                                                                                                                               VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dsImage, dsSubresRange);
+                       const VkBufferImageCopy         depthCopyRegion         = makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, params.image.numLayers));
+                       const VkBufferImageCopy         stencilCopyRegion       = makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, params.image.numLayers));
+                       const VkBufferMemoryBarrier     postCopyBarriers[]      =
+                       {
+                               makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *depthBuffer, 0ull, VK_WHOLE_SIZE),
+                               makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *stencilBuffer, 0ull, VK_WHOLE_SIZE),
+                       };
+
+                       vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
+                       vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *depthBuffer, 1u, &depthCopyRegion);
+                       vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *stencilBuffer, 1u, &stencilCopyRegion);
+                       vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(postCopyBarriers), postCopyBarriers, DE_NULL, 0u);
+               }
+       }
+       VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+       submitCommandsAndWait(vk, device, queue, *cmdBuffer);
+
+       invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
+       invalidateMappedMemoryRange(vk, device, depthBufferAlloc->getMemory(), depthBufferAlloc->getOffset(), depthBufferSize);
+       invalidateMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset(), stencilBufferSize);
+
+       if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
+               result += " Color";
+
+       if (dsUsed)
+       {
+               if (!verifyResults(context.getTestContext().getLog(), params, dsFormat, depthBufferAlloc->getHostPtr(), true, false))
+                       result += " Depth";
+
+               if (!verifyResults(context.getTestContext().getLog(), params, stencilBufferFormat, stencilBufferAlloc->getHostPtr(), false, true))
+                       result += " Stencil";
+       }
+
+       if (result.empty())
+               return tcu::TestStatus::pass("OK");
+       else
+               return tcu::TestStatus::fail("Following parts of image are incorrect:" + result);
+}
+
 } // anonymous
 
 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
@@ -1049,6 +1691,7 @@ tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
                { TEST_TYPE_LAYER_ID,                                           "fragment_layer",                                       "Read gl_Layer in fragment shader"                                                                                                              },
                { TEST_TYPE_INVOCATION_PER_LAYER,                       "invocation_per_layer",                         "Render to multiple layers with multiple invocations, one invocation per layer"                 },
                { TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,     "multiple_layers_per_invocation",       "Render to multiple layers with multiple invocations, multiple layers per invocation",  },
+               { TEST_TYPE_LAYERED_READBACK,                           "readback",                                                     "Render to multiple layers with two passes to check LOAD_OP_LOAD capability"                    },
        };
 
        const ImageParams imageParams[] =
@@ -1071,7 +1714,11 @@ tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
                                testTypes[testTypeNdx].test,
                                imageParams[imageParamNdx],
                        };
-                       addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, test, params);
+
+                       if (testTypes[testTypeNdx].test == TEST_TYPE_LAYERED_READBACK)
+                               addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, testLayeredReadBack, params);
+                       else
+                               addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, test, params);
                }
 
                group->addChild(viewTypeGroup.release());
index 5c831dd..15d2304 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "vktGeometryTestsUtil.hpp"
 #include "vkTypeUtil.hpp"
+#include "vkImageUtil.hpp"
 #include "vkDefs.hpp"
 #include "tcuImageCompare.hpp"
 
@@ -526,6 +527,23 @@ VkBufferImageCopy makeBufferImageCopy (const VkExtent3D                                    extent,
        return copyParams;
 }
 
+VkBufferImageCopy makeBufferImageCopy (const vk::VkDeviceSize&                         bufferOffset,
+                                                                          const vk::VkImageSubresourceLayers&  imageSubresource,
+                                                                          const vk::VkOffset3D&                                imageOffset,
+                                                                          const vk::VkExtent3D&                                imageExtent)
+{
+       const VkBufferImageCopy copyParams =
+       {
+               bufferOffset,                                                           //      VkDeviceSize                            bufferOffset;
+               0u,                                                                                     //      deUint32                                        bufferRowLength;
+               0u,                                                                                     //      deUint32                                        bufferImageHeight;
+               imageSubresource,                                                       //      VkImageSubresourceLayers        imageSubresource;
+               imageOffset,                                                            //      VkOffset3D                                      imageOffset;
+               imageExtent,                                                            //      VkExtent3D                                      imageExtent;
+       };
+       return copyParams;
+}
+
 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&              vk,
                                                                                   const VkDevice                               device,
                                                                                   const VkDescriptorSetLayout  descriptorSetLayout)
@@ -712,6 +730,44 @@ void zeroBuffer (const DeviceInterface& vk, const VkDevice device, const Allocat
        flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), size);
 }
 
+void fillBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize offset, const VkDeviceSize size, const VkFormat format, const tcu::Vec4& color)
+{
+       const tcu::TextureFormat        textureFormat           = mapVkFormat(format);
+       const deUint32                          colorPixelSize          = static_cast<deUint32>(tcu::getPixelSize(textureFormat));
+       tcu::TextureLevel                       colorPixelBuffer        (textureFormat, 1, 1);
+       tcu::PixelBufferAccess          colorPixel                      (colorPixelBuffer);
+
+       colorPixel.setPixel(color, 0, 0);
+
+       const deUint8*  src             = static_cast<deUint8*>(colorPixel.getDataPtr());
+       deUint8*                dstBase = static_cast<deUint8*>(alloc.getHostPtr());
+       deUint8*                dst             = &dstBase[offset];
+
+       for (deUint32 pixelPos = 0; pixelPos < size; pixelPos += colorPixelSize)
+               deMemcpy(&dst[pixelPos], src, colorPixelSize);
+
+       flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset() + offset, size);
+}
+
+void fillBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize offset, const VkDeviceSize size, const VkFormat format, const float depth)
+{
+       const tcu::TextureFormat        textureFormat           = mapVkFormat(format);
+       const deUint32                          colorPixelSize          = static_cast<deUint32>(tcu::getPixelSize(textureFormat));
+       tcu::TextureLevel                       colorPixelBuffer        (textureFormat, 1, 1);
+       tcu::PixelBufferAccess          colorPixel                      (colorPixelBuffer);
+
+       colorPixel.setPixDepth(depth, 0, 0);
+
+       const deUint8*  src             = static_cast<deUint8*>(colorPixel.getDataPtr());
+       deUint8*                dstBase = static_cast<deUint8*>(alloc.getHostPtr());
+       deUint8*                dst             = &dstBase[offset];
+
+       for (deUint32 pixelPos = 0; pixelPos < size; pixelPos += colorPixelSize)
+               deMemcpy(&dst[pixelPos], src, colorPixelSize);
+
+       flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset() + offset, size);
+}
+
 VkBool32 checkPointSize (const InstanceInterface& vki, const VkPhysicalDevice physDevice)
 {
        const VkPhysicalDeviceFeatures  features        = getPhysicalDeviceFeatures  (vki, physDevice);
index 853bb2a..469c0c5 100644 (file)
@@ -172,6 +172,7 @@ vk::Move<vk::VkDescriptorSet>       makeDescriptorSet                       (const vk::DeviceInterface& vk
 vk::Move<vk::VkRenderPass>             makeRenderPass                          (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkFormat colorFormat);
 vk::Move<vk::VkImageView>              makeImageView                           (const vk::DeviceInterface& vk, const vk::VkDevice vkDevice, const vk::VkImage image, const vk::VkImageViewType viewType, const vk::VkFormat format, const vk::VkImageSubresourceRange subresourceRange);
 vk::VkBufferImageCopy                  makeBufferImageCopy                     (const vk::VkExtent3D extent, const vk::VkImageSubresourceLayers subresourceLayers);
+vk::VkBufferImageCopy                  makeBufferImageCopy                     (const vk::VkDeviceSize& bufferOffset, const vk::VkImageSubresourceLayers& imageSubresource, const vk::VkOffset3D& imageOffset, const vk::VkExtent3D& imageExtent);
 vk::Move<vk::VkPipelineLayout> makePipelineLayout                      (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkDescriptorSetLayout descriptorSetLayout = DE_NULL);
 vk::Move<vk::VkFramebuffer>            makeFramebuffer                         (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkRenderPass renderPass, const vk::VkImageView colorAttachment, const deUint32 width, const deUint32 height, const deUint32 layers);
 vk::VkImageMemoryBarrier               makeImageMemoryBarrier          (const vk::VkAccessFlags srcAccessMask, const vk::VkAccessFlags dstAccessMask, const vk::VkImageLayout oldLayout, const vk::VkImageLayout newLayout, const vk::VkImage image, const vk::VkImageSubresourceRange subresourceRange);
@@ -187,6 +188,8 @@ void                                                        submitCommandsAndWait           (const vk::DeviceInterface& vk, const vk::VkDe
 
 bool                                                   compareWithFileImage            (Context& context, const tcu::ConstPixelBufferAccess& resultImage, std::string name);
 
+void                                                   fillBuffer                                      (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::Allocation& alloc, const vk::VkDeviceSize size, const vk::VkDeviceSize offset, const vk::VkFormat format, const tcu::Vec4& color);
+void                                                   fillBuffer                                      (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::Allocation& alloc, const vk::VkDeviceSize size, const vk::VkDeviceSize offset, const vk::VkFormat format, const float depth);
 void                                                   zeroBuffer                                      (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::Allocation& alloc, const vk::VkDeviceSize size);
 
 void                                                   checkGeometryShaderSupport      (const vk::InstanceInterface& vki, const vk::VkPhysicalDevice physDevice, const int numGeometryShaderInvocations = 0);
index 86ac606..64f0707 100755 (executable)
@@ -251464,6 +251464,7 @@ dEQP-VK.geometry.layered.1d_array.render_different_content
 dEQP-VK.geometry.layered.1d_array.fragment_layer
 dEQP-VK.geometry.layered.1d_array.invocation_per_layer
 dEQP-VK.geometry.layered.1d_array.multiple_layers_per_invocation
+dEQP-VK.geometry.layered.1d_array.readback
 dEQP-VK.geometry.layered.2d_array.render_to_default_layer
 dEQP-VK.geometry.layered.2d_array.render_to_one
 dEQP-VK.geometry.layered.2d_array.render_to_all
@@ -251471,6 +251472,7 @@ dEQP-VK.geometry.layered.2d_array.render_different_content
 dEQP-VK.geometry.layered.2d_array.fragment_layer
 dEQP-VK.geometry.layered.2d_array.invocation_per_layer
 dEQP-VK.geometry.layered.2d_array.multiple_layers_per_invocation
+dEQP-VK.geometry.layered.2d_array.readback
 dEQP-VK.geometry.layered.cube.render_to_default_layer
 dEQP-VK.geometry.layered.cube.render_to_one
 dEQP-VK.geometry.layered.cube.render_to_all
@@ -251478,6 +251480,7 @@ dEQP-VK.geometry.layered.cube.render_different_content
 dEQP-VK.geometry.layered.cube.fragment_layer
 dEQP-VK.geometry.layered.cube.invocation_per_layer
 dEQP-VK.geometry.layered.cube.multiple_layers_per_invocation
+dEQP-VK.geometry.layered.cube.readback
 dEQP-VK.geometry.layered.cube_array.render_to_default_layer
 dEQP-VK.geometry.layered.cube_array.render_to_one
 dEQP-VK.geometry.layered.cube_array.render_to_all
@@ -251485,6 +251488,7 @@ dEQP-VK.geometry.layered.cube_array.render_different_content
 dEQP-VK.geometry.layered.cube_array.fragment_layer
 dEQP-VK.geometry.layered.cube_array.invocation_per_layer
 dEQP-VK.geometry.layered.cube_array.multiple_layers_per_invocation
+dEQP-VK.geometry.layered.cube_array.readback
 dEQP-VK.geometry.layered.3d.render_to_default_layer
 dEQP-VK.geometry.layered.3d.render_to_one
 dEQP-VK.geometry.layered.3d.render_to_all
@@ -251492,6 +251496,7 @@ dEQP-VK.geometry.layered.3d.render_different_content
 dEQP-VK.geometry.layered.3d.fragment_layer
 dEQP-VK.geometry.layered.3d.invocation_per_layer
 dEQP-VK.geometry.layered.3d.multiple_layers_per_invocation
+dEQP-VK.geometry.layered.3d.readback
 dEQP-VK.geometry.instanced.draw_1_instances_1_geometry_invocations
 dEQP-VK.geometry.instanced.draw_1_instances_2_geometry_invocations
 dEQP-VK.geometry.instanced.draw_1_instances_8_geometry_invocations