Do not use ycbcr formats if ycbcr extension is not supported
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / memory / vktMemoryRequirementsTests.cpp
index 154c1b2..5b22b48 100644 (file)
 #include "vkQueryUtil.hpp"
 #include "vkStrUtil.hpp"
 #include "vkTypeUtil.hpp"
+#include "vkImageUtil.hpp"
 
 #include "deUniquePtr.hpp"
 #include "deStringUtil.hpp"
+#include "deSTLUtil.hpp"
 
 #include "tcuResultCollector.hpp"
 #include "tcuTestLog.hpp"
@@ -47,6 +49,7 @@ namespace
 {
 using namespace vk;
 using de::MovePtr;
+using tcu::TestLog;
 
 Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize size, const VkBufferCreateFlags flags, const VkBufferUsageFlags usage)
 {
@@ -64,6 +67,55 @@ Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, con
        return createBuffer(vk, device, &createInfo);
 }
 
+VkMemoryRequirements getBufferMemoryRequirements (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize size, const VkBufferCreateFlags flags, const VkBufferUsageFlags usage)
+{
+       const Unique<VkBuffer> buffer(makeBuffer(vk, device, size, flags, usage));
+       return getBufferMemoryRequirements(vk, device, *buffer);
+}
+
+VkMemoryRequirements getBufferMemoryRequirements2 (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize size, const VkBufferCreateFlags flags, const VkBufferUsageFlags usage, void* next = DE_NULL)
+{
+       const Unique<VkBuffer>                          buffer          (makeBuffer(vk, device, size, flags, usage));
+       VkBufferMemoryRequirementsInfo2KHR      info    =
+       {
+               VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR,        // VkStructureType      sType
+               DE_NULL,                                                                                                        // const void*          pNext
+               *buffer                                                                                                         // VkBuffer                     buffer
+       };
+       VkMemoryRequirements2KHR                        req2    =
+       {
+               VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,                            // VkStructureType              sType
+               next,                                                                                                           // void*                                pNext
+               {0, 0, 0}                                                                                                       // VkMemoryRequirements memoryRequirements
+       };
+
+       vk.getBufferMemoryRequirements2KHR(device, &info, &req2);
+
+       return req2.memoryRequirements;
+}
+
+VkMemoryRequirements getImageMemoryRequirements2 (const DeviceInterface& vk, const VkDevice device, const VkImageCreateInfo& createInfo, void* next = DE_NULL)
+{
+       const Unique<VkImage> image(createImage(vk, device, &createInfo));
+
+       VkImageMemoryRequirementsInfo2KHR       info    =
+       {
+               VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR,         // VkStructureType      sType
+               DE_NULL,                                                                                                        // const void*          pNext
+               *image                                                                                                          // VkImage                      image
+       };
+       VkMemoryRequirements2KHR                        req2    =
+       {
+               VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,                            // VkStructureType              sType
+               next,                                                                                                           // void*                                pNext
+               {0, 0, 0}                                                                                                       // VkMemoryRequirements memoryRequirements
+       };
+
+       vk.getImageMemoryRequirements2KHR(device, &info, &req2);
+
+       return req2.memoryRequirements;
+}
+
 //! Get an index of each set bit, starting from the least significant bit.
 std::vector<deUint32> bitsToIndices (deUint32 bits)
 {
@@ -76,12 +128,6 @@ std::vector<deUint32> bitsToIndices (deUint32 bits)
        return indices;
 }
 
-VkMemoryRequirements getBufferMemoryRequirements (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize size, const VkBufferCreateFlags flags, const VkBufferUsageFlags usage)
-{
-       const Unique<VkBuffer> buffer(makeBuffer(vk, device, size, flags, usage));
-       return getBufferMemoryRequirements(vk, device, *buffer);
-}
-
 template<typename T>
 T nextEnum (T value)
 {
@@ -105,7 +151,200 @@ T nextFlagExcluding (T value, T excludedFlags)
        return static_cast<T>(tmp);
 }
 
-void requireBufferSparseFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkBufferCreateFlags flags)
+bool validValueVkBool32 (const VkBool32 value)
+{
+       return (value == VK_FALSE || value == VK_TRUE);
+}
+
+class IBufferMemoryRequirements
+{
+public:
+       virtual void populateTestGroup                  (tcu::TestCaseGroup*                                            group) = 0;
+
+protected:
+       virtual void addFunctionTestCase                (tcu::TestCaseGroup*                                            group,
+                                                                                        const std::string&                                                     name,
+                                                                                        const std::string&                                                     desc,
+                                                                                        VkBufferCreateFlags                                            arg0) = 0;
+
+       virtual tcu::TestStatus execTest                (Context&                                                                       context,
+                                                                                        const VkBufferCreateFlags                                      bufferFlags) = 0;
+
+       virtual void preTestChecks                              (Context&                                                                       context,
+                                                                                        const InstanceInterface&                                       vki,
+                                                                                        const VkPhysicalDevice                                         physDevice,
+                                                                                        const VkBufferCreateFlags                                      flags) = 0;
+
+       virtual void updateMemoryRequirements   (const DeviceInterface&                                         vk,
+                                                                                        const VkDevice                                                         device,
+                                                                                        const VkDeviceSize                                                     size,
+                                                                                        const VkBufferCreateFlags                                      flags,
+                                                                                        const VkBufferUsageFlags                                       usage,
+                                                                                        const bool                                                                     all) = 0;
+
+       virtual void verifyMemoryRequirements   (tcu::ResultCollector&                                          result,
+                                                                                        const VkPhysicalDeviceMemoryProperties&        deviceMemoryProperties,
+                                                                                        const VkPhysicalDeviceLimits&                          limits,
+                                                                                        const VkBufferCreateFlags                                      bufferFlags,
+                                                                                        const VkBufferUsageFlags                                       usage) = 0;
+};
+
+class BufferMemoryRequirementsOriginal : public IBufferMemoryRequirements
+{
+       static tcu::TestStatus testEntryPoint   (Context&                                                                       context,
+                                                                                        const VkBufferCreateFlags                                      bufferFlags);
+
+public:
+       virtual void populateTestGroup                  (tcu::TestCaseGroup*                                            group);
+
+protected:
+       virtual void addFunctionTestCase                (tcu::TestCaseGroup*                                            group,
+                                                                                        const std::string&                                                     name,
+                                                                                        const std::string&                                                     desc,
+                                                                                        VkBufferCreateFlags                                            arg0);
+
+       virtual tcu::TestStatus execTest                (Context&                                                                       context,
+                                                                                        const VkBufferCreateFlags                                      bufferFlags);
+
+       virtual void preTestChecks                              (Context&                                                                       context,
+                                                                                        const InstanceInterface&                                       vki,
+                                                                                        const VkPhysicalDevice                                         physDevice,
+                                                                                        const VkBufferCreateFlags                                      flags);
+
+       virtual void updateMemoryRequirements   (const DeviceInterface&                                         vk,
+                                                                                        const VkDevice                                                         device,
+                                                                                        const VkDeviceSize                                                     size,
+                                                                                        const VkBufferCreateFlags                                      flags,
+                                                                                        const VkBufferUsageFlags                                       usage,
+                                                                                        const bool                                                                     all);
+
+       virtual void verifyMemoryRequirements   (tcu::ResultCollector&                                          result,
+                                                                                        const VkPhysicalDeviceMemoryProperties&        deviceMemoryProperties,
+                                                                                        const VkPhysicalDeviceLimits&                          limits,
+                                                                                        const VkBufferCreateFlags                                      bufferFlags,
+                                                                                        const VkBufferUsageFlags                                       usage);
+
+protected:
+       VkMemoryRequirements    m_allUsageFlagsRequirements;
+       VkMemoryRequirements    m_currentTestRequirements;
+};
+
+
+tcu::TestStatus BufferMemoryRequirementsOriginal::testEntryPoint (Context& context, const VkBufferCreateFlags bufferFlags)
+{
+       BufferMemoryRequirementsOriginal test;
+
+       return test.execTest(context, bufferFlags);
+}
+
+void BufferMemoryRequirementsOriginal::populateTestGroup (tcu::TestCaseGroup* group)
+{
+       const struct
+       {
+               VkBufferCreateFlags             flags;
+               const char* const               name;
+       } bufferCases[] =
+       {
+               { (VkBufferCreateFlags)0,                                                                                                                                                                                               "regular"                                       },
+               { VK_BUFFER_CREATE_SPARSE_BINDING_BIT,                                                                                                                                                                  "sparse"                                        },
+               { VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,                                                                                  "sparse_residency"                      },
+               { VK_BUFFER_CREATE_SPARSE_BINDING_BIT                                                                                   | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,  "sparse_aliased"                        },
+               { VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT   | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,  "sparse_residency_aliased"      },
+       };
+
+       de::MovePtr<tcu::TestCaseGroup> bufferGroup(new tcu::TestCaseGroup(group->getTestContext(), "buffer", ""));
+
+       for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bufferCases); ++ndx)
+               addFunctionTestCase(bufferGroup.get(), bufferCases[ndx].name, "", bufferCases[ndx].flags);
+
+       group->addChild(bufferGroup.release());
+}
+
+void BufferMemoryRequirementsOriginal::addFunctionTestCase (tcu::TestCaseGroup*        group,
+                                                                                                                       const std::string&      name,
+                                                                                                                       const std::string&      desc,
+                                                                                                                       VkBufferCreateFlags     arg0)
+{
+       addFunctionCase(group, name, desc, testEntryPoint, arg0);
+}
+
+tcu::TestStatus BufferMemoryRequirementsOriginal::execTest (Context& context, const VkBufferCreateFlags bufferFlags)
+{
+       const DeviceInterface&                                  vk                      = context.getDeviceInterface();
+       const InstanceInterface&                                vki                     = context.getInstanceInterface();
+       const VkDevice                                                  device          = context.getDevice();
+       const VkPhysicalDevice                                  physDevice      = context.getPhysicalDevice();
+
+       preTestChecks(context, vki, physDevice, bufferFlags);
+
+       const VkPhysicalDeviceMemoryProperties  memoryProperties        = getPhysicalDeviceMemoryProperties(vki, physDevice);
+       const VkPhysicalDeviceLimits                    limits                          = getPhysicalDeviceProperties(vki, physDevice).limits;
+       const VkBufferUsageFlags                                allUsageFlags           = static_cast<VkBufferUsageFlags>((VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT << 1) - 1);
+       tcu::TestLog&                                                   log                                     = context.getTestContext().getLog();
+       bool                                                                    allPass                         = true;
+
+       const VkDeviceSize sizeCases[] =
+       {
+               1    * 1024,
+               8    * 1024,
+               64   * 1024,
+               1024 * 1024,
+       };
+
+       // Updates m_allUsageFlags* fields
+       updateMemoryRequirements(vk, device, 1024, bufferFlags, allUsageFlags, true); // doesn't depend on size
+
+       for (VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; usage <= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; usage = nextFlag(usage))
+       {
+               deUint32                previousMemoryTypeBits  = 0u;
+               VkDeviceSize    previousAlignment               = 0u;
+
+               log << tcu::TestLog::Message << "Verify a buffer with usage flags: " << de::toString(getBufferUsageFlagsStr(usage)) << tcu::TestLog::EndMessage;
+
+               for (const VkDeviceSize* pSize = sizeCases; pSize < sizeCases + DE_LENGTH_OF_ARRAY(sizeCases); ++pSize)
+               {
+                       log << tcu::TestLog::Message << "- size " << *pSize << " bytes" << tcu::TestLog::EndMessage;
+
+                       tcu::ResultCollector result(log, "ERROR: ");
+
+                       // Updates m_allUsageFlags* fields
+                       updateMemoryRequirements(vk, device, *pSize, bufferFlags, usage, false);
+
+                       // Check:
+                       // - requirements for a particular buffer usage
+                       // - memoryTypeBits are a subset of bits for requirements with all usage flags combined
+                       verifyMemoryRequirements(result, memoryProperties, limits, bufferFlags, usage);
+
+                       // Check that for the same usage and create flags:
+                       // - memoryTypeBits are the same
+                       // - alignment is the same
+                       if (pSize > sizeCases)
+                       {
+                               result.check(m_currentTestRequirements.memoryTypeBits == previousMemoryTypeBits,
+                                       "memoryTypeBits differ from the ones in the previous buffer size");
+
+                               result.check(m_currentTestRequirements.alignment == previousAlignment,
+                                       "alignment differs from the one in the previous buffer size");
+                       }
+
+                       if (result.getResult() != QP_TEST_RESULT_PASS)
+                               allPass = false;
+
+                       previousMemoryTypeBits  = m_currentTestRequirements.memoryTypeBits;
+                       previousAlignment               = m_currentTestRequirements.alignment;
+               }
+
+               if (!allPass)
+                       break;
+       }
+
+       return allPass ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Some memory requirements were incorrect");
+}
+
+void BufferMemoryRequirementsOriginal::preTestChecks (Context&                                                         ,
+                                                                                                         const InstanceInterface&                              vki,
+                                                                                                         const VkPhysicalDevice                                physDevice,
+                                                                                                         const VkBufferCreateFlags                             flags)
 {
        const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
 
@@ -119,18 +358,33 @@ void requireBufferSparseFeatures (const InstanceInterface& vki, const VkPhysical
                TCU_THROW(NotSupportedError, "Feature not supported: sparseResidencyAliased");
 }
 
-void verifyBufferRequirements (tcu::ResultCollector&                                   result,
-                                                          const VkPhysicalDeviceMemoryProperties&      deviceMemoryProperties,
-                                                          const VkMemoryRequirements&                          requirements,
-                                                          const VkMemoryRequirements&                          allUsageFlagsRequirements,
-                                                          const VkPhysicalDeviceLimits&                        limits,
-                                                          const VkBufferCreateFlags                            bufferFlags,
-                                                          const VkBufferUsageFlags                                     usage)
+void BufferMemoryRequirementsOriginal::updateMemoryRequirements (const DeviceInterface&                vk,
+                                                                                                                                const VkDevice                         device,
+                                                                                                                                const VkDeviceSize                     size,
+                                                                                                                                const VkBufferCreateFlags      flags,
+                                                                                                                                const VkBufferUsageFlags       usage,
+                                                                                                                                const bool                                     all)
+{
+       if (all)
+       {
+               m_allUsageFlagsRequirements     = getBufferMemoryRequirements(vk, device, size, flags, usage);
+       }
+       else
+       {
+               m_currentTestRequirements       = getBufferMemoryRequirements(vk, device, size, flags, usage);
+       }
+}
+
+void BufferMemoryRequirementsOriginal::verifyMemoryRequirements (tcu::ResultCollector&                                         result,
+                                                                                                                                const VkPhysicalDeviceMemoryProperties&        deviceMemoryProperties,
+                                                                                                                                const VkPhysicalDeviceLimits&                          limits,
+                                                                                                                                const VkBufferCreateFlags                                      bufferFlags,
+                                                                                                                                const VkBufferUsageFlags                                       usage)
 {
-       if (result.check(requirements.memoryTypeBits != 0, "VkMemoryRequirements memoryTypeBits has no bits set"))
+       if (result.check(m_currentTestRequirements.memoryTypeBits != 0, "VkMemoryRequirements memoryTypeBits has no bits set"))
        {
                typedef std::vector<deUint32>::const_iterator   IndexIterator;
-               const std::vector<deUint32>                                             usedMemoryTypeIndices                   = bitsToIndices(requirements.memoryTypeBits);
+               const std::vector<deUint32>                                             usedMemoryTypeIndices                   = bitsToIndices(m_currentTestRequirements.memoryTypeBits);
                bool                                                                                    deviceLocalMemoryFound                  = false;
                bool                                                                                    hostVisibleCoherentMemoryFound  = false;
 
@@ -154,24 +408,24 @@ void verifyBufferRequirements (tcu::ResultCollector&                                      result,
                                "Memory type includes VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT");
                }
 
-               result.check(deIsPowerOfTwo64(static_cast<deUint64>(requirements.alignment)) == DE_TRUE,
+               result.check(deIsPowerOfTwo64(static_cast<deUint64>(m_currentTestRequirements.alignment)) == DE_TRUE,
                        "VkMemoryRequirements alignment isn't power of two");
 
                if (usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT))
                {
-                       result.check(requirements.alignment >= limits.minTexelBufferOffsetAlignment,
+                       result.check(m_currentTestRequirements.alignment >= limits.minTexelBufferOffsetAlignment,
                                "VkMemoryRequirements alignment doesn't respect minTexelBufferOffsetAlignment");
                }
 
                if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
                {
-                       result.check(requirements.alignment >= limits.minUniformBufferOffsetAlignment,
+                       result.check(m_currentTestRequirements.alignment >= limits.minUniformBufferOffsetAlignment,
                                "VkMemoryRequirements alignment doesn't respect minUniformBufferOffsetAlignment");
                }
 
                if (usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
                {
-                       result.check(requirements.alignment >= limits.minStorageBufferOffsetAlignment,
+                       result.check(m_currentTestRequirements.alignment >= limits.minStorageBufferOffsetAlignment,
                                "VkMemoryRequirements alignment doesn't respect minStorageBufferOffsetAlignment");
                }
 
@@ -181,81 +435,358 @@ void verifyBufferRequirements (tcu::ResultCollector&                                     result,
                result.check((bufferFlags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) || hostVisibleCoherentMemoryFound,
                        "Required memory type doesn't include VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT and VK_MEMORY_PROPERTY_HOST_COHERENT_BIT");
 
-               result.check((requirements.memoryTypeBits & allUsageFlagsRequirements.memoryTypeBits) == allUsageFlagsRequirements.memoryTypeBits,
+               result.check((m_currentTestRequirements.memoryTypeBits & m_allUsageFlagsRequirements.memoryTypeBits) == m_allUsageFlagsRequirements.memoryTypeBits,
                        "Memory type bits aren't a superset of memory type bits for all usage flags combined");
        }
 }
 
-tcu::TestStatus testBuffer (Context& context, const VkBufferCreateFlags bufferFlags)
+class BufferMemoryRequirementsExtended : public BufferMemoryRequirementsOriginal
+{
+       static tcu::TestStatus testEntryPoint   (Context&                                       context,
+                                                                                        const VkBufferCreateFlags      bufferFlags);
+
+protected:
+       virtual void addFunctionTestCase                (tcu::TestCaseGroup*            group,
+                                                                                        const std::string&                     name,
+                                                                                        const std::string&                     desc,
+                                                                                        VkBufferCreateFlags            arg0);
+
+       virtual void preTestChecks                              (Context&                                       context,
+                                                                                        const InstanceInterface&       vki,
+                                                                                        const VkPhysicalDevice         physDevice,
+                                                                                        const VkBufferCreateFlags      flags);
+
+       virtual void updateMemoryRequirements   (const DeviceInterface&         vk,
+                                                                                        const VkDevice                         device,
+                                                                                        const VkDeviceSize                     size,
+                                                                                        const VkBufferCreateFlags      flags,
+                                                                                        const VkBufferUsageFlags       usage,
+                                                                                        const bool                                     all);
+};
+
+tcu::TestStatus BufferMemoryRequirementsExtended::testEntryPoint (Context& context, const VkBufferCreateFlags bufferFlags)
+{
+       BufferMemoryRequirementsExtended test;
+
+       return test.execTest(context, bufferFlags);
+}
+
+void BufferMemoryRequirementsExtended::addFunctionTestCase (tcu::TestCaseGroup*        group,
+                                                                                                                       const std::string&      name,
+                                                                                                                       const std::string&      desc,
+                                                                                                                       VkBufferCreateFlags     arg0)
+{
+       addFunctionCase(group, name, desc, testEntryPoint, arg0);
+}
+
+void BufferMemoryRequirementsExtended::preTestChecks (Context&                                 context,
+                                                                                                         const InstanceInterface&      vki,
+                                                                                                         const VkPhysicalDevice        physDevice,
+                                                                                                         const VkBufferCreateFlags     flags)
+{
+       const std::string extensionName("VK_KHR_get_memory_requirements2");
+
+       if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), extensionName))
+               TCU_THROW(NotSupportedError, std::string(extensionName + " is not supported").c_str());
+
+       BufferMemoryRequirementsOriginal::preTestChecks(context, vki, physDevice, flags);
+}
+
+void BufferMemoryRequirementsExtended::updateMemoryRequirements (const DeviceInterface&                vk,
+                                                                                                                                const VkDevice                         device,
+                                                                                                                                const VkDeviceSize                     size,
+                                                                                                                                const VkBufferCreateFlags      flags,
+                                                                                                                                const VkBufferUsageFlags       usage,
+                                                                                                                                const bool                                     all)
+{
+       if (all)
+       {
+               m_allUsageFlagsRequirements     = getBufferMemoryRequirements2(vk, device, size, flags, usage);
+       }
+       else
+       {
+               m_currentTestRequirements       = getBufferMemoryRequirements2(vk, device, size, flags, usage);
+       }
+}
+
+
+class BufferMemoryRequirementsDedicatedAllocation : public BufferMemoryRequirementsExtended
 {
-       const DeviceInterface&                                  vk                                                      = context.getDeviceInterface();
-       const InstanceInterface&                                vki                                                     = context.getInstanceInterface();
-       const VkDevice                                                  device                                          = context.getDevice();
-       const VkPhysicalDevice                                  physDevice                                      = context.getPhysicalDevice();
+       static tcu::TestStatus testEntryPoint   (Context&                                                                       context,
+                                                                                        const VkBufferCreateFlags                                      bufferFlags);
+
+protected:
+       virtual void addFunctionTestCase                (tcu::TestCaseGroup*                                            group,
+                                                                                        const std::string&                                                     name,
+                                                                                        const std::string&                                                     desc,
+                                                                                        VkBufferCreateFlags                                            arg0);
+
+       virtual void preTestChecks                              (Context&                                                                       context,
+                                                                                        const InstanceInterface&                                       vki,
+                                                                                        const VkPhysicalDevice                                         physDevice,
+                                                                                        const VkBufferCreateFlags                                      flags);
+
+       virtual void updateMemoryRequirements   (const DeviceInterface&                                         vk,
+                                                                                        const VkDevice                                                         device,
+                                                                                        const VkDeviceSize                                                     size,
+                                                                                        const VkBufferCreateFlags                                      flags,
+                                                                                        const VkBufferUsageFlags                                       usage,
+                                                                                        const bool                                                                     all);
+
+       virtual void verifyMemoryRequirements   (tcu::ResultCollector&                                          result,
+                                                                                        const VkPhysicalDeviceMemoryProperties&        deviceMemoryProperties,
+                                                                                        const VkPhysicalDeviceLimits&                          limits,
+                                                                                        const VkBufferCreateFlags                                      bufferFlags,
+                                                                                        const VkBufferUsageFlags                                       usage);
+
+protected:
+       VkBool32        m_allUsageFlagsPrefersDedicatedAllocation;
+       VkBool32        m_allUsageFlagsRequiresDedicatedAllocation;
+
+       VkBool32        m_currentTestPrefersDedicatedAllocation;
+       VkBool32        m_currentTestRequiresDedicatedAllocation;
+};
 
-       requireBufferSparseFeatures(vki, physDevice, bufferFlags);
 
-       const VkPhysicalDeviceMemoryProperties  memoryProperties                        = getPhysicalDeviceMemoryProperties(vki, physDevice);
-       const VkPhysicalDeviceLimits                    limits                                          = getPhysicalDeviceProperties(vki, physDevice).limits;
-       const VkBufferUsageFlags                                allUsageFlags                           = static_cast<VkBufferUsageFlags>((VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT << 1) - 1);
-       const VkMemoryRequirements                              allUsageFlagsRequirements       = getBufferMemoryRequirements(vk, device, 1024, bufferFlags, allUsageFlags); // doesn't depend on size
-       tcu::TestLog&                                                   log                                                     = context.getTestContext().getLog();
-       bool                                                                    allPass                                         = true;
+tcu::TestStatus BufferMemoryRequirementsDedicatedAllocation::testEntryPoint(Context& context, const VkBufferCreateFlags bufferFlags)
+{
+       BufferMemoryRequirementsDedicatedAllocation test;
 
-       const VkDeviceSize sizeCases[] =
+       return test.execTest(context, bufferFlags);
+}
+
+void BufferMemoryRequirementsDedicatedAllocation::addFunctionTestCase (tcu::TestCaseGroup*     group,
+                                                                                                                                          const std::string&   name,
+                                                                                                                                          const std::string&   desc,
+                                                                                                                                          VkBufferCreateFlags  arg0)
+{
+       addFunctionCase(group, name, desc, testEntryPoint, arg0);
+}
+
+void BufferMemoryRequirementsDedicatedAllocation::preTestChecks (Context&                                      context,
+                                                                                                                                const InstanceInterface&       vki,
+                                                                                                                                const VkPhysicalDevice         physDevice,
+                                                                                                                                const VkBufferCreateFlags      flags)
+{
+       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());
+
+       BufferMemoryRequirementsExtended::preTestChecks(context, vki, physDevice, flags);
+}
+
+void BufferMemoryRequirementsDedicatedAllocation::updateMemoryRequirements (const DeviceInterface&             vk,
+                                                                                                                                                       const VkDevice                          device,
+                                                                                                                                                       const VkDeviceSize                      size,
+                                                                                                                                                       const VkBufferCreateFlags       flags,
+                                                                                                                                                       const VkBufferUsageFlags        usage,
+                                                                                                                                                       const bool                                      all)
+{
+       const deUint32                                          invalidVkBool32                 = static_cast<deUint32>(~0);
+
+       VkMemoryDedicatedRequirementsKHR        dedicatedRequirements   =
        {
-               1        * 1024,
-               8    * 1024,
-               64   * 1024,
-               1024 * 1024,
+               VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,    // VkStructureType      sType
+               DE_NULL,                                                                                                // void*                        pNext
+               invalidVkBool32,                                                                                // VkBool32                     prefersDedicatedAllocation
+               invalidVkBool32                                                                                 // VkBool32                     requiresDedicatedAllocation
        };
 
-       for (VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; usage <= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; usage = nextFlag(usage))
+       if (all)
        {
-               deUint32                previousMemoryTypeBits  = 0u;
-               VkDeviceSize    previousAlignment               = 0u;
+               m_allUsageFlagsRequirements                                     = getBufferMemoryRequirements2(vk, device, size, flags, usage, &dedicatedRequirements);
+               m_allUsageFlagsPrefersDedicatedAllocation       = dedicatedRequirements.prefersDedicatedAllocation;
+               m_allUsageFlagsRequiresDedicatedAllocation      = dedicatedRequirements.requiresDedicatedAllocation;
 
-               log << tcu::TestLog::Message << "Verify a buffer with usage flags: " << de::toString(getBufferUsageFlagsStr(usage)) << tcu::TestLog::EndMessage;
+               TCU_CHECK(validValueVkBool32(m_allUsageFlagsPrefersDedicatedAllocation));
+               // Test design expects m_allUsageFlagsRequiresDedicatedAllocation to be false
+               TCU_CHECK(m_allUsageFlagsRequiresDedicatedAllocation == VK_FALSE);
+       }
+       else
+       {
+               m_currentTestRequirements                                       = getBufferMemoryRequirements2(vk, device, size, flags, usage, &dedicatedRequirements);
+               m_currentTestPrefersDedicatedAllocation         = dedicatedRequirements.prefersDedicatedAllocation;
+               m_currentTestRequiresDedicatedAllocation        = dedicatedRequirements.requiresDedicatedAllocation;
+       }
+}
 
-               for (const VkDeviceSize* pSize = sizeCases; pSize < sizeCases + DE_LENGTH_OF_ARRAY(sizeCases); ++pSize)
-               {
-                       log << tcu::TestLog::Message << "- size " << *pSize << " bytes" << tcu::TestLog::EndMessage;
+void BufferMemoryRequirementsDedicatedAllocation::verifyMemoryRequirements (tcu::ResultCollector&                                      result,
+                                                                                                                                                       const VkPhysicalDeviceMemoryProperties& deviceMemoryProperties,
+                                                                                                                                                       const VkPhysicalDeviceLimits&                   limits,
+                                                                                                                                                       const VkBufferCreateFlags                               bufferFlags,
+                                                                                                                                                       const VkBufferUsageFlags                                usage)
+{
+       BufferMemoryRequirementsExtended::verifyMemoryRequirements(result, deviceMemoryProperties, limits, bufferFlags, usage);
 
-                       const VkMemoryRequirements      requirements    = getBufferMemoryRequirements(vk, device, *pSize, bufferFlags, usage);
-                       tcu::ResultCollector            result                  (log, "ERROR: ");
+       result.check(validValueVkBool32(m_currentTestPrefersDedicatedAllocation),
+               "Invalid VkBool32 value in m_currentTestPrefersDedicatedAllocation");
 
-                       // Check:
-                       // - requirements for a particular buffer usage
-                       // - memoryTypeBits are a subset of bits for requirements with all usage flags combined
-                       verifyBufferRequirements(result, memoryProperties, requirements, allUsageFlagsRequirements, limits, bufferFlags, usage);
+       result.check(m_currentTestRequiresDedicatedAllocation == VK_FALSE,
+               "Regular (non-shared) objects must not require dedicated allocations");
 
-                       // Check that for the same usage and create flags:
-                       // - memoryTypeBits are the same
-                       // - alignment is the same
-                       if (pSize > sizeCases)
-                       {
-                               result.check(requirements.memoryTypeBits == previousMemoryTypeBits,
-                                       "memoryTypeBits differ from the ones in the previous buffer size");
+       result.check(m_currentTestPrefersDedicatedAllocation == VK_FALSE || m_currentTestPrefersDedicatedAllocation == VK_FALSE,
+               "Preferred and required flags for dedicated memory cannot be set to true at the same time");
+}
 
-                               result.check(requirements.alignment == previousAlignment,
-                                       "alignment differs from the one in the previous buffer size");
-                       }
 
-                       if (result.getResult() != QP_TEST_RESULT_PASS)
-                               allPass = false;
+struct ImageTestParams
+{
+       ImageTestParams (VkImageCreateFlags             flags_,
+                                        VkImageTiling                  tiling_,
+                                        bool                                   transient_)
+       : flags         (flags_)
+       , tiling        (tiling_)
+       , transient     (transient_)
+       {
+       }
+
+       ImageTestParams (void)
+       {
+       }
+
+       VkImageCreateFlags              flags;
+       VkImageTiling                   tiling;
+       bool                                    transient;
+};
+
+class IImageMemoryRequirements
+{
+public:
+       virtual void populateTestGroup                  (tcu::TestCaseGroup*                                            group) = 0;
+
+protected:
+       virtual void addFunctionTestCase                (tcu::TestCaseGroup*                                            group,
+                                                                                        const std::string&                                                     name,
+                                                                                        const std::string&                                                     desc,
+                                                                                        const ImageTestParams                                          arg0) = 0;
+
+       virtual tcu::TestStatus execTest                (Context&                                                                       context,
+                                                                                        const ImageTestParams                                          bufferFlags) = 0;
+
+       virtual void preTestChecks                              (Context&                                                                       context,
+                                                                                        const InstanceInterface&                                       vki,
+                                                                                        const VkPhysicalDevice                                         physDevice,
+                                                                                        const VkImageCreateFlags                                       flags) = 0;
+
+       virtual void updateMemoryRequirements   (const DeviceInterface&                                         vk,
+                                                                                        const VkDevice                                                         device) = 0;
+
+       virtual void verifyMemoryRequirements   (tcu::ResultCollector&                                          result,
+                                                                                        const VkPhysicalDeviceMemoryProperties&        deviceMemoryProperties) = 0;
+};
+
+class ImageMemoryRequirementsOriginal : public IImageMemoryRequirements
+{
+       static tcu::TestStatus testEntryPoint   (Context&                                                                       context,
+                                                                                        const ImageTestParams                                          params);
+
+public:
+       virtual void populateTestGroup                  (tcu::TestCaseGroup*                                            group);
 
-                       previousMemoryTypeBits  = requirements.memoryTypeBits;
-                       previousAlignment               = requirements.alignment;
+protected:
+       virtual void addFunctionTestCase                (tcu::TestCaseGroup*                                            group,
+                                                                                        const std::string&                                                     name,
+                                                                                        const std::string&                                                     desc,
+                                                                                        const ImageTestParams                                          arg0);
+
+       virtual tcu::TestStatus execTest                (Context&                                                                       context,
+                                                                                        const ImageTestParams                                          params);
+
+       virtual void preTestChecks                              (Context&                                                                       context,
+                                                                                        const InstanceInterface&                                       vki,
+                                                                                        const VkPhysicalDevice                                         physDevice,
+                                                                                        const VkImageCreateFlags                                       flags);
+
+       virtual void updateMemoryRequirements   (const DeviceInterface&                                         vk,
+                                                                                        const VkDevice                                                         device);
+
+       virtual void verifyMemoryRequirements   (tcu::ResultCollector&                                          result,
+                                                                                        const VkPhysicalDeviceMemoryProperties&        deviceMemoryProperties);
+
+private:
+       virtual bool isImageSupported                   (const InstanceInterface&                                       vki,
+                                                                                        const VkPhysicalDevice                                         physDevice,
+                                                                                        const std::vector<std::string>&                        deviceExtensions,
+                                                                                        const VkImageCreateInfo&                                       info);
+
+       virtual bool isFormatMatchingAspect             (const VkFormat                                                         format,
+                                                                                        const VkImageAspectFlags                                       aspect);
+
+protected:
+       VkImageCreateInfo               m_currentTestImageInfo;
+       VkMemoryRequirements    m_currentTestRequirements;
+};
+
+
+tcu::TestStatus ImageMemoryRequirementsOriginal::testEntryPoint (Context& context, const ImageTestParams params)
+{
+       ImageMemoryRequirementsOriginal test;
+
+       return test.execTest(context, params);
+}
+
+void ImageMemoryRequirementsOriginal::populateTestGroup (tcu::TestCaseGroup* group)
+{
+       const struct
+       {
+               VkImageCreateFlags              flags;
+               bool                                    transient;
+               const char* const               name;
+       } imageFlagsCases[] =
+       {
+               { (VkImageCreateFlags)0,                                                                                                                                                                                                false,  "regular"                                       },
+               { (VkImageCreateFlags)0,                                                                                                                                                                                                true,   "transient"                                     },
+               { VK_IMAGE_CREATE_SPARSE_BINDING_BIT,                                                                                                                                                                   false,  "sparse"                                        },
+               { VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,                                                                                    false,  "sparse_residency"                      },
+               { VK_IMAGE_CREATE_SPARSE_BINDING_BIT                                                                                    | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,   false,  "sparse_aliased"                        },
+               { VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT             | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,   false,  "sparse_residency_aliased"      },
+       };
+
+       de::MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(group->getTestContext(), "image", ""));
+
+       for (int flagsNdx = 0; flagsNdx < DE_LENGTH_OF_ARRAY(imageFlagsCases); ++flagsNdx)
+       for (int tilingNdx = 0; tilingNdx <= 1; ++tilingNdx)
+       {
+               ImageTestParams         params;
+               std::ostringstream      caseName;
+
+               params.flags            =  imageFlagsCases[flagsNdx].flags;
+               params.transient        =  imageFlagsCases[flagsNdx].transient;
+               caseName                        << imageFlagsCases[flagsNdx].name;
+
+               if (tilingNdx != 0)
+               {
+                       params.tiling =  VK_IMAGE_TILING_OPTIMAL;
+                       caseName      << "_tiling_optimal";
+               }
+               else
+               {
+                       params.tiling =  VK_IMAGE_TILING_LINEAR;
+                       caseName      << "_tiling_linear";
                }
 
-               if (!allPass)
-                       break;
+               if ((params.flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) && (params.tiling == VK_IMAGE_TILING_LINEAR))
+                       continue;
+
+               addFunctionTestCase(imageGroup.get(), caseName.str(), "", params);
        }
 
-       return allPass ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Some memory requirements were incorrect");
+       group->addChild(imageGroup.release());
+}
+
+void ImageMemoryRequirementsOriginal::addFunctionTestCase (tcu::TestCaseGroup*         group,
+                                                                                                                  const std::string&           name,
+                                                                                                                  const std::string&           desc,
+                                                                                                                  const ImageTestParams        arg0)
+{
+       addFunctionCase(group, name, desc, testEntryPoint, arg0);
 }
 
-void requireImageSparseFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkImageCreateFlags createFlags)
+void ImageMemoryRequirementsOriginal::preTestChecks (Context&                                  ,
+                                                                                                        const InstanceInterface&       vki,
+                                                                                                        const VkPhysicalDevice         physDevice,
+                                                                                                        const VkImageCreateFlags       createFlags)
 {
        const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
 
@@ -269,7 +800,59 @@ void requireImageSparseFeatures (const InstanceInterface& vki, const VkPhysicalD
                TCU_THROW(NotSupportedError, "Feature not supported: sparseResidencyAliased");
 }
 
-bool imageUsageMatchesFormatFeatures (const VkImageUsageFlags usage, const VkFormatFeatureFlags featureFlags)
+void ImageMemoryRequirementsOriginal::updateMemoryRequirements (const DeviceInterface&         vk,
+                                                                                                                                const VkDevice                         device)
+{
+       const Unique<VkImage> image(createImage(vk, device, &m_currentTestImageInfo));
+
+       m_currentTestRequirements = getImageMemoryRequirements(vk, device, *image);
+}
+
+void ImageMemoryRequirementsOriginal::verifyMemoryRequirements (tcu::ResultCollector&                                  result,
+                                                                                                                               const VkPhysicalDeviceMemoryProperties& deviceMemoryProperties)
+{
+       if (result.check(m_currentTestRequirements.memoryTypeBits != 0, "VkMemoryRequirements memoryTypeBits has no bits set"))
+       {
+               typedef std::vector<deUint32>::const_iterator   IndexIterator;
+               const std::vector<deUint32>                                             usedMemoryTypeIndices                   = bitsToIndices(m_currentTestRequirements.memoryTypeBits);
+               bool                                                                                    deviceLocalMemoryFound                  = false;
+               bool                                                                                    hostVisibleCoherentMemoryFound  = false;
+
+               for (IndexIterator memoryTypeNdx = usedMemoryTypeIndices.begin(); memoryTypeNdx != usedMemoryTypeIndices.end(); ++memoryTypeNdx)
+               {
+                       if (*memoryTypeNdx >= deviceMemoryProperties.memoryTypeCount)
+                       {
+                               result.fail("VkMemoryRequirements memoryTypeBits contains bits for non-existing memory types");
+                               continue;
+                       }
+
+                       const VkMemoryPropertyFlags     memoryPropertyFlags = deviceMemoryProperties.memoryTypes[*memoryTypeNdx].propertyFlags;
+
+                       if (memoryPropertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
+                               deviceLocalMemoryFound = true;
+
+                       if (memoryPropertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
+                               hostVisibleCoherentMemoryFound = true;
+
+                       if (memoryPropertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
+                       {
+                               result.check((m_currentTestImageInfo.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) != 0u,
+                                       "Memory type includes VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT for a non-transient attachment image");
+                       }
+               }
+
+               result.check(deIsPowerOfTwo64(static_cast<deUint64>(m_currentTestRequirements.alignment)) == DE_TRUE,
+                       "VkMemoryRequirements alignment isn't power of two");
+
+               result.check(deviceLocalMemoryFound,
+                       "None of the required memory types included VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT");
+
+               result.check(m_currentTestImageInfo.tiling == VK_IMAGE_TILING_OPTIMAL || hostVisibleCoherentMemoryFound,
+                       "Required memory type doesn't include VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT and VK_MEMORY_PROPERTY_HOST_COHERENT_BIT");
+       }
+}
+
+bool isUsageMatchesFeatures (const VkImageUsageFlags usage, const VkFormatFeatureFlags featureFlags)
 {
        if ((usage & VK_IMAGE_USAGE_SAMPLED_BIT) && (featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
                return true;
@@ -284,10 +867,20 @@ bool imageUsageMatchesFormatFeatures (const VkImageUsageFlags usage, const VkFor
 }
 
 //! This catches both invalid as well as legal but unsupported combinations of image parameters
-bool isImageSupported (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkImageCreateInfo& info)
+bool ImageMemoryRequirementsOriginal::isImageSupported (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const std::vector<std::string>& deviceExtensions, const VkImageCreateInfo& info)
 {
        DE_ASSERT(info.extent.width >= 1u && info.extent.height >= 1u && info.extent.depth >= 1u);
 
+       if ((isYCbCrFormat(info.format)
+               && (info.imageType != VK_IMAGE_TYPE_2D
+                       || info.mipLevels != 1
+                       || info.arrayLayers != 1
+                       || info.samples != VK_SAMPLE_COUNT_1_BIT))
+                       || !de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_KHR_sampler_ycbcr_conversion"))
+       {
+               return false;
+       }
+
        if (info.imageType == VK_IMAGE_TYPE_1D)
        {
                DE_ASSERT(info.extent.height == 1u && info.extent.depth == 1u);
@@ -415,7 +1008,7 @@ bool isImageSupported (const InstanceInterface& vki, const VkPhysicalDevice phys
        const VkFormatFeatureFlags      formatFeatures          = (info.tiling == VK_IMAGE_TILING_LINEAR ? formatProperties.linearTilingFeatures
                                                                                                                                                                                         : formatProperties.optimalTilingFeatures);
 
-       if (!imageUsageMatchesFormatFeatures(info.usage, formatFeatures))
+       if (!isUsageMatchesFeatures(info.usage, formatFeatures))
                return false;
 
        VkImageFormatProperties         imageFormatProperties;
@@ -447,7 +1040,7 @@ VkExtent3D makeExtentForImage (const VkImageType imageType)
        return extent;
 }
 
-bool isFormatMatchingAspect (const VkFormat format, const VkImageAspectFlags aspect)
+bool ImageMemoryRequirementsOriginal::isFormatMatchingAspect (const VkFormat format, const VkImageAspectFlags aspect)
 {
        DE_ASSERT(aspect == VK_IMAGE_ASPECT_COLOR_BIT || aspect == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
 
@@ -457,52 +1050,6 @@ bool isFormatMatchingAspect (const VkFormat format, const VkImageAspectFlags asp
        return (aspect == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == isDepthStencilFormat;
 }
 
-void verifyImageRequirements (tcu::ResultCollector&                                            result,
-                                                         const VkPhysicalDeviceMemoryProperties&       deviceMemoryProperties,
-                                                         const VkMemoryRequirements&                           requirements,
-                                                         const VkImageCreateInfo&                                      imageInfo)
-{
-       if (result.check(requirements.memoryTypeBits != 0, "VkMemoryRequirements memoryTypeBits has no bits set"))
-       {
-               typedef std::vector<deUint32>::const_iterator   IndexIterator;
-               const std::vector<deUint32>                                             usedMemoryTypeIndices                   = bitsToIndices(requirements.memoryTypeBits);
-               bool                                                                                    deviceLocalMemoryFound                  = false;
-               bool                                                                                    hostVisibleCoherentMemoryFound  = false;
-
-               for (IndexIterator memoryTypeNdx = usedMemoryTypeIndices.begin(); memoryTypeNdx != usedMemoryTypeIndices.end(); ++memoryTypeNdx)
-               {
-                       if (*memoryTypeNdx >= deviceMemoryProperties.memoryTypeCount)
-                       {
-                               result.fail("VkMemoryRequirements memoryTypeBits contains bits for non-existing memory types");
-                               continue;
-                       }
-
-                       const VkMemoryPropertyFlags     memoryPropertyFlags = deviceMemoryProperties.memoryTypes[*memoryTypeNdx].propertyFlags;
-
-                       if (memoryPropertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
-                               deviceLocalMemoryFound = true;
-
-                       if (memoryPropertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
-                               hostVisibleCoherentMemoryFound = true;
-
-                       if (memoryPropertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
-                       {
-                               result.check((imageInfo.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) != 0u,
-                                       "Memory type includes VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT for a non-transient attachment image");
-                       }
-               }
-
-               result.check(deIsPowerOfTwo64(static_cast<deUint64>(requirements.alignment)) == DE_TRUE,
-                       "VkMemoryRequirements alignment isn't power of two");
-
-               result.check(deviceLocalMemoryFound,
-                       "None of the required memory types included VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT");
-
-               result.check(imageInfo.tiling == VK_IMAGE_TILING_OPTIMAL || hostVisibleCoherentMemoryFound,
-                       "Required memory type doesn't include VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT and VK_MEMORY_PROPERTY_HOST_COHERENT_BIT");
-       }
-}
-
 std::string getImageInfoString (const VkImageCreateInfo& imageInfo)
 {
        std::ostringstream str;
@@ -531,15 +1078,229 @@ std::string getImageInfoString (const VkImageCreateInfo& imageInfo)
        return str.str();
 }
 
-struct ImageParams
-{
-       VkImageCreateFlags              flags;
-       VkImageTiling                   tiling;
-       bool                                    transient;
-};
-
-tcu::TestStatus testImage (Context& context, const ImageParams params)
+tcu::TestStatus ImageMemoryRequirementsOriginal::execTest (Context& context, const ImageTestParams params)
 {
+       const VkFormat                          formats[]               =
+       {
+               VK_FORMAT_R4G4_UNORM_PACK8,
+               VK_FORMAT_R4G4B4A4_UNORM_PACK16,
+               VK_FORMAT_B4G4R4A4_UNORM_PACK16,
+               VK_FORMAT_R5G6B5_UNORM_PACK16,
+               VK_FORMAT_B5G6R5_UNORM_PACK16,
+               VK_FORMAT_R5G5B5A1_UNORM_PACK16,
+               VK_FORMAT_B5G5R5A1_UNORM_PACK16,
+               VK_FORMAT_A1R5G5B5_UNORM_PACK16,
+               VK_FORMAT_R8_UNORM,
+               VK_FORMAT_R8_SNORM,
+               VK_FORMAT_R8_USCALED,
+               VK_FORMAT_R8_SSCALED,
+               VK_FORMAT_R8_UINT,
+               VK_FORMAT_R8_SINT,
+               VK_FORMAT_R8_SRGB,
+               VK_FORMAT_R8G8_UNORM,
+               VK_FORMAT_R8G8_SNORM,
+               VK_FORMAT_R8G8_USCALED,
+               VK_FORMAT_R8G8_SSCALED,
+               VK_FORMAT_R8G8_UINT,
+               VK_FORMAT_R8G8_SINT,
+               VK_FORMAT_R8G8_SRGB,
+               VK_FORMAT_R8G8B8_UNORM,
+               VK_FORMAT_R8G8B8_SNORM,
+               VK_FORMAT_R8G8B8_USCALED,
+               VK_FORMAT_R8G8B8_SSCALED,
+               VK_FORMAT_R8G8B8_UINT,
+               VK_FORMAT_R8G8B8_SINT,
+               VK_FORMAT_R8G8B8_SRGB,
+               VK_FORMAT_B8G8R8_UNORM,
+               VK_FORMAT_B8G8R8_SNORM,
+               VK_FORMAT_B8G8R8_USCALED,
+               VK_FORMAT_B8G8R8_SSCALED,
+               VK_FORMAT_B8G8R8_UINT,
+               VK_FORMAT_B8G8R8_SINT,
+               VK_FORMAT_B8G8R8_SRGB,
+               VK_FORMAT_R8G8B8A8_UNORM,
+               VK_FORMAT_R8G8B8A8_SNORM,
+               VK_FORMAT_R8G8B8A8_USCALED,
+               VK_FORMAT_R8G8B8A8_SSCALED,
+               VK_FORMAT_R8G8B8A8_UINT,
+               VK_FORMAT_R8G8B8A8_SINT,
+               VK_FORMAT_R8G8B8A8_SRGB,
+               VK_FORMAT_B8G8R8A8_UNORM,
+               VK_FORMAT_B8G8R8A8_SNORM,
+               VK_FORMAT_B8G8R8A8_USCALED,
+               VK_FORMAT_B8G8R8A8_SSCALED,
+               VK_FORMAT_B8G8R8A8_UINT,
+               VK_FORMAT_B8G8R8A8_SINT,
+               VK_FORMAT_B8G8R8A8_SRGB,
+               VK_FORMAT_A8B8G8R8_UNORM_PACK32,
+               VK_FORMAT_A8B8G8R8_SNORM_PACK32,
+               VK_FORMAT_A8B8G8R8_USCALED_PACK32,
+               VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
+               VK_FORMAT_A8B8G8R8_UINT_PACK32,
+               VK_FORMAT_A8B8G8R8_SINT_PACK32,
+               VK_FORMAT_A8B8G8R8_SRGB_PACK32,
+               VK_FORMAT_A2R10G10B10_UNORM_PACK32,
+               VK_FORMAT_A2R10G10B10_SNORM_PACK32,
+               VK_FORMAT_A2R10G10B10_USCALED_PACK32,
+               VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
+               VK_FORMAT_A2R10G10B10_UINT_PACK32,
+               VK_FORMAT_A2R10G10B10_SINT_PACK32,
+               VK_FORMAT_A2B10G10R10_UNORM_PACK32,
+               VK_FORMAT_A2B10G10R10_SNORM_PACK32,
+               VK_FORMAT_A2B10G10R10_USCALED_PACK32,
+               VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
+               VK_FORMAT_A2B10G10R10_UINT_PACK32,
+               VK_FORMAT_A2B10G10R10_SINT_PACK32,
+               VK_FORMAT_R16_UNORM,
+               VK_FORMAT_R16_SNORM,
+               VK_FORMAT_R16_USCALED,
+               VK_FORMAT_R16_SSCALED,
+               VK_FORMAT_R16_UINT,
+               VK_FORMAT_R16_SINT,
+               VK_FORMAT_R16_SFLOAT,
+               VK_FORMAT_R16G16_UNORM,
+               VK_FORMAT_R16G16_SNORM,
+               VK_FORMAT_R16G16_USCALED,
+               VK_FORMAT_R16G16_SSCALED,
+               VK_FORMAT_R16G16_UINT,
+               VK_FORMAT_R16G16_SINT,
+               VK_FORMAT_R16G16_SFLOAT,
+               VK_FORMAT_R16G16B16_UNORM,
+               VK_FORMAT_R16G16B16_SNORM,
+               VK_FORMAT_R16G16B16_USCALED,
+               VK_FORMAT_R16G16B16_SSCALED,
+               VK_FORMAT_R16G16B16_UINT,
+               VK_FORMAT_R16G16B16_SINT,
+               VK_FORMAT_R16G16B16_SFLOAT,
+               VK_FORMAT_R16G16B16A16_UNORM,
+               VK_FORMAT_R16G16B16A16_SNORM,
+               VK_FORMAT_R16G16B16A16_USCALED,
+               VK_FORMAT_R16G16B16A16_SSCALED,
+               VK_FORMAT_R16G16B16A16_UINT,
+               VK_FORMAT_R16G16B16A16_SINT,
+               VK_FORMAT_R16G16B16A16_SFLOAT,
+               VK_FORMAT_R32_UINT,
+               VK_FORMAT_R32_SINT,
+               VK_FORMAT_R32_SFLOAT,
+               VK_FORMAT_R32G32_UINT,
+               VK_FORMAT_R32G32_SINT,
+               VK_FORMAT_R32G32_SFLOAT,
+               VK_FORMAT_R32G32B32_UINT,
+               VK_FORMAT_R32G32B32_SINT,
+               VK_FORMAT_R32G32B32_SFLOAT,
+               VK_FORMAT_R32G32B32A32_UINT,
+               VK_FORMAT_R32G32B32A32_SINT,
+               VK_FORMAT_R32G32B32A32_SFLOAT,
+               VK_FORMAT_R64_UINT,
+               VK_FORMAT_R64_SINT,
+               VK_FORMAT_R64_SFLOAT,
+               VK_FORMAT_R64G64_UINT,
+               VK_FORMAT_R64G64_SINT,
+               VK_FORMAT_R64G64_SFLOAT,
+               VK_FORMAT_R64G64B64_UINT,
+               VK_FORMAT_R64G64B64_SINT,
+               VK_FORMAT_R64G64B64_SFLOAT,
+               VK_FORMAT_R64G64B64A64_UINT,
+               VK_FORMAT_R64G64B64A64_SINT,
+               VK_FORMAT_R64G64B64A64_SFLOAT,
+               VK_FORMAT_B10G11R11_UFLOAT_PACK32,
+               VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
+               VK_FORMAT_D16_UNORM,
+               VK_FORMAT_X8_D24_UNORM_PACK32,
+               VK_FORMAT_D32_SFLOAT,
+               VK_FORMAT_S8_UINT,
+               VK_FORMAT_D16_UNORM_S8_UINT,
+               VK_FORMAT_D24_UNORM_S8_UINT,
+               VK_FORMAT_D32_SFLOAT_S8_UINT,
+               VK_FORMAT_BC1_RGB_UNORM_BLOCK,
+               VK_FORMAT_BC1_RGB_SRGB_BLOCK,
+               VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
+               VK_FORMAT_BC1_RGBA_SRGB_BLOCK,
+               VK_FORMAT_BC2_UNORM_BLOCK,
+               VK_FORMAT_BC2_SRGB_BLOCK,
+               VK_FORMAT_BC3_UNORM_BLOCK,
+               VK_FORMAT_BC3_SRGB_BLOCK,
+               VK_FORMAT_BC4_UNORM_BLOCK,
+               VK_FORMAT_BC4_SNORM_BLOCK,
+               VK_FORMAT_BC5_UNORM_BLOCK,
+               VK_FORMAT_BC5_SNORM_BLOCK,
+               VK_FORMAT_BC6H_UFLOAT_BLOCK,
+               VK_FORMAT_BC6H_SFLOAT_BLOCK,
+               VK_FORMAT_BC7_UNORM_BLOCK,
+               VK_FORMAT_BC7_SRGB_BLOCK,
+               VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
+               VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
+               VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
+               VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
+               VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
+               VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
+               VK_FORMAT_EAC_R11_UNORM_BLOCK,
+               VK_FORMAT_EAC_R11_SNORM_BLOCK,
+               VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
+               VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
+               VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
+               VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
+               VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
+               VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
+               VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
+               VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
+               VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
+               VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
+               VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
+               VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
+               VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
+               VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
+               VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
+               VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
+               VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
+               VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
+               VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
+               VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
+               VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
+               VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
+               VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
+               VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
+               VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
+               VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
+               VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
+               VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
+               VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
+               VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
+               VK_FORMAT_G8B8G8R8_422_UNORM_KHR,
+               VK_FORMAT_B8G8R8G8_422_UNORM_KHR,
+               VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR,
+               VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR,
+               VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR,
+               VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR,
+               VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR,
+               VK_FORMAT_R10X6_UNORM_PACK16_KHR,
+               VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR,
+               VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR,
+               VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR,
+               VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR,
+               VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR,
+               VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR,
+               VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR,
+               VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR,
+               VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR,
+               VK_FORMAT_R12X4_UNORM_PACK16_KHR,
+               VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR,
+               VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR,
+               VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR,
+               VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR,
+               VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR,
+               VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR,
+               VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR,
+               VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR,
+               VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR,
+               VK_FORMAT_G16B16G16R16_422_UNORM_KHR,
+               VK_FORMAT_B16G16R16G16_422_UNORM_KHR,
+               VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR,
+               VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR,
+               VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR,
+               VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR,
+               VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR
+       };
        const DeviceInterface&          vk                              = context.getDeviceInterface();
        const InstanceInterface&        vki                             = context.getInstanceInterface();
        const VkDevice                          device                  = context.getDevice();
@@ -547,7 +1308,7 @@ tcu::TestStatus testImage (Context& context, const ImageParams params)
        const VkImageCreateFlags        sparseFlags             = VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT;
        const VkImageUsageFlags         transientFlags  = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
 
-       requireImageSparseFeatures(vki, physDevice, params.flags);
+       preTestChecks(context, vki, physDevice, params.flags);
 
        const VkPhysicalDeviceMemoryProperties  memoryProperties                = getPhysicalDeviceMemoryProperties(vki, physDevice);
        const deUint32                                                  notInitializedBits              = ~0u;
@@ -565,60 +1326,66 @@ tcu::TestStatus testImage (Context& context, const ImageParams params)
                const VkImageAspectFlags        aspect                                  = allAspects[loopAspectNdx];
                deUint32                                        previousMemoryTypeBits  = notInitializedBits;
 
-               for (VkFormat loopFormat = VK_FORMAT_R4G4_UNORM_PACK8; loopFormat <= VK_FORMAT_ASTC_12x12_SRGB_BLOCK; loopFormat = nextEnum(loopFormat))
-               if  (isFormatMatchingAspect(loopFormat, aspect))
+               for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
                {
-                       // memoryTypeBits may differ between depth/stencil formats
-                       if (aspect == depthStencilAspect)
-                               previousMemoryTypeBits = notInitializedBits;
-
-                       for (VkImageType                        loopImageType   = VK_IMAGE_TYPE_1D;                                     loopImageType   != VK_IMAGE_TYPE_LAST;                                  loopImageType   = nextEnum(loopImageType))
-                       for (VkImageCreateFlags         loopCreateFlags = (VkImageCreateFlags)0;                        loopCreateFlags <= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; loopCreateFlags = nextFlagExcluding(loopCreateFlags, sparseFlags))
-                       for (VkImageUsageFlags          loopUsageFlags  = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;      loopUsageFlags  <= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; loopUsageFlags  = nextFlagExcluding(loopUsageFlags, transientFlags))
-                       for (VkSampleCountFlagBits      loopSampleCount = VK_SAMPLE_COUNT_1_BIT;                        loopSampleCount <= VK_SAMPLE_COUNT_16_BIT;                              loopSampleCount = nextFlag(loopSampleCount))
+                       const VkFormat format = formats[formatNdx];
+
+                       if  (isFormatMatchingAspect(format, aspect))
                        {
-                               const VkImageCreateFlags        actualCreateFlags       = loopCreateFlags | params.flags;
-                               const VkImageUsageFlags         actualUsageFlags        = loopUsageFlags  | (params.transient ? VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0);
-                               const bool                                      isCube                          = (actualCreateFlags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) != 0u;
-                               const VkImageCreateInfo         imageInfo                       =
+                               // memoryTypeBits may differ between depth/stencil formats
+                               if (aspect == depthStencilAspect)
+                                       previousMemoryTypeBits = notInitializedBits;
+
+                               for (VkImageType                        loopImageType   = VK_IMAGE_TYPE_1D;                                     loopImageType   != VK_IMAGE_TYPE_LAST;                                  loopImageType   = nextEnum(loopImageType))
+                               for (VkImageCreateFlags         loopCreateFlags = (VkImageCreateFlags)0;                        loopCreateFlags <= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; loopCreateFlags = nextFlagExcluding(loopCreateFlags, sparseFlags))
+                               for (VkImageUsageFlags          loopUsageFlags  = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;      loopUsageFlags  <= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; loopUsageFlags  = nextFlagExcluding(loopUsageFlags, transientFlags))
+                               for (VkSampleCountFlagBits      loopSampleCount = VK_SAMPLE_COUNT_1_BIT;                        loopSampleCount <= VK_SAMPLE_COUNT_16_BIT;                              loopSampleCount = nextFlag(loopSampleCount))
                                {
-                                       VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType          sType;
-                                       DE_NULL,                                                                        // const void*              pNext;
-                                       actualCreateFlags,                                                      // VkImageCreateFlags       flags;
-                                       loopImageType,                                                          // VkImageType              imageType;
-                                       loopFormat,                                                                     // VkFormat                 format;
-                                       makeExtentForImage(loopImageType),                      // VkExtent3D               extent;
-                                       1u,                                                                                     // uint32_t                 mipLevels;
-                                       (isCube ? 6u : 1u),                                                     // uint32_t                 arrayLayers;
-                                       loopSampleCount,                                                        // VkSampleCountFlagBits    samples;
-                                       params.tiling,                                                          // VkImageTiling            tiling;
-                                       actualUsageFlags,                                                       // VkImageUsageFlags        usage;
-                                       VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode            sharingMode;
-                                       0u,                                                                                     // uint32_t                 queueFamilyIndexCount;
-                                       DE_NULL,                                                                        // const uint32_t*          pQueueFamilyIndices;
-                                       VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout            initialLayout;
-                               };
-
-                               if (!isImageSupported(vki, physDevice, imageInfo))
-                                       continue;
-
-                               log << tcu::TestLog::Message << "- " << getImageInfoString(imageInfo) << tcu::TestLog::EndMessage;
-                               ++numCheckedImages;
-
-                               const Unique<VkImage>           image                   (createImage(vk, device, &imageInfo));
-                               const VkMemoryRequirements      requirements    = getImageMemoryRequirements(vk, device, *image);
-                               tcu::ResultCollector            result                  (log, "ERROR: ");
-
-                               verifyImageRequirements(result, memoryProperties, requirements, imageInfo);
-
-                               // For the same tiling, transient usage, and sparse flags, (and format, if D/S) memoryTypeBits must be the same for all images
-                               result.check((previousMemoryTypeBits == notInitializedBits) || (requirements.memoryTypeBits == previousMemoryTypeBits),
-                                                               "memoryTypeBits differ from the ones in the previous image configuration");
-
-                               if (result.getResult() != QP_TEST_RESULT_PASS)
-                                       allPass = false;
-
-                               previousMemoryTypeBits = requirements.memoryTypeBits;
+                                       const VkImageCreateFlags        actualCreateFlags       = loopCreateFlags | params.flags;
+                                       const VkImageUsageFlags         actualUsageFlags        = loopUsageFlags  | (params.transient ? VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0);
+                                       const bool                                      isCube                          = (actualCreateFlags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) != 0u;
+                                       const VkImageCreateInfo         imageInfo                       =
+                                       {
+                                               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType          sType;
+                                               DE_NULL,                                                                        // const void*              pNext;
+                                               actualCreateFlags,                                                      // VkImageCreateFlags       flags;
+                                               loopImageType,                                                          // VkImageType              imageType;
+                                               format,                                                                 // VkFormat                 format;
+                                               makeExtentForImage(loopImageType),                      // VkExtent3D               extent;
+                                               1u,                                                                                     // uint32_t                 mipLevels;
+                                               (isCube ? 6u : 1u),                                                     // uint32_t                 arrayLayers;
+                                               loopSampleCount,                                                        // VkSampleCountFlagBits    samples;
+                                               params.tiling,                                                          // VkImageTiling            tiling;
+                                               actualUsageFlags,                                                       // VkImageUsageFlags        usage;
+                                               VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode            sharingMode;
+                                               0u,                                                                                     // uint32_t                 queueFamilyIndexCount;
+                                               DE_NULL,                                                                        // const uint32_t*          pQueueFamilyIndices;
+                                               VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout            initialLayout;
+                                       };
+
+                                       m_currentTestImageInfo = imageInfo;
+
+                                       if (!isImageSupported(vki, physDevice, context.getDeviceExtensions(), m_currentTestImageInfo))
+                                               continue;
+
+                                       log << tcu::TestLog::Message << "- " << getImageInfoString(m_currentTestImageInfo) << tcu::TestLog::EndMessage;
+                                       ++numCheckedImages;
+
+                                       tcu::ResultCollector result(log, "ERROR: ");
+
+                                       updateMemoryRequirements(vk, device);
+
+                                       verifyMemoryRequirements(result, memoryProperties);
+
+                                       // For the same tiling, transient usage, and sparse flags, (and format, if D/S) memoryTypeBits must be the same for all images
+                                       result.check((previousMemoryTypeBits == notInitializedBits) || (m_currentTestRequirements.memoryTypeBits == previousMemoryTypeBits),
+                                                                       "memoryTypeBits differ from the ones in the previous image configuration");
+
+                                       if (result.getResult() != QP_TEST_RESULT_PASS)
+                                               allPass = false;
+
+                                       previousMemoryTypeBits = m_currentTestRequirements.memoryTypeBits;
+                               }
                        }
                }
        }
@@ -629,86 +1396,429 @@ tcu::TestStatus testImage (Context& context, const ImageParams params)
        return allPass ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Some memory requirements were incorrect");
 }
 
-void populateTestGroup (tcu::TestCaseGroup* group)
+
+class ImageMemoryRequirementsExtended : public ImageMemoryRequirementsOriginal
+{
+public:
+       static tcu::TestStatus testEntryPoint   (Context&                                                                       context,
+                                                                                        const ImageTestParams                                          params);
+
+protected:
+       virtual void addFunctionTestCase                (tcu::TestCaseGroup*                                            group,
+                                                                                        const std::string&                                                     name,
+                                                                                        const std::string&                                                     desc,
+                                                                                        const ImageTestParams                                          arg0);
+
+       virtual void preTestChecks                              (Context&                                                                       context,
+                                                                                        const InstanceInterface&                                       vki,
+                                                                                        const VkPhysicalDevice                                         physDevice,
+                                                                                        const VkImageCreateFlags                                       flags);
+
+       virtual void updateMemoryRequirements   (const DeviceInterface&                                         vk,
+                                                                                        const VkDevice                                                         device);
+};
+
+
+tcu::TestStatus ImageMemoryRequirementsExtended::testEntryPoint (Context& context, const ImageTestParams params)
+{
+       ImageMemoryRequirementsExtended test;
+
+       return test.execTest(context, params);
+}
+
+void ImageMemoryRequirementsExtended::addFunctionTestCase (tcu::TestCaseGroup*         group,
+                                                                                                                  const std::string&           name,
+                                                                                                                  const std::string&           desc,
+                                                                                                                  const ImageTestParams        arg0)
+{
+       addFunctionCase(group, name, desc, testEntryPoint, arg0);
+}
+
+void ImageMemoryRequirementsExtended::preTestChecks (Context&                                  context,
+                                                                                                        const InstanceInterface&       vki,
+                                                                                                        const VkPhysicalDevice         physDevice,
+                                                                                                        const VkImageCreateFlags       createFlags)
+{
+       const std::string extensionName("VK_KHR_get_memory_requirements2");
+
+       if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), extensionName))
+               TCU_THROW(NotSupportedError, std::string(extensionName + " is not supported").c_str());
+
+       ImageMemoryRequirementsOriginal::preTestChecks (context, vki, physDevice, createFlags);
+}
+
+void ImageMemoryRequirementsExtended::updateMemoryRequirements (const DeviceInterface&         vk,
+                                                                                                                           const VkDevice                              device)
+{
+       m_currentTestRequirements = getImageMemoryRequirements2(vk, device, m_currentTestImageInfo);
+}
+
+
+class ImageMemoryRequirementsDedicatedAllocation : public ImageMemoryRequirementsExtended
+{
+public:
+       static tcu::TestStatus testEntryPoint   (Context&                                                                       context,
+                                                                                        const ImageTestParams                                          params);
+
+protected:
+       virtual void addFunctionTestCase                (tcu::TestCaseGroup*                                            group,
+                                                                                        const std::string&                                                     name,
+                                                                                        const std::string&                                                     desc,
+                                                                                        const ImageTestParams                                          arg0);
+
+       virtual void preTestChecks                              (Context&                                                                       context,
+                                                                                        const InstanceInterface&                                       vki,
+                                                                                        const VkPhysicalDevice                                         physDevice,
+                                                                                        const VkImageCreateFlags                                       flags);
+
+       virtual void updateMemoryRequirements   (const DeviceInterface&                                         vk,
+                                                                                        const VkDevice                                                         device);
+
+       virtual void verifyMemoryRequirements   (tcu::ResultCollector&                                          result,
+                                                                                        const VkPhysicalDeviceMemoryProperties&        deviceMemoryProperties);
+
+protected:
+       VkBool32        m_currentTestPrefersDedicatedAllocation;
+       VkBool32        m_currentTestRequiresDedicatedAllocation;
+};
+
+
+tcu::TestStatus ImageMemoryRequirementsDedicatedAllocation::testEntryPoint (Context& context, const ImageTestParams params)
+{
+       ImageMemoryRequirementsDedicatedAllocation test;
+
+       return test.execTest(context, params);
+}
+
+void ImageMemoryRequirementsDedicatedAllocation::addFunctionTestCase (tcu::TestCaseGroup*              group,
+                                                                                                                                         const std::string&            name,
+                                                                                                                                         const std::string&            desc,
+                                                                                                                                         const ImageTestParams         arg0)
+{
+       addFunctionCase(group, name, desc, testEntryPoint, arg0);
+}
+
+void ImageMemoryRequirementsDedicatedAllocation::preTestChecks (Context&                                       context,
+                                                                                                                               const InstanceInterface&        vki,
+                                                                                                                               const VkPhysicalDevice          physDevice,
+                                                                                                                               const VkImageCreateFlags        createFlags)
+{
+       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());
+
+       ImageMemoryRequirementsExtended::preTestChecks (context, vki, physDevice, createFlags);
+}
+
+
+void ImageMemoryRequirementsDedicatedAllocation::updateMemoryRequirements (const DeviceInterface&      vk,
+                                                                                                                                                  const VkDevice                       device)
 {
-       // Buffers
+       const deUint32                                          invalidVkBool32                 = static_cast<deUint32>(~0);
+
+       VkMemoryDedicatedRequirementsKHR        dedicatedRequirements   =
        {
-               const struct
-               {
-                       VkBufferCreateFlags             flags;
-                       const char* const               name;
-               } bufferCases[] =
-               {
-                       { (VkBufferCreateFlags)0,                                                                                                                                                                                               "regular"                                       },
-                       { VK_BUFFER_CREATE_SPARSE_BINDING_BIT,                                                                                                                                                                  "sparse"                                        },
-                       { VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,                                                                                  "sparse_residency"                      },
-                       { VK_BUFFER_CREATE_SPARSE_BINDING_BIT                                                                                   | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,  "sparse_aliased"                        },
-                       { VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT   | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,  "sparse_residency_aliased"      },
-               };
+               VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,    // VkStructureType      sType
+               DE_NULL,                                                                                                // void*                        pNext
+               invalidVkBool32,                                                                                // VkBool32                     prefersDedicatedAllocation
+               invalidVkBool32                                                                                 // VkBool32                     requiresDedicatedAllocation
+       };
+
+       m_currentTestRequirements                                       = getImageMemoryRequirements2(vk, device, m_currentTestImageInfo, &dedicatedRequirements);
+       m_currentTestPrefersDedicatedAllocation         = dedicatedRequirements.prefersDedicatedAllocation;
+       m_currentTestRequiresDedicatedAllocation        = dedicatedRequirements.requiresDedicatedAllocation;
+}
+
+void ImageMemoryRequirementsDedicatedAllocation::verifyMemoryRequirements (tcu::ResultCollector&                                               result,
+                                                                                                                                                  const VkPhysicalDeviceMemoryProperties&      deviceMemoryProperties)
+{
+       ImageMemoryRequirementsExtended::verifyMemoryRequirements(result, deviceMemoryProperties);
+
+       result.check(validValueVkBool32(m_currentTestPrefersDedicatedAllocation),
+               "Non-bool value in m_currentTestPrefersDedicatedAllocation");
+
+       result.check(m_currentTestRequiresDedicatedAllocation == VK_FALSE,
+               "Test design expects m_currentTestRequiresDedicatedAllocation to be false");
+
+       result.check(m_currentTestPrefersDedicatedAllocation == VK_FALSE || m_currentTestPrefersDedicatedAllocation == VK_FALSE,
+               "Preferred and required flags for dedicated memory cannot be set to true at the same time");
+}
+
+void populateCoreTestGroup (tcu::TestCaseGroup* group)
+{
+       BufferMemoryRequirementsOriginal        bufferTest;
+       ImageMemoryRequirementsOriginal         imageTest;
+
+       bufferTest.populateTestGroup(group);
+       imageTest.populateTestGroup(group);
+}
+
+void populateExtendedTestGroup (tcu::TestCaseGroup* group)
+{
+       BufferMemoryRequirementsExtended        bufferTest;
+       ImageMemoryRequirementsExtended         imageTest;
+
+       bufferTest.populateTestGroup(group);
+       imageTest.populateTestGroup(group);
+}
+
+void populateDedicatedAllocationTestGroup (tcu::TestCaseGroup* group)
+{
+       BufferMemoryRequirementsDedicatedAllocation     bufferTest;
+       ImageMemoryRequirementsDedicatedAllocation      imageTest;
+
+       bufferTest.populateTestGroup(group);
+       imageTest.populateTestGroup(group);
+}
+
+bool isMultiplaneImageSupported (const InstanceInterface&      vki,
+                                                                const VkPhysicalDevice         physicalDevice,
+                                                                const VkImageCreateInfo&       info)
+{
+       if ((info.flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) && info.imageType != VK_IMAGE_TYPE_2D)
+               return false;
+
+       if ((info.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) &&
+               (info.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) == 0u)
+               return false;
+
+       const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physicalDevice);
+
+       if (info.flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT)
+       {
+               DE_ASSERT(info.tiling == VK_IMAGE_TILING_OPTIMAL);
 
-               de::MovePtr<tcu::TestCaseGroup> bufferGroup(new tcu::TestCaseGroup(group->getTestContext(), "buffer", ""));
+               if (info.imageType == VK_IMAGE_TYPE_2D && !features.sparseResidencyImage2D)
+                       return false;
+       }
+
+       const VkFormatProperties        formatProperties        = getPhysicalDeviceFormatProperties(vki, physicalDevice, info.format);
+       const VkFormatFeatureFlags      formatFeatures          = (info.tiling == VK_IMAGE_TILING_LINEAR ? formatProperties.linearTilingFeatures
+                                                                                                                                                                                        : formatProperties.optimalTilingFeatures);
 
-               for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bufferCases); ++ndx)
-                       addFunctionCase(bufferGroup.get(), bufferCases[ndx].name, "", testBuffer, bufferCases[ndx].flags);
+       if (!isUsageMatchesFeatures(info.usage, formatFeatures))
+               return false;
 
-               group->addChild(bufferGroup.release());
+       VkImageFormatProperties         imageFormatProperties;
+       const VkResult                          result                          = vki.getPhysicalDeviceImageFormatProperties(
+                                                                                                               physicalDevice, info.format, info.imageType, info.tiling, info.usage, info.flags, &imageFormatProperties);
+
+       if (result == VK_SUCCESS)
+       {
+               if (info.arrayLayers > imageFormatProperties.maxArrayLayers)
+                       return false;
+               if (info.mipLevels > imageFormatProperties.maxMipLevels)
+                       return false;
+               if ((info.samples & imageFormatProperties.sampleCounts) == 0u)
+                       return false;
        }
 
-       // Images
+       return result == VK_SUCCESS;
+}
+
+tcu::TestStatus testMultiplaneImages (Context& context, ImageTestParams params)
+{
+       const VkFormat multiplaneFormats[] =
        {
-               const struct
-               {
-                       VkImageCreateFlags              flags;
-                       bool                                    transient;
-                       const char* const               name;
-               } imageFlagsCases[] =
-               {
-                       { (VkImageCreateFlags)0,                                                                                                                                                                                                false,  "regular"                                       },
-                       { (VkImageCreateFlags)0,                                                                                                                                                                                                true,   "transient"                                     },
-                       { VK_IMAGE_CREATE_SPARSE_BINDING_BIT,                                                                                                                                                                   false,  "sparse"                                        },
-                       { VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,                                                                                    false,  "sparse_residency"                      },
-                       { VK_IMAGE_CREATE_SPARSE_BINDING_BIT                                                                                    | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,   false,  "sparse_aliased"                        },
-                       { VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT             | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,   false,  "sparse_residency_aliased"      },
-               };
-
-               de::MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(group->getTestContext(), "image", ""));
-
-               for (int flagsNdx = 0; flagsNdx < DE_LENGTH_OF_ARRAY(imageFlagsCases); ++flagsNdx)
-               for (int tilingNdx = 0; tilingNdx <= 1; ++tilingNdx)
-               {
-                       ImageParams                     params;
-                       std::ostringstream      caseName;
+               VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR,
+               VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR,
+               VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR,
+               VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR,
+               VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR,
+               VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR,
+               VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR,
+               VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR,
+               VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR,
+               VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR,
+               VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR,
+               VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR,
+               VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR,
+               VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR,
+               VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR,
+               VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR,
+               VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR,
+               VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR,
+               VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR
+       };
+       {
+               const std::string extensionName("VK_KHR_get_memory_requirements2");
 
-                       params.flags            =  imageFlagsCases[flagsNdx].flags;
-                       params.transient        =  imageFlagsCases[flagsNdx].transient;
-                       caseName                        << imageFlagsCases[flagsNdx].name;
+               if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), extensionName))
+                       TCU_THROW(NotSupportedError, std::string(extensionName + " is not supported").c_str());
+       }
+       {
+               const std::string extensionName("VK_KHR_sampler_ycbcr_conversion");
 
-                       if (tilingNdx != 0)
+               if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), extensionName))
+                       TCU_THROW(NotSupportedError, std::string(extensionName + " is not supported").c_str());
+       }
+
+       const DeviceInterface&                                  vk                                      = context.getDeviceInterface();
+       const InstanceInterface&                                vki                                     = context.getInstanceInterface();
+       const VkDevice                                                  device                          = context.getDevice();
+       const VkPhysicalDevice                                  physicalDevice          = context.getPhysicalDevice();
+       const VkImageCreateFlags                                sparseFlags                     = VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT;
+       const VkImageUsageFlags                                 transientFlags          = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
+       const VkPhysicalDeviceMemoryProperties  memoryProperties        = getPhysicalDeviceMemoryProperties(vki, physicalDevice);
+       tcu::TestLog&                                                   log                                     = context.getTestContext().getLog();
+       tcu::ResultCollector                                    result                          (log, "ERROR: ");
+       deUint32                                                                errorCount                      = 0;
+
+       log << TestLog::Message << "Memory properties: " << memoryProperties << TestLog::EndMessage;
+
+       for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(multiplaneFormats); formatNdx++)
+       {
+               for (VkImageCreateFlags         loopCreateFlags = (VkImageCreateFlags)0;                        loopCreateFlags <= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; loopCreateFlags = nextFlagExcluding(loopCreateFlags, sparseFlags))
+               for (VkImageUsageFlags          loopUsageFlags  = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;      loopUsageFlags  <= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; loopUsageFlags  = nextFlagExcluding(loopUsageFlags, transientFlags))
+               {
+                       const VkFormat                          format                          = multiplaneFormats[formatNdx];
+                       const VkImageCreateFlags        actualCreateFlags       = loopCreateFlags | params.flags;
+                       const VkImageUsageFlags         actualUsageFlags        = loopUsageFlags  | (params.transient ? VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0);
+                       const VkImageCreateInfo         imageInfo                       =
                        {
-                               params.tiling =  VK_IMAGE_TILING_OPTIMAL;
-                               caseName      << "_tiling_optimal";
-                       }
-                       else
+                               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,    // VkStructureType          sType;
+                               DE_NULL,                                                                // const void*              pNext;
+                               actualCreateFlags,                                              // VkImageCreateFlags       flags;
+                               VK_IMAGE_TYPE_2D,                                               // VkImageType              imageType;
+                               format,                                                                 // VkFormat                 format;
+                               { 64u, 64u, 1u, },                                              // VkExtent3D               extent;
+                               1u,                                                                             // uint32_t                 mipLevels;
+                               1u,                                                                             // uint32_t                 arrayLayers;
+                               VK_SAMPLE_COUNT_1_BIT,                                  // VkSampleCountFlagBits    samples;
+                               params.tiling,                                                  // VkImageTiling            tiling;
+                               actualUsageFlags,                                               // VkImageUsageFlags        usage;
+                               VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode            sharingMode;
+                               0u,                                                                             // uint32_t                 queueFamilyIndexCount;
+                               DE_NULL,                                                                // const uint32_t*          pQueueFamilyIndices;
+                               VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout            initialLayout;
+                       };
+
+                       if (isMultiplaneImageSupported(vki, physicalDevice, imageInfo))
                        {
-                               params.tiling =  VK_IMAGE_TILING_LINEAR;
-                               caseName      << "_tiling_linear";
-                       }
+                               const Unique<VkImage>                   image                   (createImage(vk, device, &imageInfo));
 
-                       if ((params.flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) && (params.tiling == VK_IMAGE_TILING_LINEAR))
-                               continue;
+                               log << tcu::TestLog::Message << "- " << getImageInfoString(imageInfo) << tcu::TestLog::EndMessage;
 
-                       addFunctionCase(imageGroup.get(), caseName.str(), "", testImage, params);
+                               for (deUint32 planeNdx = 0; planeNdx < (deUint32)getPlaneCount(format); planeNdx++)
+                               {
+                                       const VkImageAspectFlagBits                                     aspect          = getPlaneAspect(planeNdx);
+                                       const VkImagePlaneMemoryRequirementsInfoKHR     aspectInfo      =
+                                       {
+                                               VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR,
+                                               DE_NULL,
+                                               aspect
+                                       };
+                                       const VkImageMemoryRequirementsInfo2KHR         info            =
+                                       {
+                                               VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR,
+                                               (actualCreateFlags & VK_IMAGE_CREATE_DISJOINT_BIT_KHR) == 0 ? DE_NULL : &aspectInfo,
+                                               *image
+                                       };
+                                       VkMemoryRequirements2KHR                                        requirements    =
+                                       {
+                                               VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
+                                               DE_NULL,
+                                               { 0u, 0u, 0u }
+                                       };
+
+                                       vk.getImageMemoryRequirements2KHR(device, &info, &requirements);
+
+                                       log << TestLog::Message << "Aspect: " << getImageAspectFlagsStr(aspect) << ", Requirements: " << requirements << TestLog::EndMessage;
+
+                                       result.check(deIsPowerOfTwo64(static_cast<deUint64>(requirements.memoryRequirements.alignment)), "VkMemoryRequirements alignment isn't power of two");
+
+                                       if (result.check(requirements.memoryRequirements.memoryTypeBits != 0, "No supported memory types"))
+                                       {
+                                               bool    hasHostVisibleType      = false;
+
+                                               for (deUint32 memoryTypeIndex = 0; (0x1u << memoryTypeIndex) <= requirements.memoryRequirements.memoryTypeBits; memoryTypeIndex++)
+                                               {
+                                                       if (result.check(memoryTypeIndex < memoryProperties.memoryTypeCount, "Unknown memory type bits set in memory requirements"))
+                                                       {
+                                                               const VkMemoryPropertyFlags     propertyFlags   (memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags);
+
+                                                               if (propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+                                                                       hasHostVisibleType = true;
+
+                                                               if (propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
+                                                               {
+                                                                       result.check((imageInfo.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) != 0u,
+                                                                               "Memory type includes VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT for a non-transient attachment image");
+                                                               }
+                                                       }
+                                                       else
+                                                               break;
+                                               }
+
+                                               result.check(params.tiling != VK_IMAGE_TILING_LINEAR || hasHostVisibleType, "Required memory type doesn't include VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT");
+                                       }
+                               }
+                       }
                }
+       }
+
+       if (errorCount > 1)
+               return tcu::TestStatus(result.getResult(), "Failed " + de::toString(errorCount) + " cases.");
+       else
+               return tcu::TestStatus(result.getResult(), result.getMessage());
+}
 
-               group->addChild(imageGroup.release());
+void populateMultiplaneTestGroup (tcu::TestCaseGroup* group)
+{
+       const struct
+       {
+               VkImageCreateFlags              flags;
+               bool                                    transient;
+               const char* const               name;
+       } imageFlagsCases[] =
+       {
+               { (VkImageCreateFlags)0,                                                                                                                                                                                                false,  "regular"                                       },
+               { (VkImageCreateFlags)0,                                                                                                                                                                                                true,   "transient"                                     },
+               { VK_IMAGE_CREATE_SPARSE_BINDING_BIT,                                                                                                                                                                   false,  "sparse"                                        },
+               { VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,                                                                                    false,  "sparse_residency"                      },
+               { VK_IMAGE_CREATE_SPARSE_BINDING_BIT                                                                                    | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,   false,  "sparse_aliased"                        },
+               { VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT             | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,   false,  "sparse_residency_aliased"      },
+       };
+       const struct
+       {
+               VkImageTiling   value;
+               const char*             name;
+       } tilings[] =
+       {
+               { VK_IMAGE_TILING_OPTIMAL,      "optimal"       },
+               { VK_IMAGE_TILING_LINEAR,       "linear"        }
+       };
+
+       for (size_t flagsNdx = 0; flagsNdx < DE_LENGTH_OF_ARRAY(imageFlagsCases); ++flagsNdx)
+       for (size_t tilingNdx = 0; tilingNdx < DE_LENGTH_OF_ARRAY(tilings); ++tilingNdx)
+       {
+               const VkImageCreateFlags        flags           = imageFlagsCases[flagsNdx].flags;
+               const bool                                      transient       = imageFlagsCases[flagsNdx].transient;
+               const VkImageTiling                     tiling          = tilings[tilingNdx].value;
+               const ImageTestParams           params          (flags, tiling, transient);
+               const std::string                       name            = std::string(imageFlagsCases[flagsNdx].name) + "_" + tilings[tilingNdx].name;
+
+               if (tiling == VK_IMAGE_TILING_LINEAR && (flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0)
+                       continue;
+
+               addFunctionCase(group, name, name, testMultiplaneImages, params);
        }
 }
 
 } // anonymous
 
+
 tcu::TestCaseGroup* createRequirementsTests (tcu::TestContext& testCtx)
 {
-       return createTestGroup(testCtx, "requirements", "Buffer and image memory requirements", populateTestGroup);
+       de::MovePtr<tcu::TestCaseGroup> requirementsGroup(new tcu::TestCaseGroup(testCtx, "requirements", "Buffer and image memory requirements"));
+
+       requirementsGroup->addChild(createTestGroup(testCtx, "core",                                    "Memory requirements tests with core functionality",                                            populateCoreTestGroup));
+       requirementsGroup->addChild(createTestGroup(testCtx, "extended",                                "Memory requirements tests with extension VK_KHR_get_memory_requirements2",     populateExtendedTestGroup));
+       requirementsGroup->addChild(createTestGroup(testCtx, "dedicated_allocation",    "Memory requirements tests with extension VK_KHR_dedicated_allocation",         populateDedicatedAllocationTestGroup));
+       requirementsGroup->addChild(createTestGroup(testCtx, "multiplane_image",                "Memory requirements tests with vkGetImagePlaneMemoryRequirements",                     populateMultiplaneTestGroup));
+
+       return requirementsGroup.release();
 }
 
 } // memory