Fixed incorrect calculation of GCD
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / api / vktApiImageClearingTests.cpp
index 4f77a56..d7e7260 100644 (file)
@@ -5,24 +5,17 @@
  * Copyright (c) 2016 The Khronos Group Inc.
  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and/or associated documentation files (the
- * "Materials"), to deal in the Materials without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Materials, and to
- * permit persons to whom the Materials are furnished to do so, subject to
- * the following conditions:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- * The above copyright notice(s) and this permission notice shall be included
- * in all copies or substantial portions of the Materials.
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  *
  *//*!
  * \file
 
 #include "deRandom.hpp"
 #include "deMath.h"
+#include "deSTLUtil.hpp"
 #include "deStringUtil.hpp"
 #include "deUniquePtr.hpp"
 #include "deArrayUtil.hpp"
+#include "deInt32.h"
 #include "vkImageUtil.hpp"
 #include "vkMemUtil.hpp"
 #include "vktTestCase.hpp"
 #include "vktTestCaseUtil.hpp"
+#include "vktTestGroupUtil.hpp"
 #include "vkQueryUtil.hpp"
 #include "vkRefUtil.hpp"
 #include "vkTypeUtil.hpp"
@@ -52,6 +48,7 @@
 #include "tcuTestLog.hpp"
 #include "tcuVectorUtil.hpp"
 #include <sstream>
+#include <numeric>
 
 namespace vkt
 {
@@ -65,6 +62,177 @@ using namespace tcu;
 namespace
 {
 
+enum AllocationKind
+{
+       ALLOCATION_KIND_SUBALLOCATED,
+       ALLOCATION_KIND_DEDICATED,
+};
+
+
+de::MovePtr<Allocation> allocateBuffer (const InstanceInterface&       vki,
+                                                                               const DeviceInterface&          vkd,
+                                                                               const VkPhysicalDevice&         physDevice,
+                                                                               const VkDevice                          device,
+                                                                               const VkBuffer&                         buffer,
+                                                                               const MemoryRequirement         requirement,
+                                                                               Allocator&                                      allocator,
+                                                                               AllocationKind                          allocationKind)
+{
+       switch (allocationKind)
+       {
+               case ALLOCATION_KIND_SUBALLOCATED:
+               {
+                       const VkMemoryRequirements memoryRequirements = getBufferMemoryRequirements(vkd, device, buffer);
+
+                       return allocator.allocate(memoryRequirements, requirement);
+               }
+
+               case ALLOCATION_KIND_DEDICATED:
+               {
+                       return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement);
+               }
+
+               default:
+               {
+                       TCU_THROW(InternalError, "Invalid allocation kind");
+               }
+       }
+}
+
+de::MovePtr<Allocation> allocateImage (const InstanceInterface&                vki,
+                                                                          const DeviceInterface&               vkd,
+                                                                          const VkPhysicalDevice&              physDevice,
+                                                                          const VkDevice                               device,
+                                                                          const VkImage&                               image,
+                                                                          const MemoryRequirement              requirement,
+                                                                          Allocator&                                   allocator,
+                                                                          AllocationKind                               allocationKind)
+{
+       switch (allocationKind)
+       {
+               case ALLOCATION_KIND_SUBALLOCATED:
+               {
+                       const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vkd, device, image);
+
+                       return allocator.allocate(memoryRequirements, requirement);
+               }
+
+               case ALLOCATION_KIND_DEDICATED:
+               {
+                       return allocateDedicated(vki, vkd, physDevice, device, image, requirement);
+               }
+
+               default:
+               {
+                       TCU_THROW(InternalError, "Invalid allocation kind");
+               }
+       }
+}
+
+VkExtent3D getMipLevelExtent (VkExtent3D baseExtent, const deUint32 mipLevel)
+{
+       baseExtent.width        = std::max(baseExtent.width  >> mipLevel, 1u);
+       baseExtent.height       = std::max(baseExtent.height >> mipLevel, 1u);
+       baseExtent.depth        = std::max(baseExtent.depth  >> mipLevel, 1u);
+       return baseExtent;
+}
+
+deUint32 getNumMipLevels (const VkExtent3D& baseExtent, const deUint32 maxMipLevels)
+{
+       const deUint32 widestEdge = std::max(std::max(baseExtent.width, baseExtent.height), baseExtent.depth);
+       return std::min(static_cast<deUint32>(deFloatLog2(static_cast<float>(widestEdge))) + 1u, maxMipLevels);
+}
+
+deUint32 greatestCommonDivisor (const deUint32 a, const deUint32 b)
+{
+       /* Find GCD */
+       deUint32 temp;
+       deUint32 x=a;
+       deUint32 y=b;
+
+       while (x%y != 0)
+       {
+               temp = y;
+               y = x%y;
+               x = temp;
+       }
+       return y;
+}
+
+deUint32 lowestCommonMultiple (const deUint32 a, const deUint32 b)
+{
+       return (a*b)/greatestCommonDivisor(a,b);
+}
+
+std::vector<deUint32> getImageMipLevelSizes (const deUint32 pixelSize, const VkExtent3D& baseExtent, const deUint32 numMipLevels, const deUint32 perLevelAlignment = 1u)
+{
+       std::vector<deUint32> results(numMipLevels);
+
+       for (deUint32 mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
+       {
+               const VkExtent3D extent = getMipLevelExtent(baseExtent, mipLevel);
+               results[mipLevel] = static_cast<deUint32>(extent.width * extent.height * extent.depth * pixelSize);
+               results[mipLevel] = ((results[mipLevel] + perLevelAlignment-1) / perLevelAlignment) * perLevelAlignment;
+       }
+
+       return results;
+}
+
+struct LayerRange
+{
+       deUint32 baseArrayLayer;
+       deUint32 layerCount;
+};
+
+inline bool isInClearRange (const UVec4& clearCoords, const deUint32 x, const deUint32 y, deUint32 arrayLayer = 0, tcu::Maybe<LayerRange> imageViewLayerRange = tcu::Maybe<LayerRange>(), tcu::Maybe<LayerRange> attachmentClearLayerRange = tcu::Maybe<LayerRange>())
+{
+       if (attachmentClearLayerRange)
+       {
+               // Only layers in range passed to clear command are cleared
+
+               const deUint32 clearBaseLayer = (imageViewLayerRange ? imageViewLayerRange->baseArrayLayer : 0) + attachmentClearLayerRange->baseArrayLayer;
+
+               if ((arrayLayer < clearBaseLayer) || (arrayLayer >= (clearBaseLayer + attachmentClearLayerRange->layerCount)))
+               {
+                       return false;
+               }
+       }
+
+       if (clearCoords == UVec4())
+       {
+               return true;
+       }
+
+       //! Check if a point lies in a cross-like area.
+       return !((x <  clearCoords[0] && y <  clearCoords[1]) ||
+                        (x <  clearCoords[0] && y >= clearCoords[3]) ||
+                        (x >= clearCoords[2] && y <  clearCoords[1]) ||
+                        (x >= clearCoords[2] && y >= clearCoords[3]));
+}
+
+inline bool isInInitialClearRange (bool isAttachmentformat, deUint32 mipLevel, deUint32 arrayLayer, LayerRange imageViewLayerRange)
+{
+       if (!isAttachmentformat)
+       {
+               // initial clear is done using renderpass load op - does not apply for non-renderable formats
+               return false;
+       }
+
+       if (mipLevel > 0)
+       {
+               // intial clear is done using FB bound to level 0 only
+               return false;
+       }
+
+       // Only layers in range bound to framebuffer are cleared to initial color
+       if ((arrayLayer < imageViewLayerRange.baseArrayLayer) || (arrayLayer >= (imageViewLayerRange.baseArrayLayer + imageViewLayerRange.layerCount)))
+       {
+               return false;
+       }
+
+       return true;
+}
+
 // This method is copied from the vktRenderPassTests.cpp. It should be moved to a common place.
 int calcFloatDiff (float a, float b)
 {
@@ -288,11 +456,16 @@ bool comparePixelToColorClearValue (const ConstPixelBufferAccess& access,
 
 struct TestParams
 {
+       bool                    useSingleMipLevel;      //!< only mip level 0, otherwise up to maxMipLevels
        VkImageType             imageType;
        VkFormat                imageFormat;
        VkExtent3D              imageExtent;
+       deUint32        imageLayerCount;
+       LayerRange      imageViewLayerRange;
        VkClearValue    initValue;
-       VkClearValue    clearValue;
+       VkClearValue    clearValue[2];          //!< the second value is used with more than one mip map
+       LayerRange              clearLayerRange;
+       AllocationKind  allocationKind;
 };
 
 class ImageClearingTestInstance : public vkt::TestInstance
@@ -303,10 +476,10 @@ public:
 
        Move<VkCommandPool>                                     createCommandPool                               (VkCommandPoolCreateFlags commandPoolCreateFlags) const;
        Move<VkCommandBuffer>                           allocatePrimaryCommandBuffer    (VkCommandPool commandPool) const;
-       Move<VkImage>                                           createImage                                             (VkImageType imageType, VkFormat format, VkExtent3D extent, VkImageUsageFlags usage) const;
-       Move<VkImageView>                                       createImageView                                 (VkImage image, VkImageViewType viewType, VkFormat format, VkImageAspectFlags aspectMask) const;
+       Move<VkImage>                                           createImage                                             (VkImageType imageType, VkFormat format, VkExtent3D extent, deUint32 arrayLayerCount, VkImageUsageFlags usage) const;
+       Move<VkImageView>                                       createImageView                                 (VkImage image, VkImageViewType viewType, VkFormat format, VkImageAspectFlags aspectMask, LayerRange layerRange) const;
        Move<VkRenderPass>                                      createRenderPass                                (VkFormat format) const;
-       Move<VkFramebuffer>                                     createFrameBuffer                               (VkImageView imageView, VkRenderPass renderPass, deUint32 imageWidth, deUint32 imageHeight) const;
+       Move<VkFramebuffer>                                     createFrameBuffer                               (VkImageView imageView, VkRenderPass renderPass, deUint32 imageWidth, deUint32 imageHeight, deUint32 imageLayersCount) const;
 
        void                                                            beginCommandBuffer                              (VkCommandBufferUsageFlags usageFlags) const;
        void                                                            endCommandBuffer                                (void) const;
@@ -314,15 +487,22 @@ public:
        void                                                            beginRenderPass                                 (VkSubpassContents content, VkClearValue clearValue) const;
 
        void                                                            pipelineImageBarrier                    (VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const;
-       de::MovePtr<TextureLevel>                       readImage                                               (VkImageAspectFlags aspectMask) const;
+       de::MovePtr<TextureLevelPyramid>        readImage                                               (VkImageAspectFlags aspectMask, deUint32 baseLayer) const;
+       tcu::TestStatus                                         verifyResultImage                               (const std::string& successMessage, const UVec4& clearCoords = UVec4()) const;
 
 protected:
-       VkImageViewType                                         getCorrespondingImageViewType   (VkImageType imageType) const;
+       enum ViewType
+       {
+               VIEW_TYPE_SINGLE,
+               VIEW_TYPE_ARRAY
+       };
+       VkImageViewType                                         getCorrespondingImageViewType   (VkImageType imageType, ViewType viewType) const;
        VkImageUsageFlags                                       getImageUsageFlags                              (VkFormat format) const;
        VkImageAspectFlags                                      getImageAspectFlags                             (VkFormat format) const;
        bool                                                            getIsAttachmentFormat                   (VkFormat format) const;
        bool                                                            getIsStencilFormat                              (VkFormat format) const;
        bool                                                            getIsDepthFormat                                (VkFormat format) const;
+       VkImageFormatProperties                         getImageFormatProperties                (void) const;
        de::MovePtr<Allocation>                         allocateAndBindImageMemory              (VkImage image) const;
 
        const TestParams&                                       m_params;
@@ -336,6 +516,9 @@ protected:
        const bool                                                      m_isAttachmentFormat;
        const VkImageUsageFlags                         m_imageUsageFlags;
        const VkImageAspectFlags                        m_imageAspectFlags;
+       const VkImageFormatProperties           m_imageFormatProperties;
+       const deUint32                                          m_imageMipLevels;
+       const deUint32                                          m_thresholdMipLevel;
 
        Unique<VkCommandPool>                           m_commandPool;
        Unique<VkCommandBuffer>                         m_commandBuffer;
@@ -359,37 +542,53 @@ ImageClearingTestInstance::ImageClearingTestInstance (Context& context, const Te
        , m_isAttachmentFormat          (getIsAttachmentFormat(params.imageFormat))
        , m_imageUsageFlags                     (getImageUsageFlags(params.imageFormat))
        , m_imageAspectFlags            (getImageAspectFlags(params.imageFormat))
+       , m_imageFormatProperties       (getImageFormatProperties())
+       , m_imageMipLevels                      (params.useSingleMipLevel ? 1u : getNumMipLevels(params.imageExtent, m_imageFormatProperties.maxMipLevels))
+       , m_thresholdMipLevel           (std::max(m_imageMipLevels / 2u, 1u))
        , m_commandPool                         (createCommandPool(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT))
        , m_commandBuffer                       (allocatePrimaryCommandBuffer(*m_commandPool))
 
        , m_image                                       (createImage(params.imageType,
                                                                                         params.imageFormat,
                                                                                         params.imageExtent,
+                                                                                        params.imageLayerCount,
                                                                                         m_imageUsageFlags))
 
        , m_imageMemory                         (allocateAndBindImageMemory(*m_image))
        , m_imageView                           (m_isAttachmentFormat ? createImageView(*m_image,
-                                                                                                getCorrespondingImageViewType(params.imageType),
+                                                                                                getCorrespondingImageViewType(params.imageType, params.imageLayerCount > 1u ? VIEW_TYPE_ARRAY : VIEW_TYPE_SINGLE),
                                                                                                 params.imageFormat,
-                                                                                                m_imageAspectFlags) : vk::Move<VkImageView>())
+                                                                                                m_imageAspectFlags,
+                                                                                                params.imageViewLayerRange) : vk::Move<VkImageView>())
 
        , m_renderPass                          (m_isAttachmentFormat ? createRenderPass(params.imageFormat) : vk::Move<vk::VkRenderPass>())
-       , m_frameBuffer                         (m_isAttachmentFormat ? createFrameBuffer(*m_imageView, *m_renderPass, params.imageExtent.width, params.imageExtent.height) : vk::Move<vk::VkFramebuffer>())
+       , m_frameBuffer                         (m_isAttachmentFormat ? createFrameBuffer(*m_imageView, *m_renderPass, params.imageExtent.width, params.imageExtent.height, params.imageViewLayerRange.layerCount) : vk::Move<vk::VkFramebuffer>())
 {
+       if (m_params.allocationKind == ALLOCATION_KIND_DEDICATED)
+       {
+               const std::string extensionName("VK_KHR_dedicated_allocation");
+
+               if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), extensionName))
+                       TCU_THROW(NotSupportedError, std::string(extensionName + " is not supported").c_str());
+       }
 }
 
-VkImageViewType ImageClearingTestInstance::getCorrespondingImageViewType (VkImageType imageType) const
+VkImageViewType ImageClearingTestInstance::getCorrespondingImageViewType (VkImageType imageType, ViewType viewType) const
 {
        switch (imageType)
        {
-               case VK_IMAGE_TYPE_1D:
-                       return VK_IMAGE_VIEW_TYPE_1D;
-               case VK_IMAGE_TYPE_2D:
-                       return VK_IMAGE_VIEW_TYPE_2D;
-               case VK_IMAGE_TYPE_3D:
-                       return VK_IMAGE_VIEW_TYPE_3D;
-               default:
-                       DE_FATAL("Unknown image type!");
+       case VK_IMAGE_TYPE_1D:
+               return (viewType == VIEW_TYPE_ARRAY) ?  VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D;
+       case VK_IMAGE_TYPE_2D:
+               return (viewType == VIEW_TYPE_ARRAY) ?  VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
+       case VK_IMAGE_TYPE_3D:
+               if (viewType != VIEW_TYPE_SINGLE)
+               {
+                       DE_FATAL("Cannot have 3D image array");
+               }
+               return VK_IMAGE_VIEW_TYPE_3D;
+       default:
+               DE_FATAL("Unknown image type!");
        }
 
        return VK_IMAGE_VIEW_TYPE_2D;
@@ -452,53 +651,37 @@ bool ImageClearingTestInstance::getIsDepthFormat (VkFormat format) const
        return false;
 }
 
+VkImageFormatProperties ImageClearingTestInstance::getImageFormatProperties (void) const
+{
+       VkImageFormatProperties properties;
+       const VkResult result = m_vki.getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(), m_params.imageFormat, m_params.imageType,
+                                                                                                                                                VK_IMAGE_TILING_OPTIMAL, m_imageUsageFlags, (VkImageCreateFlags)0, &properties);
+
+       if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
+               TCU_THROW(NotSupportedError, "Format not supported");
+       else
+               return properties;
+}
+
 de::MovePtr<Allocation> ImageClearingTestInstance::allocateAndBindImageMemory (VkImage image) const
 {
-       de::MovePtr<Allocation> imageMemory     (m_allocator.allocate(getImageMemoryRequirements(m_vkd, m_device, image), MemoryRequirement::Any));
+       de::MovePtr<Allocation> imageMemory     (allocateImage(m_vki, m_vkd, m_context.getPhysicalDevice(), m_device, image, MemoryRequirement::Any, m_allocator, m_params.allocationKind));
        VK_CHECK(m_vkd.bindImageMemory(m_device, image, imageMemory->getMemory(), imageMemory->getOffset()));
        return imageMemory;
 }
 
 Move<VkCommandPool> ImageClearingTestInstance::createCommandPool (VkCommandPoolCreateFlags commandPoolCreateFlags) const
 {
-       const VkCommandPoolCreateInfo                   cmdPoolCreateInfo               =
-       {
-               VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,                                     // VkStructureType             sType;
-               DE_NULL,                                                                                                        // const void*                 pNext;
-               commandPoolCreateFlags,                                                                         // VkCommandPoolCreateFlags    flags;
-               m_queueFamilyIndex                                                                                      // deUint32                    queueFamilyIndex;
-       };
-
-       return vk::createCommandPool(m_vkd, m_device, &cmdPoolCreateInfo, DE_NULL);
+       return vk::createCommandPool(m_vkd, m_device, commandPoolCreateFlags, m_queueFamilyIndex);
 }
 
 Move<VkCommandBuffer> ImageClearingTestInstance::allocatePrimaryCommandBuffer (VkCommandPool commandPool) const
 {
-       const VkCommandBufferAllocateInfo               cmdBufferAllocateInfo   =
-       {
-               VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,                         // VkStructureType             sType;
-               DE_NULL,                                                                                                        // const void*                 pNext;
-               commandPool,                                                                                            // VkCommandPool               commandPool;
-               VK_COMMAND_BUFFER_LEVEL_PRIMARY,                                                        // VkCommandBufferLevel        level;
-               1                                                                                                                       // deUint32                    commandBufferCount;
-       };
-
-       return vk::allocateCommandBuffer(m_vkd, m_device, &cmdBufferAllocateInfo);
+       return vk::allocateCommandBuffer(m_vkd, m_device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
 }
 
-Move<VkImage> ImageClearingTestInstance::createImage (VkImageType imageType, VkFormat format, VkExtent3D extent, VkImageUsageFlags usage) const
+Move<VkImage> ImageClearingTestInstance::createImage (VkImageType imageType, VkFormat format, VkExtent3D extent, deUint32 arrayLayerCount, VkImageUsageFlags usage) const
 {
-       VkImageFormatProperties properties;
-       if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
-                                                                                                                                                                format,
-                                                                                                                                                                imageType,
-                                                                                                                                                                VK_IMAGE_TILING_OPTIMAL,
-                                                                                                                                                                usage, 0,
-                                                                                                                                                                &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
-       {
-               TCU_THROW(NotSupportedError, "Format not supported");
-       }
-
        const VkImageCreateInfo                                 imageCreateInfo                 =
        {
                VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType                      sType;
@@ -507,13 +690,13 @@ Move<VkImage> ImageClearingTestInstance::createImage (VkImageType imageType, VkF
                imageType,                                                                      // VkImageType                          imageType;
                format,                                                                         // VkFormat                                     format;
                extent,                                                                         // VkExtent3D                           extent;
-               1,                                                                                      // deUint32                                     mipLevels;
-               1,                                                                                      // deUint32                                     arrayLayers;
+               m_imageMipLevels,                                                       // deUint32                                     mipLevels;
+               arrayLayerCount,                                                        // deUint32                                     arrayLayers;
                VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits        samples;
                VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling                        tiling;
                usage,                                                                          // VkImageUsageFlags            usage;
                VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                        sharingMode;
-               1                                                                                     // deUint32                                     queueFamilyIndexCount;
+               1u,                                                                                     // deUint32                                     queueFamilyIndexCount;
                &m_queueFamilyIndex,                                            // const deUint32*                      pQueueFamilyIndices;
                VK_IMAGE_LAYOUT_UNDEFINED                                       // VkImageLayout                        initialLayout;
        };
@@ -521,7 +704,7 @@ Move<VkImage> ImageClearingTestInstance::createImage (VkImageType imageType, VkF
        return vk::createImage(m_vkd, m_device, &imageCreateInfo, DE_NULL);
 }
 
-Move<VkImageView> ImageClearingTestInstance::createImageView (VkImage image, VkImageViewType viewType, VkFormat format, VkImageAspectFlags aspectMask) const
+Move<VkImageView> ImageClearingTestInstance::createImageView (VkImage image, VkImageViewType viewType, VkFormat format, VkImageAspectFlags aspectMask, LayerRange layerRange) const
 {
        const VkImageViewCreateInfo                             imageViewCreateInfo             =
        {
@@ -541,9 +724,9 @@ Move<VkImageView> ImageClearingTestInstance::createImageView (VkImage image, VkI
                        aspectMask,                                                                     // VkImageAspectFlags                   aspectMask;
                        0u,                                                                                     // deUint32                                             baseMipLevel;
                        1u,                                                                                     // deUint32                                             mipLevels;
-                       0u,                                                                                     // deUint32                                             baseArrayLayer;
-                       1u,                                                                                     // deUint32                                             arraySize;
-               },                                                                                      // VkImageSubresourceRange              subresourceRange;
+                       layerRange.baseArrayLayer,                                      // deUint32                                             baseArrayLayer;
+                       layerRange.layerCount,                                          // deUint32                                             arraySize;
+               },                                                                                              // VkImageSubresourceRange              subresourceRange;
        };
 
        return vk::createImageView(m_vkd, m_device, &imageViewCreateInfo, DE_NULL);
@@ -629,7 +812,7 @@ Move<VkRenderPass> ImageClearingTestInstance::createRenderPass (VkFormat format)
        return vk::createRenderPass(m_vkd, m_device, &renderPassCreateInfo, DE_NULL);
 }
 
-Move<VkFramebuffer> ImageClearingTestInstance::createFrameBuffer (VkImageView imageView, VkRenderPass renderPass, deUint32 imageWidth, deUint32 imageHeight) const
+Move<VkFramebuffer> ImageClearingTestInstance::createFrameBuffer (VkImageView imageView, VkRenderPass renderPass, deUint32 imageWidth, deUint32 imageHeight, deUint32 imageLayersCount) const
 {
        const VkImageView                                               attachmentViews[1]              =
        {
@@ -646,7 +829,7 @@ Move<VkFramebuffer> ImageClearingTestInstance::createFrameBuffer (VkImageView im
                attachmentViews,                                                        // const VkImageView*           pAttachments;
                imageWidth,                                                                     // deUint32                                     width;
                imageHeight,                                                            // deUint32                                     height;
-               1u,                                                                                     // deUint32                                     layers;
+               imageLayersCount,                                                       // deUint32                                     layers;
        };
 
        return createFramebuffer(m_vkd, m_device, &framebufferCreateInfo, DE_NULL);
@@ -672,14 +855,7 @@ void ImageClearingTestInstance::endCommandBuffer (void) const
 
 void ImageClearingTestInstance::submitCommandBuffer (void) const
 {
-       const VkFenceCreateInfo fenceCreateInfo                                                 =
-       {
-               VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,                                    // VkStructureType       sType;
-               DE_NULL,                                                                                                // const void*           pNext;
-               0u                                                                                                              // VkFenceCreateFlags    flags;
-       };
-
-       const Unique<VkFence>                                   fence                                   (createFence(m_vkd, m_device, &fenceCreateInfo));
+       const Unique<VkFence>                                   fence                                   (createFence(m_vkd, m_device));
 
        const VkSubmitInfo                                              submitInfo                              =
        {
@@ -699,19 +875,8 @@ void ImageClearingTestInstance::submitCommandBuffer (void) const
        VK_CHECK(m_vkd.waitForFences(m_device, 1, &fence.get(), VK_TRUE, ~0ull));
 }
 
-
 void ImageClearingTestInstance::pipelineImageBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const
 {
-
-       const VkImageSubresourceRange   subResourcerange        =
-       {
-               m_imageAspectFlags,                             // VkImageAspectFlags   aspectMask;
-               0,                                                              // deUint32                             baseMipLevel;
-               1,                                                              // deUint32                             levelCount;
-               0,                                                              // deUint32                             baseArrayLayer;
-               1                                                               // deUint32                             layerCount;
-       };
-
        const VkImageMemoryBarrier              imageBarrier    =
        {
                VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
@@ -723,25 +888,36 @@ void ImageClearingTestInstance::pipelineImageBarrier(VkPipelineStageFlags srcSta
                VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
                VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     destQueueFamilyIndex;
                *m_image,                                                                       // VkImage                                      image;
-               subResourcerange                                                        // VkImageSubresourceRange      subresourceRange;
+               {
+                       m_imageAspectFlags,                                                     // VkImageAspectFlags   aspectMask;
+                       0u,                                                                                     // deUint32                             baseMipLevel;
+                       VK_REMAINING_MIP_LEVELS,                                        // deUint32                             levelCount;
+                       0u,                                                                                     // deUint32                             baseArrayLayer;
+                       VK_REMAINING_ARRAY_LAYERS,                                      // deUint32                             layerCount;
+               },                                                                                      // VkImageSubresourceRange      subresourceRange;
        };
 
        m_vkd.cmdPipelineBarrier(*m_commandBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier);
 }
 
-
-de::MovePtr<TextureLevel> ImageClearingTestInstance::readImage (VkImageAspectFlags aspectMask) const
+de::MovePtr<TextureLevelPyramid> ImageClearingTestInstance::readImage (VkImageAspectFlags aspectMask, deUint32 arrayLayer) const
 {
-       Move<VkBuffer>                                  buffer;
-       de::MovePtr<Allocation>                 bufferAlloc;
+       const TextureFormat                                     tcuFormat               = aspectMask == VK_IMAGE_ASPECT_COLOR_BIT ? mapVkFormat(m_params.imageFormat) :
+                                                                                                                 aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT ? getDepthCopyFormat(m_params.imageFormat) :
+                                                                                                                 aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT ? getStencilCopyFormat(m_params.imageFormat) :
+                                                                                                                 TextureFormat();
+       const deUint32                                          pixelSize               = getPixelSize(tcuFormat);
+       deUint32                                                        alignment               = 4;    // subsequent mip levels aligned to 4 bytes
+
+       if (!getIsDepthFormat(m_params.imageFormat) && !getIsStencilFormat(m_params.imageFormat))
+               alignment = lowestCommonMultiple(pixelSize, alignment); // alignment must be multiple of pixel size, if not D/S.
 
-       const TextureFormat                             tcuFormat               = aspectMask == VK_IMAGE_ASPECT_COLOR_BIT ? mapVkFormat(m_params.imageFormat) :
-                                                                                                         aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT ? getDepthCopyFormat(m_params.imageFormat) :
-                                                                                                         aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT ? getStencilCopyFormat(m_params.imageFormat) :
-                                                                                                         TextureFormat();
+       const std::vector<deUint32>                     mipLevelSizes   = getImageMipLevelSizes(pixelSize, m_params.imageExtent, m_imageMipLevels, alignment);
+       const VkDeviceSize                                      imageTotalSize  = std::accumulate(mipLevelSizes.begin(), mipLevelSizes.end(), 0u);
 
-       const VkDeviceSize                              pixelDataSize   = m_params.imageExtent.width * m_params.imageExtent.height * m_params.imageExtent.depth * tcuFormat.getPixelSize();
-       de::MovePtr<TextureLevel>               result                  (new TextureLevel(tcuFormat, m_params.imageExtent.width, m_params.imageExtent.height, m_params.imageExtent.depth));
+       de::MovePtr<TextureLevelPyramid>        result                  (new TextureLevelPyramid(tcuFormat, m_imageMipLevels));
+       Move<VkBuffer>                                          buffer;
+       de::MovePtr<Allocation>                         bufferAlloc;
 
        // Create destination buffer
        {
@@ -750,7 +926,7 @@ de::MovePtr<TextureLevel> ImageClearingTestInstance::readImage (VkImageAspectFla
                        VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
                        DE_NULL,                                                                        // const void*                  pNext;
                        0u,                                                                                     // VkBufferCreateFlags  flags;
-                       pixelDataSize,                                                          // VkDeviceSize                 size;
+                       imageTotalSize,                                                         // VkDeviceSize                 size;
                        VK_BUFFER_USAGE_TRANSFER_DST_BIT,                       // VkBufferUsageFlags   usage;
                        VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
                        0u,                                                                                     // deUint32                             queueFamilyIndexCount;
@@ -758,7 +934,7 @@ de::MovePtr<TextureLevel> ImageClearingTestInstance::readImage (VkImageAspectFla
                };
 
                buffer          = createBuffer(m_vkd, m_device, &bufferParams);
-               bufferAlloc     = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, m_device, *buffer), MemoryRequirement::HostVisible);
+               bufferAlloc     = allocateBuffer(m_vki, m_vkd, m_context.getPhysicalDevice(), m_device, *buffer, MemoryRequirement::HostVisible, m_allocator, m_params.allocationKind);
                VK_CHECK(m_vkd.bindBufferMemory(m_device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
        }
 
@@ -774,62 +950,174 @@ de::MovePtr<TextureLevel> ImageClearingTestInstance::readImage (VkImageAspectFla
                VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     dstQueueFamilyIndex;
                *buffer,                                                                        // VkBuffer                     buffer;
                0u,                                                                                     // VkDeviceSize         offset;
-               pixelDataSize                                                           // VkDeviceSize         size;
+               imageTotalSize,                                                         // VkDeviceSize         size;
        };
 
        // Copy image to buffer
-
-       const VkBufferImageCopy                 copyRegion              =
+       std::vector<VkBufferImageCopy> copyRegions;
        {
-               0u,                                                                                             // VkDeviceSize                         bufferOffset;
-               m_params.imageExtent.width,                                             // deUint32                                     bufferRowLength;
-               m_params.imageExtent.height,                                    // deUint32                                     bufferImageHeight;
-               { aspectMask, 0u, 0u, 1u },                                             // VkImageSubresourceLayers     imageSubresource;
-               { 0, 0, 0 },                                                                    // VkOffset3D                           imageOffset;
-               m_params.imageExtent                                                    // VkExtent3D                           imageExtent;
-       };
+               deUint32 offset = 0u;
+               for (deUint32 mipLevel = 0; mipLevel < m_imageMipLevels; ++mipLevel)
+               {
+                       const VkExtent3D                extent  = getMipLevelExtent(m_params.imageExtent, mipLevel);
+                       const VkBufferImageCopy region  =
+                       {
+                               offset,                                                                         // VkDeviceSize                         bufferOffset;
+                               0u,                                                                                     // deUint32                                     bufferRowLength;
+                               0u,                                                                                     // deUint32                                     bufferImageHeight;
+                               { aspectMask, mipLevel, arrayLayer, 1u },       // VkImageSubresourceLayers     imageSubresource;
+                               { 0, 0, 0 },                                                            // VkOffset3D                           imageOffset;
+                               extent                                                                          // VkExtent3D                           imageExtent;
+                       };
+                       copyRegions.push_back(region);
+                       offset += mipLevelSizes[mipLevel];
+               }
+       }
 
        beginCommandBuffer(0);
 
        pipelineImageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
                                                 VK_PIPELINE_STAGE_TRANSFER_BIT,
-                                                VK_ACCESS_TRANSFER_WRITE_BIT |
-                                                VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
-                                                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+                                                VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
                                                 VK_ACCESS_TRANSFER_READ_BIT,
                                                 VK_IMAGE_LAYOUT_GENERAL,
                                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
 
-       m_vkd.cmdCopyImageToBuffer(*m_commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1, &copyRegion);
+       m_vkd.cmdCopyImageToBuffer(*m_commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, static_cast<deUint32>(copyRegions.size()), &copyRegions[0]);
        m_vkd.cmdPipelineBarrier(*m_commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
 
        pipelineImageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
                                                 VK_PIPELINE_STAGE_TRANSFER_BIT,
-
-                                                VK_ACCESS_TRANSFER_READ_BIT |
-                                                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
-                                                VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
-
-                                                VK_ACCESS_TRANSFER_READ_BIT |
-                                                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
-                                                VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
+                                                VK_ACCESS_TRANSFER_READ_BIT,
+                                                VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
                                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                                                 VK_IMAGE_LAYOUT_GENERAL);
 
        endCommandBuffer();
-
        submitCommandBuffer();
 
-       invalidateMappedMemoryRange(m_vkd, m_device, bufferAlloc->getMemory(), bufferAlloc->getOffset(), pixelDataSize);
+       invalidateMappedMemoryRange(m_vkd, m_device, bufferAlloc->getMemory(), bufferAlloc->getOffset(), imageTotalSize);
 
-       copy(*result, ConstPixelBufferAccess(result->getFormat(), result->getSize(), bufferAlloc->getHostPtr()));
+       {
+               deUint32 offset = 0u;
+               for (deUint32 mipLevel = 0; mipLevel < m_imageMipLevels; ++mipLevel)
+               {
+                       const VkExtent3D        extent          = getMipLevelExtent(m_params.imageExtent, mipLevel);
+                       const void*                     pLevelData      = static_cast<const void*>(reinterpret_cast<deUint8*>(bufferAlloc->getHostPtr()) + offset);
+
+                       result->allocLevel(mipLevel, extent.width, extent.height, extent.depth);
+                       copy(result->getLevel(mipLevel), ConstPixelBufferAccess(result->getFormat(), result->getLevel(mipLevel).getSize(), pLevelData));
+
+                       offset += mipLevelSizes[mipLevel];
+               }
+       }
 
        return result;
 }
 
+tcu::TestStatus ImageClearingTestInstance::verifyResultImage (const std::string& successMessage, const UVec4& clearCoords) const
+{
+       DE_ASSERT((clearCoords == UVec4()) || m_params.imageExtent.depth == 1u);
+
+       if (getIsDepthFormat(m_params.imageFormat))
+       {
+               DE_ASSERT(m_imageMipLevels == 1u);
+
+               for (deUint32 arrayLayer = 0; arrayLayer < m_params.imageLayerCount; ++arrayLayer)
+               {
+                       de::MovePtr<TextureLevelPyramid>        image                   = readImage(VK_IMAGE_ASPECT_DEPTH_BIT, arrayLayer);
+                       std::string                                                     message;
+                       float                                                           depthValue;
+
+                       for (deUint32 y = 0; y < m_params.imageExtent.height; ++y)
+                       for (deUint32 x = 0; x < m_params.imageExtent.width; ++x)
+                       {
+                               if (isInClearRange(clearCoords, x, y, arrayLayer, m_params.imageViewLayerRange, m_params.clearLayerRange))
+                                       depthValue = m_params.clearValue[0].depthStencil.depth;
+                               else
+                               if (isInInitialClearRange(m_isAttachmentFormat, 0u /* mipLevel */, arrayLayer, m_params.imageViewLayerRange))
+                               {
+                                       depthValue = m_params.initValue.depthStencil.depth;
+                               }
+                               else
+                                       continue;
+
+                               if (!comparePixelToDepthClearValue(image->getLevel(0), x, y, depthValue, message))
+                                       return TestStatus::fail("Depth value mismatch! " + message);
+                       }
+               }
+       }
+
+       if (getIsStencilFormat(m_params.imageFormat))
+       {
+               DE_ASSERT(m_imageMipLevels == 1u);
+
+               for (deUint32 arrayLayer = 0; arrayLayer < m_params.imageLayerCount; ++arrayLayer)
+               {
+                       de::MovePtr<TextureLevelPyramid>        image                   = readImage(VK_IMAGE_ASPECT_STENCIL_BIT, arrayLayer);
+                       std::string                                                     message;
+                       deUint32                                                        stencilValue;
+
+                       for (deUint32 y = 0; y < m_params.imageExtent.height; ++y)
+                       for (deUint32 x = 0; x < m_params.imageExtent.width; ++x)
+                       {
+                               if (isInClearRange(clearCoords, x, y, arrayLayer, m_params.imageViewLayerRange, m_params.clearLayerRange))
+                                       stencilValue = m_params.clearValue[0].depthStencil.stencil;
+                               else
+                               if (isInInitialClearRange(m_isAttachmentFormat, 0u /* mipLevel */, arrayLayer, m_params.imageViewLayerRange))
+                               {
+                                       stencilValue = m_params.initValue.depthStencil.stencil;
+                               }
+                               else
+                                       continue;
+
+                               if (!comparePixelToStencilClearValue(image->getLevel(0), x, y, stencilValue, message))
+                                       return TestStatus::fail("Stencil value mismatch! " + message);
+                       }
+               }
+       }
+
+       if (!isDepthStencilFormat(m_params.imageFormat))
+       {
+               for (deUint32 arrayLayer = 0; arrayLayer < m_params.imageLayerCount; ++arrayLayer)
+               {
+                       de::MovePtr<TextureLevelPyramid>        image                   = readImage(VK_IMAGE_ASPECT_COLOR_BIT, arrayLayer);
+                       std::string                                                     message;
+                       const VkClearColorValue*                        pColorValue;
+
+                       for (deUint32 mipLevel = 0; mipLevel < m_imageMipLevels; ++mipLevel)
+                       {
+                               const int                       clearColorNdx   = (mipLevel < m_thresholdMipLevel ? 0 : 1);
+                               const VkExtent3D        extent                  = getMipLevelExtent(m_params.imageExtent, mipLevel);
+
+                               for (deUint32 z = 0; z < extent.depth;  ++z)
+                               for (deUint32 y = 0; y < extent.height; ++y)
+                               for (deUint32 x = 0; x < extent.width;  ++x)
+                               {
+                                       if (isInClearRange(clearCoords, x, y, arrayLayer, m_params.imageViewLayerRange, m_params.clearLayerRange))
+                                               pColorValue = &m_params.clearValue[clearColorNdx].color;
+                                       else
+                                       {
+                                               if (isInInitialClearRange(m_isAttachmentFormat, mipLevel, arrayLayer, m_params.imageViewLayerRange))
+                                               {
+                                                       pColorValue = &m_params.initValue.color;
+                                               }
+                                               else
+                                                       continue;
+                                       }
+                                       if (!comparePixelToColorClearValue(image->getLevel(mipLevel), x, y, z, *pColorValue, message))
+                                               return TestStatus::fail("Color value mismatch! " + message);
+                               }
+                       }
+               }
+       }
+
+       return TestStatus::pass(successMessage);
+}
+
 void ImageClearingTestInstance::beginRenderPass (VkSubpassContents content, VkClearValue clearValue) const
 {
-       const VkRenderPassBeginInfo             renderPassBeginInfo             =
+       const VkRenderPassBeginInfo renderPassBeginInfo =
        {
                VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                               // VkStructureType              sType;
                DE_NULL,                                                                                                // const void*                  pNext;
@@ -852,24 +1140,21 @@ void ImageClearingTestInstance::beginRenderPass (VkSubpassContents content, VkCl
 class ClearColorImageTestInstance : public ImageClearingTestInstance
 {
 public:
-                                                                       ClearColorImageTestInstance             (Context&                       context,
-                                                                                                                                        const TestParams&      testParams)
-                                                                               : ImageClearingTestInstance(context, testParams)
-                                                                       {}
-
-       virtual TestStatus                              iterate                                                 (void);
+                               ClearColorImageTestInstance     (Context& context, const TestParams& testParams) : ImageClearingTestInstance (context, testParams) {}
+       TestStatus      iterate                                         (void);
 };
 
 TestStatus ClearColorImageTestInstance::iterate (void)
 {
-       const VkImageSubresourceRange   subResourcerange        =
+       std::vector<VkImageSubresourceRange> subresourceRanges;
+
+       if (m_imageMipLevels == 1)
+               subresourceRanges.push_back(makeImageSubresourceRange(m_imageAspectFlags, 0u, 1u, m_params.clearLayerRange.baseArrayLayer, m_params.clearLayerRange.layerCount));
+       else
        {
-               m_imageAspectFlags,                             // VkImageAspectFlags   aspectMask;
-               0,                                                              // deUint32                             baseMipLevel;
-               1,                                                              // deUint32                             levelCount;
-               0,                                                              // deUint32                             baseArrayLayer;
-               1                                                               // deUint32                             layerCount;
-       };
+               subresourceRanges.push_back(makeImageSubresourceRange(m_imageAspectFlags,       0u,                                             m_thresholdMipLevel,            m_params.clearLayerRange.baseArrayLayer, m_params.clearLayerRange.layerCount));
+               subresourceRanges.push_back(makeImageSubresourceRange(m_imageAspectFlags,       m_thresholdMipLevel,    VK_REMAINING_MIP_LEVELS,        m_params.clearLayerRange.baseArrayLayer, m_params.clearLayerRange.layerCount));
+       }
 
        beginCommandBuffer(0);
 
@@ -889,16 +1174,17 @@ TestStatus ClearColorImageTestInstance::iterate (void)
                beginRenderPass(VK_SUBPASS_CONTENTS_INLINE, m_params.initValue);
                m_vkd.cmdEndRenderPass(*m_commandBuffer);
 
-               pipelineImageBarrier(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,                        // VkPipelineStageFlags         srcStageMask
-                       VK_PIPELINE_STAGE_TRANSFER_BIT,                         // VkPipelineStageFlags         dstStageMask
-                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags                        srcAccessMask
-                                                VK_ACCESS_TRANSFER_WRITE_BIT,                                  // VkAccessFlags                        dstAccessMask
-                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // VkImageLayout                        oldLayout;
-                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);                  // VkImageLayout                        newLayout;
+               pipelineImageBarrier(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,                // VkPipelineStageFlags         srcStageMask
+                       VK_PIPELINE_STAGE_TRANSFER_BIT,                                                         // VkPipelineStageFlags         dstStageMask
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                                           // VkAccessFlags                        srcAccessMask
+                       VK_ACCESS_TRANSFER_WRITE_BIT,                                                           // VkAccessFlags                        dstAccessMask
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                                       // VkImageLayout                        oldLayout;
+                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);                                          // VkImageLayout                        newLayout;
        }
 
-
-       m_vkd.cmdClearColorImage(*m_commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_params.clearValue.color, 1, &subResourcerange);
+       // Different clear color per range
+       for (std::size_t i = 0u; i < subresourceRanges.size(); ++i)
+               m_vkd.cmdClearColorImage(*m_commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_params.clearValue[i].color, 1, &subresourceRanges[i]);
 
        pipelineImageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,                            // VkPipelineStageFlags         srcStageMask
                                                 VK_PIPELINE_STAGE_TRANSFER_BIT,                                // VkPipelineStageFlags         dstStageMask
@@ -910,45 +1196,19 @@ TestStatus ClearColorImageTestInstance::iterate (void)
        endCommandBuffer();
        submitCommandBuffer();
 
-       de::MovePtr<TextureLevel>       result                                          = readImage(VK_IMAGE_ASPECT_COLOR_BIT);
-       std::string                                     compareResult;
-
-       for (deUint32 z = 0; z < m_params.imageExtent.depth; z++)
-       {
-               for (deUint32 y = 0; y < m_params.imageExtent.height; y++)
-               {
-                       for (deUint32 x = 0; x < m_params.imageExtent.width; x++)
-                       {
-                               if (!comparePixelToColorClearValue(result->getAccess(), x, y, z, m_params.clearValue.color, compareResult))
-                                       return TestStatus::fail("Color value mismatch! " + compareResult);
-                       }
-               }
-       }
-
-       return TestStatus::pass("cmdClearColorImage passed");
+       return verifyResultImage("cmdClearColorImage passed");
 }
 
 class ClearDepthStencilImageTestInstance : public ImageClearingTestInstance
 {
 public:
-                                                                       ClearDepthStencilImageTestInstance      (Context&                       context,
-                                                                                                                                                const TestParams&      testParams)
-                                                                               : ImageClearingTestInstance                     (context, testParams)
-                                                                       {}
-
-       virtual TestStatus                              iterate                                                         (void);
+                               ClearDepthStencilImageTestInstance      (Context& context, const TestParams& testParams) : ImageClearingTestInstance (context, testParams) {}
+       TestStatus      iterate                                                         (void);
 };
 
 TestStatus ClearDepthStencilImageTestInstance::iterate (void)
 {
-       const VkImageSubresourceRange   subResourcerange        =
-       {
-               m_imageAspectFlags,                             // VkImageAspectFlags   aspectMask;
-               0,                                                              // deUint32                             baseMipLevel;
-               1,                                                              // deUint32                             levelCount;
-               0,                                                              // deUint32                             baseArrayLayer;
-               1                                                               // deUint32                             layerCount;
-       };
+       const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(m_imageAspectFlags, 0u, 1u, m_params.clearLayerRange.baseArrayLayer, m_params.clearLayerRange.layerCount);
 
        beginCommandBuffer(0);
 
@@ -976,7 +1236,7 @@ TestStatus ClearDepthStencilImageTestInstance::iterate (void)
                                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);                                 // VkImageLayout                        newLayout;
        }
 
-       m_vkd.cmdClearDepthStencilImage(*m_commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_params.clearValue.depthStencil, 1, &subResourcerange);
+       m_vkd.cmdClearDepthStencilImage(*m_commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_params.clearValue[0].depthStencil, 1, &subresourceRange);
 
        pipelineImageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,                                    // VkPipelineStageFlags         srcStageMask
                                                 VK_PIPELINE_STAGE_TRANSFER_BIT,                                        // VkPipelineStageFlags         dstStageMask
@@ -988,414 +1248,126 @@ TestStatus ClearDepthStencilImageTestInstance::iterate (void)
        endCommandBuffer();
        submitCommandBuffer();
 
-       de::MovePtr<TextureLevel>                                               depthResult;
-       de::MovePtr<TextureLevel>                                               stencilResult;
-       bool                                                                                    isDepthFormat           = getIsDepthFormat(m_params.imageFormat);
-       if (isDepthFormat)
-       {
-               depthResult             = readImage(VK_IMAGE_ASPECT_DEPTH_BIT);
-       }
-       const bool                                                                              isStencilFormat         = getIsStencilFormat(m_params.imageFormat);
-
-       if (isStencilFormat)
-       {
-               stencilResult   = readImage(VK_IMAGE_ASPECT_STENCIL_BIT);
-       }
-
-       std::string                                                                             compareResult;
-
-       for (deUint32 y = 0; y < m_params.imageExtent.height; ++y)
-       {
-               for (deUint32 x = 0; x < m_params.imageExtent.width; ++x)
-               {
-                       if (isDepthFormat && !comparePixelToDepthClearValue(depthResult->getAccess(), x, y, m_params.clearValue.depthStencil.depth, compareResult))
-                               return TestStatus::fail("Depth value mismatch! " + compareResult);
-
-                       if (isStencilFormat && !comparePixelToStencilClearValue(stencilResult->getAccess(), x, y, m_params.clearValue.depthStencil.stencil, compareResult))
-                               return TestStatus::fail("Stencil value mismatch! " + compareResult);
-               }
-       }
-
-       return TestStatus::pass("cmdClearDepthStencilImage passed");
+       return verifyResultImage("cmdClearDepthStencilImage passed");
 }
 
-class ClearColorAttachmentTestInstance : public ImageClearingTestInstance
+class ClearAttachmentTestInstance : public ImageClearingTestInstance
 {
 public:
-                                                                       ClearColorAttachmentTestInstance        (Context&                                       context,
-                                                                                                                                                const TestParams&      testParams)
-                                                                               : ImageClearingTestInstance(context, testParams)
-                                                                       {
-                                                                               if (!m_isAttachmentFormat)
-                                                                               {
-                                                                                       TCU_THROW(NotSupportedError, "Format not renderable");
-                                                                               }
-                                                                       }
-
-       virtual TestStatus                              iterate                                                         (void);
-};
-
-TestStatus ClearColorAttachmentTestInstance::iterate (void)
-{
-       const VkClearAttachment                 clearAttachment         =
+       enum ClearType
        {
-               VK_IMAGE_ASPECT_COLOR_BIT,                                              // kImageAspectFlags    aspectMask;
-               0u,                                                                                             // deUint32                             colorAttachment;
-               m_params.clearValue                                                             // VkClearValue                 clearValue;
+               FULL_CLEAR,
+               PARTIAL_CLEAR,
        };
 
-       const VkClearRect                               clearRect                       =
-       {
-               {
-                       { 0, 0 },
-                       { m_params.imageExtent.width, m_params.imageExtent.height }
-               },                                                                                                                                      // VkRect2D     rect;
-               0u,                                                                                                                                     // deUint32     baseArrayLayer;
-               1u                                                                                                                                      // deUint32     layerCount;
-       };
-
-       beginCommandBuffer(0);
-
-       pipelineImageBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                         // VkPipelineStageFlags         srcStageMask
-                                                VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                    // VkPipelineStageFlags         dstStageMask
-                                                0,                                                                                             // VkAccessFlags                        srcAccessMask
-                                                VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
-                                                VK_ACCESS_TRANSFER_WRITE_BIT,                                  // VkAccessFlags                        dstAccessMask
-                                                VK_IMAGE_LAYOUT_UNDEFINED,                                             // VkImageLayout                        oldLayout;
-                                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);             // VkImageLayout                        newLayout;
-
-       beginRenderPass(VK_SUBPASS_CONTENTS_INLINE, m_params.initValue);
-       m_vkd.cmdClearAttachments(*m_commandBuffer, 1, &clearAttachment, 1, &clearRect);
-       m_vkd.cmdEndRenderPass(*m_commandBuffer);
-
-       pipelineImageBarrier(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,                        // VkPipelineStageFlags         srcStageMask
-                                                VK_PIPELINE_STAGE_TRANSFER_BIT,                                // VkPipelineStageFlags         dstStageMask
-                                                VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
-                                                VK_ACCESS_TRANSFER_WRITE_BIT,                                  // VkAccessFlags                        srcAccessMask
-                                                VK_ACCESS_TRANSFER_READ_BIT,                                   // VkAccessFlags                        dstAccessMask
-                                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,              // VkImageLayout                        oldLayout;
-                                                VK_IMAGE_LAYOUT_GENERAL);                                              // VkImageLayout                        newLayout;
-
-       endCommandBuffer();
-       submitCommandBuffer();
-
-       de::MovePtr<TextureLevel>               result                                          = readImage(VK_IMAGE_ASPECT_COLOR_BIT);
-       std::string                                             compareResult;
-
-       for (deUint32 y = 0; y < m_params.imageExtent.height; y++)
+       ClearAttachmentTestInstance (Context& context, const TestParams& testParams, const ClearType clearType = FULL_CLEAR)
+               : ImageClearingTestInstance     (context, testParams)
+               , m_clearType                           (clearType)
        {
-               for (deUint32 x = 0; x < m_params.imageExtent.width; x++)
-               {
-                               if (!comparePixelToColorClearValue(result->getAccess(), x, y, 0, m_params.clearValue.color, compareResult))
-                                       return TestStatus::fail("Color value mismatch" + compareResult);
-               }
+               if (!m_isAttachmentFormat)
+                       TCU_THROW(NotSupportedError, "Format not renderable");
        }
 
-       return TestStatus::pass("cmdClearAttachments passed");
-}
-
-class ClearDepthStencilAttachmentTestInstance : public ImageClearingTestInstance
-{
-public:
-                                                                       ClearDepthStencilAttachmentTestInstance (Context&                               context,
-                                                                                                                                                        const TestParams&              testParams)
-                                                                               : ImageClearingTestInstance(context, testParams)
-                                                                       {
-                                                                               if (!m_isAttachmentFormat)
-                                                                               {
-                                                                                       TCU_THROW(NotSupportedError, "Format not renderable");
-                                                                               }
-                                                                       }
-
-       virtual TestStatus                              iterate                                                                 (void);
-};
-
-TestStatus ClearDepthStencilAttachmentTestInstance::iterate (void)
-{
-       const VkClearAttachment                 clearAttachment         =
-       {
-               VK_IMAGE_ASPECT_DEPTH_BIT |
-               VK_IMAGE_ASPECT_STENCIL_BIT,                                    // kImageAspectFlags    aspectMask;
-               0u,                                                                                             // deUint32                             colorAttachment;
-               m_params.clearValue                                                             // VkClearValue                 clearValue;
-       };
-
-       const VkClearRect                               clearRect                       =
+       TestStatus iterate (void)
        {
+               const VkClearAttachment clearAttachment =
                {
-                       { 0, 0 },
-                       { m_params.imageExtent.width, m_params.imageExtent.height }
-               },                                                                                                                                      // VkRect2D     rect;
-               0u,                                                                                                                                     // deUint32     baseArrayLayer;
-               1u                                                                                                                                      // deUint32     layerCount;
-       };
-
-       beginCommandBuffer(0);
-
-       pipelineImageBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                                 // VkPipelineStageFlags         srcStageMask
-                                                VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                            // VkPipelineStageFlags         dstStageMask
-                                                0,                                                                                                     // VkAccessFlags                        srcAccessMask
-                                                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
-                                                VK_ACCESS_TRANSFER_WRITE_BIT,                                          // VkAccessFlags                        dstAccessMask
-                                                VK_IMAGE_LAYOUT_UNDEFINED,                                                     // VkImageLayout                        oldLayout;
-                                                VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);     // VkImageLayout                        newLayout;
-
-       beginRenderPass(VK_SUBPASS_CONTENTS_INLINE, m_params.initValue);
-       m_vkd.cmdClearAttachments(*m_commandBuffer, 1, &clearAttachment, 1, &clearRect);
-       m_vkd.cmdEndRenderPass(*m_commandBuffer);
-
-       pipelineImageBarrier(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,                                // VkPipelineStageFlags         srcStageMask
-                                                VK_PIPELINE_STAGE_TRANSFER_BIT,                                        // VkPipelineStageFlags         dstStageMask
-                                                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
-                                                VK_ACCESS_TRANSFER_WRITE_BIT,                                          // VkAccessFlags                        srcAccessMask
-                                                VK_ACCESS_TRANSFER_READ_BIT,                                           // VkAccessFlags                        dstAccessMask
-                                                VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,      // VkImageLayout                        oldLayout;
-                                                VK_IMAGE_LAYOUT_GENERAL);                                                      // VkImageLayout                        newLayout;
-
-       endCommandBuffer();
-       submitCommandBuffer();
-
-       de::MovePtr<TextureLevel>                                               depthResult;
-       de::MovePtr<TextureLevel>                                               stencilResult;
-       bool                                                                                    isDepthFormat           = getIsDepthFormat(m_params.imageFormat);
-       if (isDepthFormat)
-       {
-               depthResult             = readImage(VK_IMAGE_ASPECT_DEPTH_BIT);
-       }
-       const bool                                                                              isStencilFormat         = getIsStencilFormat(m_params.imageFormat);
-
-       if (isStencilFormat)
-       {
-               stencilResult   = readImage(VK_IMAGE_ASPECT_STENCIL_BIT);
-       }
-
+                       m_imageAspectFlags,                                     // VkImageAspectFlags   aspectMask;
+                       0u,                                                                     // deUint32                             colorAttachment;
+                       m_params.clearValue[0]                          // VkClearValue                 clearValue;
+               };
 
-       std::string                                                                             compareResult;
+               UVec4                                           clearCoords;
+               std::vector<VkClearRect>        clearRects;
 
-       for (deUint32 y = 0; y < m_params.imageExtent.height; y++)
-       {
-               for (deUint32 x = 0; x < m_params.imageExtent.width; x++)
+               if (m_clearType == FULL_CLEAR)
                {
-                       if (isDepthFormat && !comparePixelToDepthClearValue(depthResult->getAccess(), x, y, m_params.clearValue.depthStencil.depth, compareResult))
-                               return TestStatus::fail("Depth value mismatch! " + compareResult);
-
-                       if (isStencilFormat && !comparePixelToStencilClearValue(stencilResult->getAccess(), x, y, m_params.clearValue.depthStencil.stencil, compareResult))
-                               return TestStatus::fail("Stencil value mismatch! " + compareResult);
+                       const VkClearRect rect =
+                       {
+                               {
+                                       { 0, 0 },                                                                                                                                       // VkOffset2D    offset;
+                                       { m_params.imageExtent.width, m_params.imageExtent.height }                                     // VkExtent2D    extent;
+                               },                                                                                                                                                      // VkRect2D     rect;
+                               m_params.clearLayerRange.baseArrayLayer,                                                                // deUint32     baseArrayLayer;
+                               m_params.clearLayerRange.layerCount,                                                                    // deUint32     layerCount;
+                       };
+
+                       clearRects.push_back(rect);
                }
-       }
-
-       return TestStatus::pass("cmdClearAttachments passed");
-}
-
-class PartialClearColorAttachmentTestInstance : public ImageClearingTestInstance
-{
-public:
-                                                                       PartialClearColorAttachmentTestInstance (Context&                               context,
-                                                                                                                                                        const TestParams&              testParams)
-                                                                               : ImageClearingTestInstance(context, testParams)
-                                                                       {
-                                                                               if (!m_isAttachmentFormat)
-                                                                               {
-                                                                                       TCU_THROW(NotSupportedError, "Format not renderable");
-                                                                               }
-                                                                       }
-
-       virtual TestStatus                              iterate                                                                 (void);
-};
+               else
+               {
+                       const deUint32  clearX          = m_params.imageExtent.width  / 4u;
+                       const deUint32  clearY          = m_params.imageExtent.height / 4u;
+                       const deUint32  clearWidth      = m_params.imageExtent.width  / 2u;
+                       const deUint32  clearHeight     = m_params.imageExtent.height / 2u;
 
-TestStatus PartialClearColorAttachmentTestInstance::iterate (void)
-{
-       const VkClearAttachment                 clearAttachment         =
-       {
-               VK_IMAGE_ASPECT_COLOR_BIT,                                              // kImageAspectFlags    aspectMask;
-               0u,                                                                                             // deUint32                             colorAttachment;
-               m_params.clearValue                                                             // VkClearValue                 clearValue;
-       };
+                       clearCoords     = UVec4(clearX,                                 clearY,
+                                                               clearX + clearWidth,    clearY + clearHeight);
 
-       const VkClearRect                               clearRects[2]           =
-       {
-               {
-                       {
-                               { 0, (deInt32)(m_params.imageExtent.height / 4) },
-                               { m_params.imageExtent.width, m_params.imageExtent.height / 2}
-                       },                                                                                                                                      // VkRect2D     rect;
-                       0u,                                                                                                                                     // deUint32     baseArrayLayer;
-                       1u                                                                                                                                      // deUint32     layerCount;
-               },
-               {
+                       const VkClearRect rects[2] =
                        {
-                               { (deInt32)(m_params.imageExtent.width / 4), 0 },
-                               { m_params.imageExtent.width / 2, m_params.imageExtent.height}
-                       },                                                                                                                                      // VkRect2D     rect;
-                       0u,                                                                                                                                     // deUint32     baseArrayLayer;
-                       1u                                                                                                                                      // deUint32     layerCount;
+                               {
+                                       {
+                                               { 0,                                                    static_cast<deInt32>(clearY)    },              // VkOffset2D    offset;
+                                               { m_params.imageExtent.width,   clearHeight                                             }               // VkExtent2D    extent;
+                                       },                                                                                                                                              // VkRect2D     rect;
+                                       m_params.clearLayerRange.baseArrayLayer,                                                                // deUint32     baseArrayLayer;
+                                       m_params.clearLayerRange.layerCount                                                                             // deUint32     layerCount;
+                               },
+                               {
+                                       {
+                                               { static_cast<deInt32>(clearX), 0                                                       },                      // VkOffset2D    offset;
+                                               { clearWidth,                                   m_params.imageExtent.height     }                       // VkExtent2D    extent;
+                                       },                                                                                                                                              // VkRect2D     rect;
+                                       m_params.clearLayerRange.baseArrayLayer,                                                                // deUint32     baseArrayLayer;
+                                       m_params.clearLayerRange.layerCount                                                                             // deUint32     layerCount;
+                               }
+                       };
+
+                       clearRects.push_back(rects[0]);
+                       clearRects.push_back(rects[1]);
                }
-       };
 
-       beginCommandBuffer(0);
+               const bool                      isDepthStencil          = isDepthStencilFormat(m_params.imageFormat);
+               const VkAccessFlags     accessMask                      = (isDepthStencil ? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT     : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
+               const VkImageLayout     attachmentLayout        = (isDepthStencil ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
 
-       pipelineImageBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                         // VkPipelineStageFlags         srcStageMask
-                                                VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                    // VkPipelineStageFlags         dstStageMask
-                                                0,                                                                                             // VkAccessFlags                        srcAccessMask
-                                                VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                  // VkAccessFlags                        dstAccessMask
-                                                VK_IMAGE_LAYOUT_UNDEFINED,                                             // VkImageLayout                        oldLayout;
-                                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);             // VkImageLayout                        newLayout;
+               beginCommandBuffer(0);
 
-       beginRenderPass(VK_SUBPASS_CONTENTS_INLINE, m_params.initValue);
-       m_vkd.cmdClearAttachments(*m_commandBuffer, 1, &clearAttachment, 2, clearRects);
-       m_vkd.cmdEndRenderPass(*m_commandBuffer);
+               pipelineImageBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                         // VkPipelineStageFlags         srcStageMask
+                                                        VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                    // VkPipelineStageFlags         dstStageMask
+                                                        0,                                                                                             // VkAccessFlags                        srcAccessMask
+                                                        accessMask,                                                                    // VkAccessFlags                        dstAccessMask
+                                                        VK_IMAGE_LAYOUT_UNDEFINED,                                             // VkImageLayout                        oldLayout;
+                                                        attachmentLayout);                                                             // VkImageLayout                        newLayout;
 
-       pipelineImageBarrier(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,                        // VkPipelineStageFlags         srcStageMask
-                                                VK_PIPELINE_STAGE_TRANSFER_BIT,                                // VkPipelineStageFlags         dstStageMask
-                                                VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
-                                                VK_ACCESS_TRANSFER_WRITE_BIT,                                  // VkAccessFlags                        srcAccessMask
-                                                VK_ACCESS_TRANSFER_READ_BIT,                                   // VkAccessFlags                        dstAccessMask
-                                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,              // VkImageLayout                        oldLayout;
-                                                VK_IMAGE_LAYOUT_GENERAL);                                              // VkImageLayout                        newLayout;
-
-       endCommandBuffer();
+               beginRenderPass(VK_SUBPASS_CONTENTS_INLINE, m_params.initValue);
+               m_vkd.cmdClearAttachments(*m_commandBuffer, 1, &clearAttachment, static_cast<deUint32>(clearRects.size()), &clearRects[0]);
+               m_vkd.cmdEndRenderPass(*m_commandBuffer);
 
-       submitCommandBuffer();
+               pipelineImageBarrier(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,                        // VkPipelineStageFlags         srcStageMask
+                                                        VK_PIPELINE_STAGE_TRANSFER_BIT,                                // VkPipelineStageFlags         dstStageMask
+                                                        accessMask,                                                                    // VkAccessFlags                        srcAccessMask
+                                                        VK_ACCESS_TRANSFER_READ_BIT,                                   // VkAccessFlags                        dstAccessMask
+                                                        attachmentLayout,                                                              // VkImageLayout                        oldLayout;
+                                                        VK_IMAGE_LAYOUT_GENERAL);                                              // VkImageLayout                        newLayout;
 
-       de::MovePtr<TextureLevel>               result                                          = readImage(VK_IMAGE_ASPECT_COLOR_BIT);
-       std::string                                             compareResult;
+               endCommandBuffer();
+               submitCommandBuffer();
 
-       for (deUint32 y = 0; y < m_params.imageExtent.height; y++)
-       {
-               for (deUint32 x = 0; x < m_params.imageExtent.width; x++)
-               {
-                       if (((x < m_params.imageExtent.width / 4) && (y < m_params.imageExtent.height / 4)) ||
-                               ((x < m_params.imageExtent.width / 4) && (y >= (m_params.imageExtent.height * 3) / 4)) ||
-                               ((x >= (m_params.imageExtent.width * 3) / 4) && (y < m_params.imageExtent.height / 4)) ||
-                               ((x >= (m_params.imageExtent.width * 3) / 4) && (y >= (m_params.imageExtent.height * 3) / 4)))
-                       {
-                               if (!comparePixelToColorClearValue(result->getAccess(), x, y, 0, m_params.initValue.color, compareResult))
-                                       return TestStatus::fail("Color value mismatch! " + compareResult);
-                       }
-                       else if (!comparePixelToColorClearValue(result->getAccess(), x, y, 0, m_params.clearValue.color, compareResult))
-                               return TestStatus::fail("Color value mismatch! " + compareResult);
-               }
+               return verifyResultImage("cmdClearAttachments passed", clearCoords);
        }
 
-       return TestStatus::pass("cmdClearAttachments passed");
-}
+private:
+       const ClearType m_clearType;
+};
 
-class PartialClearDepthStencilAttachmentTestInstance : public ImageClearingTestInstance
+class PartialClearAttachmentTestInstance : public ClearAttachmentTestInstance
 {
 public:
-                                                                       PartialClearDepthStencilAttachmentTestInstance  (Context&                               context,
-                                                                                                                                                                        const TestParams&              testParams)
-                                                                               : ImageClearingTestInstance(context, testParams)
-                                                                       {
-                                                                               if (!m_isAttachmentFormat)
-                                                                               {
-                                                                                       TCU_THROW(NotSupportedError, "Format not renderable");
-                                                                               }
-                                                                       }
-
-       virtual TestStatus                              iterate                                                                                 (void);
+       PartialClearAttachmentTestInstance (Context& context, const TestParams& testParams) : ClearAttachmentTestInstance (context, testParams, PARTIAL_CLEAR) {}
 };
 
-TestStatus PartialClearDepthStencilAttachmentTestInstance::iterate (void)
-{
-       const VkClearAttachment                 clearAttachment         =
-       {
-               VK_IMAGE_ASPECT_DEPTH_BIT |
-               VK_IMAGE_ASPECT_STENCIL_BIT,                                    // kImageAspectFlags    aspectMask;
-               0u,                                                                                             // deUint32                             colorAttachment;
-               m_params.clearValue                                                             // VkClearValue                 clearValue;
-       };
-
-       const VkClearRect                               clearRects[2]           =
-       {
-               {
-                       {
-                               { 0, (deInt32)(m_params.imageExtent.height / 4) },
-                               { m_params.imageExtent.width, m_params.imageExtent.height / 2}
-                       },                                                                                                                                      // VkRect2D     rect;
-                       0u,                                                                                                                                     // deUint32     baseArrayLayer;
-                       1u                                                                                                                                      // deUint32     layerCount;
-               },
-               {
-                       {
-                               { (deInt32)(m_params.imageExtent.width / 4), 0 },
-                               { m_params.imageExtent.width / 2, m_params.imageExtent.height}
-                       },                                                                                                                                      // VkRect2D     rect;
-                       0u,                                                                                                                                     // deUint32     baseArrayLayer;
-                       1u                                                                                                                                      // deUint32     layerCount;
-               }
-       };
-
-       beginCommandBuffer(0);
-
-       pipelineImageBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                                 // VkPipelineStageFlags         srcStageMask
-                                                VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                            // VkPipelineStageFlags         dstStageMask
-                                                0,                                                                                                     // VkAccessFlags                        srcAccessMask
-                                                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,          // VkAccessFlags                        dstAccessMask
-                                                VK_IMAGE_LAYOUT_UNDEFINED,                                                     // VkImageLayout                        oldLayout;
-                                                VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);     // VkImageLayout                        newLayout;
-
-       beginRenderPass(VK_SUBPASS_CONTENTS_INLINE, m_params.initValue);
-       m_vkd.cmdClearAttachments(*m_commandBuffer, 1, &clearAttachment, 2, clearRects);
-       m_vkd.cmdEndRenderPass(*m_commandBuffer);
-
-       pipelineImageBarrier(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,                                // VkPipelineStageFlags         srcStageMask
-                                                VK_PIPELINE_STAGE_TRANSFER_BIT,                                        // VkPipelineStageFlags         dstStageMask
-                                                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
-                                                VK_ACCESS_TRANSFER_WRITE_BIT,                                          // VkAccessFlags                        srcAccessMask
-                                                VK_ACCESS_TRANSFER_READ_BIT,                                           // VkAccessFlags                        dstAccessMask
-                                                VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,      // VkImageLayout                        oldLayout;
-                                                VK_IMAGE_LAYOUT_GENERAL);                                                      // VkImageLayout                        newLayout;
-
-       endCommandBuffer();
-
-       submitCommandBuffer();
-
-       de::MovePtr<TextureLevel>                                               depthResult;
-       de::MovePtr<TextureLevel>                                               stencilResult;
-       bool                                                                                    isDepthFormat           = getIsDepthFormat(m_params.imageFormat);
-       if (isDepthFormat)
-       {
-               depthResult             = readImage(VK_IMAGE_ASPECT_DEPTH_BIT);
-       }
-       const bool                                                                              isStencilFormat         = getIsStencilFormat(m_params.imageFormat);
-
-       if (isStencilFormat)
-       {
-               stencilResult   = readImage(VK_IMAGE_ASPECT_STENCIL_BIT);
-       }
-
-       std::string                                                                             compareResult;
-
-       for (deUint32 y = 0; y < m_params.imageExtent.height; y++)
-       {
-               for (deUint32 x = 0; x < m_params.imageExtent.width; x++)
-               {
-                       if (((x < m_params.imageExtent.width / 4) && (y < m_params.imageExtent.height / 4)) ||
-                               ((x < m_params.imageExtent.width / 4) && (y >= (m_params.imageExtent.height * 3) / 4)) ||
-                               ((x >= (m_params.imageExtent.width * 3) / 4) && (y < m_params.imageExtent.height / 4)) ||
-                               ((x >= (m_params.imageExtent.width * 3) / 4) && (y >= (m_params.imageExtent.height * 3) / 4)))
-                       {
-                               if (isDepthFormat && !comparePixelToDepthClearValue(depthResult->getAccess(), x, y, m_params.initValue.depthStencil.depth, compareResult))
-                                       return TestStatus::fail("Depth value mismatch! " + compareResult);
-
-                               if (isStencilFormat && !comparePixelToStencilClearValue(stencilResult->getAccess(), x, y, m_params.initValue.depthStencil.stencil, compareResult))
-                                       return TestStatus::fail("Stencil value mismatch! " + compareResult);
-                       }
-                       else
-                       {
-                               if (isDepthFormat && !comparePixelToDepthClearValue(depthResult->getAccess(), x, y, m_params.clearValue.depthStencil.depth, compareResult))
-                                       return TestStatus::fail("Depth value mismatch! " + compareResult);
-
-                               if (isStencilFormat && !comparePixelToStencilClearValue(stencilResult->getAccess(), x, y, m_params.clearValue.depthStencil.stencil, compareResult))
-                                       return TestStatus::fail("Stencil value mismatch! " + compareResult);
-                       }
-               }
-       }
-
-       return TestStatus::pass("cmdClearAttachments passed");
-}
-
 VkClearValue makeClearColorValue (VkFormat format, float r, float g, float b, float a)
 {
        const   TextureFormat tcuFormat = mapVkFormat(format);
@@ -1450,13 +1422,8 @@ const char* getImageTypeCaseName (VkImageType type)
        return de::getSizedArrayElement<VK_IMAGE_TYPE_LAST>(s_names, type);
 }
 
-} // anonymous
-
-TestCaseGroup* createImageClearingTests (TestContext& testCtx)
+TestCaseGroup* createImageClearingTestsCommon (TestContext& testCtx, tcu::TestCaseGroup* imageClearingTests, AllocationKind allocationKind)
 {
-       // Main testgroup.
-       de::MovePtr<TestCaseGroup>      imageClearingTests                                              (new TestCaseGroup(testCtx, "image_clearing", "Image Clearing Tests"));
-
        de::MovePtr<TestCaseGroup>      colorImageClearTests                                    (new TestCaseGroup(testCtx, "clear_color_image", "Color Image Clear Tests"));
        de::MovePtr<TestCaseGroup>      depthStencilImageClearTests                             (new TestCaseGroup(testCtx, "clear_depth_stencil_image", "Color Depth/Stencil Image Tests"));
        de::MovePtr<TestCaseGroup>      colorAttachmentClearTests                               (new TestCaseGroup(testCtx, "clear_color_attachment", "Color Color Attachment Tests"));
@@ -1659,6 +1626,32 @@ TestCaseGroup* createImageClearingTests (TestContext& testCtx)
        };
        const size_t    numOfDepthStencilImageFormatsToTest             = DE_LENGTH_OF_ARRAY(depthStencilImageFormatsToTest);
 
+       struct ImageLayerParams
+       {
+               deUint32                imageLayerCount;
+               LayerRange              imageViewRange;
+               LayerRange              clearLayerRange;
+               const char*             testName;
+       };
+       const ImageLayerParams imageLayerParamsToTest[] =
+       {
+               {
+                       1u,                                     // imageLayerCount
+                       {0u, 1u},                       // imageViewRange
+                       {0u, 1u},                       // clearLayerRange
+                       DE_NULL                         // testName
+               },
+               {
+                       16u,                            // imageLayerCount
+                       {3u, 12u},                      // imageViewRange
+                       {2u, 5u},                       // clearLayerRange
+                       "multiple_layers"       // testName
+               },
+       };
+
+       const size_t    numOfImageLayerParamsToTest                             = DE_LENGTH_OF_ARRAY(imageLayerParamsToTest);
+
+       // Clear color image
        {
                const VkImageType                       imageTypesToTest[]              =
                {
@@ -1675,152 +1668,178 @@ TestCaseGroup* createImageClearingTests (TestContext& testCtx)
                        { 256, 256, 16}
                };
 
-               TestParams                                      colorImageTestParams;
-
                for (size_t     imageTypeIndex = 0; imageTypeIndex < numOfImageTypesToTest; ++imageTypeIndex)
+               for (size_t imageFormatIndex = 0; imageFormatIndex < numOfColorImageFormatsToTest; ++imageFormatIndex)
+               for (size_t imageLayerParamsIndex = 0; imageLayerParamsIndex < numOfImageLayerParamsToTest; ++imageLayerParamsIndex)
                {
-                       for (size_t imageFormatIndex = 0; imageFormatIndex < numOfColorImageFormatsToTest; ++imageFormatIndex)
+
+                       if (imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount > 1u && imageTypesToTest[imageTypeIndex] == VK_IMAGE_TYPE_3D)
+                       {
+                               // 3D ARRAY images are not supported
+                               continue;
+                       }
+
+                       const VkFormat          format          = colorImageFormatsToTest[imageFormatIndex];
+                       const TestParams        testParams      =
                        {
-                               colorImageTestParams.imageType          = imageTypesToTest[imageTypeIndex];
-                               colorImageTestParams.imageFormat        = colorImageFormatsToTest[imageFormatIndex];
-                               colorImageTestParams.imageExtent        = imageDimensionsByType[imageTypeIndex];
-                               colorImageTestParams.initValue          = makeClearColorValue(colorImageTestParams.imageFormat, 0.2f, 0.1f, 0.7f, 0.8f);
-                               colorImageTestParams.clearValue         = makeClearColorValue(colorImageTestParams.imageFormat, 0.1f, 0.5f, 0.3f, 0.9f);
+                               false,                                                                                                                          // bool                         useSingleMipLevel;
+                               imageTypesToTest[imageTypeIndex],                                                                       // VkImageType          imageType;
+                               format,                                                                                                                         // VkFormat                     imageFormat;
+                               imageDimensionsByType[imageTypeIndex],                                                          // VkExtent3D           imageExtent;
+                               imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount,          // deUint32         imageLayerCount;
+                               {
+                                       0u,
+                                       imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount
+                               },                                                                                                                                      // LayerRange           imageViewLayerRange;
+                               makeClearColorValue(format, 0.2f, 0.1f, 0.7f, 0.8f),                            // VkClearValue         initValue;
+                               {
+                                       makeClearColorValue(format, 0.1f, 0.5f, 0.3f, 0.9f),                            // VkClearValue         clearValue[0];
+                                       makeClearColorValue(format, 0.3f, 0.6f, 0.2f, 0.7f),                            // VkClearValue         clearValue[1];
+                               },
+                               imageLayerParamsToTest[imageLayerParamsIndex].clearLayerRange,          // LayerRange       clearLayerRange;
+                               allocationKind                                                                                                          // AllocationKind       allocationKind;
+                       };
 
-                               std::ostringstream      testCaseName;
-                               testCaseName << getImageTypeCaseName(colorImageTestParams.imageType);
-                               testCaseName << "_" << getFormatCaseName(colorImageTestParams.imageFormat);
+                       std::ostringstream      testCaseName;
+                       testCaseName << getImageTypeCaseName(testParams.imageType) << "_" << getFormatCaseName(format);
+                       if (imageLayerParamsToTest[imageLayerParamsIndex].testName != DE_NULL)
+                               testCaseName << "_" << imageLayerParamsToTest[imageLayerParamsIndex].testName;
 
-                               colorImageClearTests->addChild(new InstanceFactory1<ClearColorImageTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName.str(), "Clear Color Image", colorImageTestParams));
-                       }
+                       colorImageClearTests->addChild(new InstanceFactory1<ClearColorImageTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName.str(), "Clear Color Image", testParams));
                }
 
                imageClearingTests->addChild(colorImageClearTests.release());
        }
 
+       // Clear depth/stencil image
        {
-               TestParams                                      depthStencilImageTestParams                     =
-               {
-                       VK_IMAGE_TYPE_2D,                                                               // VkImageType          imageType;
-                       depthStencilImageFormatsToTest[0],                              // VkFormat                     format;
-                       { 256, 256, 1 },                                                                // VkExtent3D           extent;
-                       makeClearValueDepthStencil(0.5f, 0x03),                 // VkClearValue         initValue
-                       makeClearValueDepthStencil(0.1f, 0x06)                  // VkClearValue         clearValue
-               };
-
                for (size_t imageFormatIndex = 0; imageFormatIndex < numOfDepthStencilImageFormatsToTest; ++imageFormatIndex)
+               for (size_t imageLayerParamsIndex = 0; imageLayerParamsIndex < numOfImageLayerParamsToTest; ++imageLayerParamsIndex)
                {
-                       depthStencilImageTestParams.imageFormat = depthStencilImageFormatsToTest[imageFormatIndex];
+                       const TestParams testParams =
+                       {
+                               true,                                                                                                                           // bool                         useSingleMipLevel;
+                               VK_IMAGE_TYPE_2D,                                                                                                       // VkImageType          imageType;
+                               depthStencilImageFormatsToTest[imageFormatIndex],                                       // VkFormat                     format;
+                               { 256, 256, 1 },                                                                                                        // VkExtent3D           extent;
+                               imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount,          // deUint32         imageLayerCount;
+                               {
+                                       0u,
+                                       imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount
+                               },                                                                                                                                      // LayerRange           imageViewLayerRange;
+                               makeClearValueDepthStencil(0.5f, 0x03),                                                         // VkClearValue         initValue
+                               {
+                                       makeClearValueDepthStencil(0.1f, 0x06),                                                         // VkClearValue         clearValue[0];
+                                       makeClearValueDepthStencil(0.3f, 0x04),                                                         // VkClearValue         clearValue[1];
+                               },
+                               imageLayerParamsToTest[imageLayerParamsIndex].clearLayerRange,          // LayerRange       clearLayerRange;
+                               allocationKind                                                                                                          // AllocationKind       allocationKind;
+                       };
 
                        std::ostringstream      testCaseName;
-                       testCaseName << getImageTypeCaseName(depthStencilImageTestParams.imageType);
-                       testCaseName << "_" << getFormatCaseName(depthStencilImageTestParams.imageFormat);
+                       testCaseName << getImageTypeCaseName(testParams.imageType) << "_" << getFormatCaseName(testParams.imageFormat);
+                       if (imageLayerParamsToTest[imageLayerParamsIndex].testName != DE_NULL)
+                               testCaseName << "_" << imageLayerParamsToTest[imageLayerParamsIndex].testName;
 
-                       depthStencilImageClearTests->addChild(new InstanceFactory1<ClearDepthStencilImageTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName.str(), "Clear Depth/Stencil Image", depthStencilImageTestParams));
+                       depthStencilImageClearTests->addChild(new InstanceFactory1<ClearDepthStencilImageTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName.str(), "Clear Depth/Stencil Image", testParams));
                }
 
                imageClearingTests->addChild(depthStencilImageClearTests.release());
        }
 
+       // Clear color attachment
        {
-               TestParams                                      colorAttachmentTestParams                       =
-               {
-                       VK_IMAGE_TYPE_2D,                                                               // VkImageType          imageType;
-                       colorImageFormatsToTest[0],                                             // VkFormat                     format;
-                       { 256, 256, 1 },                                                                // VkExtent3D           extent;
-                       makeClearValueColorU32(0, 0, 0, 0),                             // VkClearValue         initValue
-                       makeClearValueColorU32(0, 0, 0, 0)                              // VkClearValue         clearValue
-               };
-
                for (size_t imageFormatIndex = 0; imageFormatIndex < numOfColorImageFormatsToTest; ++imageFormatIndex)
+               for (size_t imageLayerParamsIndex = 0; imageLayerParamsIndex < numOfImageLayerParamsToTest; ++imageLayerParamsIndex)
                {
-                       colorAttachmentTestParams.imageFormat   = colorImageFormatsToTest[imageFormatIndex];
-                       colorAttachmentTestParams.initValue             = makeClearColorValue(colorAttachmentTestParams.imageFormat, 0.2f, 0.1f, 0.7f, 0.8f);
-                       colorAttachmentTestParams.clearValue    = makeClearColorValue(colorAttachmentTestParams.imageFormat, 0.1f, 0.5f, 0.3f, 0.9f);
+                       const VkFormat          format          = colorImageFormatsToTest[imageFormatIndex];
+
+                       const TestParams        testParams =
+                       {
+                               true,                                                                                                                   // bool                         useSingleMipLevel;
+                               VK_IMAGE_TYPE_2D,                                                                                               // VkImageType          imageType;
+                               format,                                                                                                                 // VkFormat                     format;
+                               { 256, 256, 1 },                                                                                                // VkExtent3D           extent;
+                               imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount,  // deUint32         imageLayerCount;
+                               imageLayerParamsToTest[imageLayerParamsIndex].imageViewRange,   // LayerRange           imageViewLayerRange;
+                               makeClearColorValue(format, 0.2f, 0.1f, 0.7f, 0.8f),                    // VkClearValue         initValue
+                               {
+                                       makeClearColorValue(format, 0.1f, 0.5f, 0.3f, 0.9f),                    // VkClearValue         clearValue[0];
+                                       makeClearColorValue(format, 0.3f, 0.6f, 0.2f, 0.7f),                    // VkClearValue         clearValue[1];
+                               },
+                               imageLayerParamsToTest[imageLayerParamsIndex].clearLayerRange,  // LayerRange       clearLayerRange;
+                               allocationKind                                                                                                  // AllocationKind       allocationKind;
+                       };
 
                        std::ostringstream      testCaseName;
-                       testCaseName << getImageTypeCaseName(colorAttachmentTestParams.imageType);
-                       testCaseName << "_" << getFormatCaseName(colorAttachmentTestParams.imageFormat);
+                       testCaseName << getImageTypeCaseName(testParams.imageType) << "_" << getFormatCaseName(format);
+                       if (imageLayerParamsToTest[imageLayerParamsIndex].testName != DE_NULL)
+                               testCaseName << "_" << imageLayerParamsToTest[imageLayerParamsIndex].testName;
 
-                       colorAttachmentClearTests->addChild(new InstanceFactory1<ClearColorAttachmentTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName.str(), "Clear Color Attachment", colorAttachmentTestParams));
+                       colorAttachmentClearTests->addChild(new InstanceFactory1<ClearAttachmentTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName.str(), "Clear Color Attachment", testParams));
+                       partialColorAttachmentClearTests->addChild(new InstanceFactory1<PartialClearAttachmentTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName.str(), "Partial Clear Color Attachment", testParams));
                }
 
                imageClearingTests->addChild(colorAttachmentClearTests.release());
+               imageClearingTests->addChild(partialColorAttachmentClearTests.release());
        }
 
+       // Clear depth/stencil attachment
        {
-               TestParams                                      depthStencilAttachmentTestParams        =
-               {
-                       VK_IMAGE_TYPE_2D,                                                               // VkImageType          imageType;
-                       depthStencilImageFormatsToTest[0],                              // VkFormat                     format;
-                       { 256, 256, 1 },                                                                // VkExtent3D           extent;
-                       makeClearValueDepthStencil(0.5f, 0x03),                 // VkClearValue         initValue
-                       makeClearValueDepthStencil(0.1f, 0x06)                  // VkClearValue         clearValue
-               };
-
                for (size_t imageFormatIndex = 0; imageFormatIndex < numOfDepthStencilImageFormatsToTest; ++imageFormatIndex)
+               for (size_t imageLayerParamsIndex = 0; imageLayerParamsIndex < numOfImageLayerParamsToTest; ++imageLayerParamsIndex)
                {
-                       depthStencilAttachmentTestParams.imageFormat = depthStencilImageFormatsToTest[imageFormatIndex];
+                       const TestParams testParams =
+                       {
+                               true,                                                                                                                   // bool                         useSingleMipLevel;
+                               VK_IMAGE_TYPE_2D,                                                                                               // VkImageType          imageType;
+                               depthStencilImageFormatsToTest[imageFormatIndex],                               // VkFormat                     format;
+                               { 256, 256, 1 },                                                                                                // VkExtent3D           extent;
+                               imageLayerParamsToTest[imageLayerParamsIndex].imageLayerCount,  // deUint32         imageLayerCount;
+                               imageLayerParamsToTest[imageLayerParamsIndex].imageViewRange,   // LayerRange           imageViewLayerRange;
+                               makeClearValueDepthStencil(0.5f, 0x03),                                                 // VkClearValue         initValue
+                               {
+                                       makeClearValueDepthStencil(0.1f, 0x06),                                                 // VkClearValue         clearValue[0];
+                                       makeClearValueDepthStencil(0.3f, 0x04),                                                 // VkClearValue         clearValue[1];
+                               },
+                               imageLayerParamsToTest[imageLayerParamsIndex].clearLayerRange,  // LayerRange       clearLayerRange;
+                               allocationKind                                                                                                  // AllocationKind       allocationKind;
+                       };
 
                        std::ostringstream      testCaseName;
-                       testCaseName << getImageTypeCaseName(depthStencilAttachmentTestParams.imageType);
-                       testCaseName << "_" << getFormatCaseName(depthStencilAttachmentTestParams.imageFormat);
+                       testCaseName << getImageTypeCaseName(testParams.imageType) << "_" << getFormatCaseName(testParams.imageFormat);
+                       if (imageLayerParamsToTest[imageLayerParamsIndex].testName != DE_NULL)
+                               testCaseName << "_" << imageLayerParamsToTest[imageLayerParamsIndex].testName;
 
-                       depthStencilAttachmentClearTests->addChild(new InstanceFactory1<ClearDepthStencilAttachmentTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName.str(), "Clear Depth/Stencil Attachment", depthStencilAttachmentTestParams));
+                       depthStencilAttachmentClearTests->addChild(new InstanceFactory1<ClearAttachmentTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName.str(), "Clear Depth/Stencil Attachment", testParams));
+                       partialDepthStencilAttachmentClearTests->addChild(new InstanceFactory1<PartialClearAttachmentTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName.str(), "Parital Clear Depth/Stencil Attachment", testParams));
                }
 
                imageClearingTests->addChild(depthStencilAttachmentClearTests.release());
+               imageClearingTests->addChild(partialDepthStencilAttachmentClearTests.release());
        }
 
-       {
-               TestParams                                      colorAttachmentTestParams                       =
-               {
-                       VK_IMAGE_TYPE_2D,                                                               // VkImageType          imageType;
-                       colorImageFormatsToTest[0],                                             // VkFormat                     format;
-                       { 256, 256, 1 },                                                                // VkExtent3D           extent;
-                       makeClearValueColorU32(0, 0, 0, 0),                             // VkClearValue         initValue
-                       makeClearValueColorU32(0, 0, 0, 0)                              // VkClearValue         clearValue
-               };
-
-               for (size_t imageFormatIndex = 0; imageFormatIndex < numOfColorImageFormatsToTest; ++imageFormatIndex)
-               {
-                       colorAttachmentTestParams.imageFormat   = colorImageFormatsToTest[imageFormatIndex];
-                       colorAttachmentTestParams.initValue             = makeClearColorValue(colorAttachmentTestParams.imageFormat, 0.2f, 0.1f, 0.7f, 0.8f);
-                       colorAttachmentTestParams.clearValue    = makeClearColorValue(colorAttachmentTestParams.imageFormat, 0.1f, 0.5f, 0.3f, 0.9f);
-
-                       std::ostringstream      testCaseName;
-                       testCaseName << getImageTypeCaseName(colorAttachmentTestParams.imageType);
-                       testCaseName << "_" << getFormatCaseName(colorAttachmentTestParams.imageFormat);
-
-                       partialColorAttachmentClearTests->addChild(new InstanceFactory1<PartialClearColorAttachmentTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName.str(), "Partial Clear Color Attachment", colorAttachmentTestParams));
-               }
-
-               imageClearingTests->addChild(partialColorAttachmentClearTests.release());
-       }
+       return imageClearingTests;
+}
 
-       {
-               TestParams                                      depthStencilAttachmentTestParams        =
-               {
-                       VK_IMAGE_TYPE_2D,                                                               // VkImageType          imageType;
-                       depthStencilImageFormatsToTest[0],                              // VkFormat                     format;
-                       { 256, 256, 1 },                                                                // VkExtent3D           extent;
-                       makeClearValueDepthStencil(0.5f, 0x03),                 // VkClearValue         initValue
-                       makeClearValueDepthStencil(0.1f, 0x06)                  // VkClearValue         clearValue
-               };
+void createCoreImageClearingTests (tcu::TestCaseGroup* group)
+{
+       createImageClearingTestsCommon(group->getTestContext(), group, ALLOCATION_KIND_SUBALLOCATED);
+}
 
-               for (size_t imageFormatIndex = 0; imageFormatIndex < numOfDepthStencilImageFormatsToTest; ++imageFormatIndex)
-               {
-                       depthStencilAttachmentTestParams.imageFormat    = depthStencilImageFormatsToTest[imageFormatIndex];
+void createDedicatedAllocationImageClearingTests (tcu::TestCaseGroup* group)
+{
+       createImageClearingTestsCommon(group->getTestContext(), group, ALLOCATION_KIND_DEDICATED);
+}
 
-                       std::ostringstream      testCaseName;
-                       testCaseName << getImageTypeCaseName(depthStencilAttachmentTestParams.imageType);
-                       testCaseName << "_" << getFormatCaseName(depthStencilAttachmentTestParams.imageFormat);
+} // anonymous
 
-                       partialDepthStencilAttachmentClearTests->addChild(new InstanceFactory1<PartialClearDepthStencilAttachmentTestInstance, TestParams>(testCtx, NODETYPE_SELF_VALIDATE, testCaseName.str(), "Parital Clear Depth/Stencil Attachment", depthStencilAttachmentTestParams));
-               }
+TestCaseGroup* createImageClearingTests (TestContext& testCtx)
+{
+       de::MovePtr<TestCaseGroup>      imageClearingTests      (new TestCaseGroup(testCtx, "image_clearing", "Image Clearing Tests"));
 
-               imageClearingTests->addChild(partialDepthStencilAttachmentClearTests.release());
-       }
+       imageClearingTests->addChild(createTestGroup(testCtx, "core",                                   "Core Image Clearing Tests",                                                    createCoreImageClearingTests));
+       imageClearingTests->addChild(createTestGroup(testCtx, "dedicated_allocation",   "Image Clearing Tests For Dedicated Memory Allocation", createDedicatedAllocationImageClearingTests));
 
        return imageClearingTests.release();
 }