Tests for VK_KHR_bind_memory2

Regular and aliased bindings with suballocated and
dedicatedly allocated memory are exercised.

Added tests:
 * dEQP-VK.memory.binding.*

Components: Vulkan

VK-GL-CTS issue: 434

Change-Id: I853ca8b007a9b2f6340ed60cca1a5cb35887ec11
(cherry picked from commit a0aa054cbddcebe880d12836fae9a24ad4eade9f)
diff --git a/Android.mk b/Android.mk
index 0e97e3b..34e51a4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -788,6 +788,7 @@
 	external/vulkancts/modules/vulkan/image/vktImageTestsUtil.cpp \
 	external/vulkancts/modules/vulkan/image/vktImageTexture.cpp \
 	external/vulkancts/modules/vulkan/memory/vktMemoryAllocationTests.cpp \
+	external/vulkancts/modules/vulkan/memory/vktMemoryBindingTests.cpp \
 	external/vulkancts/modules/vulkan/memory/vktMemoryMappingTests.cpp \
 	external/vulkancts/modules/vulkan/memory/vktMemoryPipelineBarrierTests.cpp \
 	external/vulkancts/modules/vulkan/memory/vktMemoryRequirementsTests.cpp \
diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt
index acd2c31..59ae7a2 100644
--- a/android/cts/master/vk-master.txt
+++ b/android/cts/master/vk-master.txt
@@ -43555,6 +43555,48 @@
 dEQP-VK.memory.requirements.extended.image.sparse_aliased_tiling_linear
 dEQP-VK.memory.requirements.extended.image.sparse_aliased_tiling_optimal
 dEQP-VK.memory.requirements.extended.image.sparse_residency_aliased_tiling_optimal
+dEQP-VK.memory.binding.regular.suballocated.buffer_33
+dEQP-VK.memory.binding.regular.suballocated.buffer_257
+dEQP-VK.memory.binding.regular.suballocated.buffer_4087
+dEQP-VK.memory.binding.regular.suballocated.buffer_8095
+dEQP-VK.memory.binding.regular.suballocated.buffer_1048577
+dEQP-VK.memory.binding.regular.suballocated.image_8_8
+dEQP-VK.memory.binding.regular.suballocated.image_8_33
+dEQP-VK.memory.binding.regular.suballocated.image_8_257
+dEQP-VK.memory.binding.regular.suballocated.image_33_8
+dEQP-VK.memory.binding.regular.suballocated.image_33_33
+dEQP-VK.memory.binding.regular.suballocated.image_33_257
+dEQP-VK.memory.binding.regular.suballocated.image_257_8
+dEQP-VK.memory.binding.regular.suballocated.image_257_33
+dEQP-VK.memory.binding.regular.suballocated.image_257_257
+dEQP-VK.memory.binding.regular.dedicated.buffer_33
+dEQP-VK.memory.binding.regular.dedicated.buffer_257
+dEQP-VK.memory.binding.regular.dedicated.buffer_4087
+dEQP-VK.memory.binding.regular.dedicated.buffer_8095
+dEQP-VK.memory.binding.regular.dedicated.buffer_1048577
+dEQP-VK.memory.binding.regular.dedicated.image_8_8
+dEQP-VK.memory.binding.regular.dedicated.image_8_33
+dEQP-VK.memory.binding.regular.dedicated.image_8_257
+dEQP-VK.memory.binding.regular.dedicated.image_33_8
+dEQP-VK.memory.binding.regular.dedicated.image_33_33
+dEQP-VK.memory.binding.regular.dedicated.image_33_257
+dEQP-VK.memory.binding.regular.dedicated.image_257_8
+dEQP-VK.memory.binding.regular.dedicated.image_257_33
+dEQP-VK.memory.binding.regular.dedicated.image_257_257
+dEQP-VK.memory.binding.aliasing.suballocated.buffer_33
+dEQP-VK.memory.binding.aliasing.suballocated.buffer_257
+dEQP-VK.memory.binding.aliasing.suballocated.buffer_4087
+dEQP-VK.memory.binding.aliasing.suballocated.buffer_8095
+dEQP-VK.memory.binding.aliasing.suballocated.buffer_1048577
+dEQP-VK.memory.binding.aliasing.suballocated.image_8_8
+dEQP-VK.memory.binding.aliasing.suballocated.image_8_33
+dEQP-VK.memory.binding.aliasing.suballocated.image_8_257
+dEQP-VK.memory.binding.aliasing.suballocated.image_33_8
+dEQP-VK.memory.binding.aliasing.suballocated.image_33_33
+dEQP-VK.memory.binding.aliasing.suballocated.image_33_257
+dEQP-VK.memory.binding.aliasing.suballocated.image_257_8
+dEQP-VK.memory.binding.aliasing.suballocated.image_257_33
+dEQP-VK.memory.binding.aliasing.suballocated.image_257_257
 dEQP-VK.pipeline.stencil.format.s8_uint.states.front_fail_decc_pass_repl_dfail_inv_comp_not_equal_back_fail_decc_pass_repl_dfail_keep_comp_less
 dEQP-VK.pipeline.stencil.format.s8_uint.states.front_fail_incc_pass_keep_dfail_inv_comp_not_equal_back_fail_decc_pass_repl_dfail_inv_comp_not_equal
 dEQP-VK.pipeline.stencil.format.s8_uint.states.front_fail_wrap_pass_decw_dfail_wrap_comp_less_back_fail_incc_pass_keep_dfail_inv_comp_not_equal
diff --git a/external/vulkancts/framework/vulkan/vkBasicTypes.inl b/external/vulkancts/framework/vulkan/vkBasicTypes.inl
index a412e33..cfedd26 100644
--- a/external/vulkancts/framework/vulkan/vkBasicTypes.inl
+++ b/external/vulkancts/framework/vulkan/vkBasicTypes.inl
@@ -216,6 +216,8 @@
 	VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR				= 1000146002,
 	VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR									= 1000146003,
 	VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR					= 1000146004,
+	VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR								= 1000157000,
+	VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR								= 1000157001,
 };
 
 enum VkSystemAllocationScope
@@ -941,6 +943,7 @@
 	VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR			= 0x00000020,
 	VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR	= 0x00000080,
 	VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR				= 0x00000100,
+	VK_IMAGE_CREATE_ALIAS_BIT_KHR						= 0x00000400,
 };
 typedef deUint32 VkImageCreateFlags;
 
diff --git a/external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl b/external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl
index ead3c17..8c5c0b3 100644
--- a/external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl
+++ b/external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl
@@ -151,3 +151,5 @@
 virtual VkResult	getSemaphoreFdKHR						(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd) const;
 virtual VkResult	getRefreshCycleDurationGOOGLE			(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) const;
 virtual VkResult	getPastPresentationTimingGOOGLE			(VkDevice device, VkSwapchainKHR swapchain, deUint32* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings) const;
+virtual VkResult	bindBufferMemory2KHR					(VkDevice device, deUint32 bindInfoCount, const VkBindBufferMemoryInfoKHR* pBindInfos) const;
+virtual VkResult	bindImageMemory2KHR						(VkDevice device, deUint32 bindInfoCount, const VkBindImageMemoryInfoKHR* pBindInfos) const;
diff --git a/external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl b/external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl
index bc61e21..97ccf27 100644
--- a/external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl
@@ -751,3 +751,13 @@
 {
 	return m_vk.getPastPresentationTimingGOOGLE(device, swapchain, pPresentationTimingCount, pPresentationTimings);
 }
+
+VkResult DeviceDriver::bindBufferMemory2KHR (VkDevice device, deUint32 bindInfoCount, const VkBindBufferMemoryInfoKHR* pBindInfos) const
+{
+	return m_vk.bindBufferMemory2KHR(device, bindInfoCount, pBindInfos);
+}
+
+VkResult DeviceDriver::bindImageMemory2KHR (VkDevice device, deUint32 bindInfoCount, const VkBindImageMemoryInfoKHR* pBindInfos) const
+{
+	return m_vk.bindImageMemory2KHR(device, bindInfoCount, pBindInfos);
+}
diff --git a/external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl b/external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl
index 51d10e6..0d199bf 100644
--- a/external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl
+++ b/external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl
@@ -151,3 +151,5 @@
 GetSemaphoreFdKHRFunc						getSemaphoreFdKHR;
 GetRefreshCycleDurationGOOGLEFunc			getRefreshCycleDurationGOOGLE;
 GetPastPresentationTimingGOOGLEFunc			getPastPresentationTimingGOOGLE;
+BindBufferMemory2KHRFunc					bindBufferMemory2KHR;
+BindImageMemory2KHRFunc						bindImageMemory2KHR;
diff --git a/external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl b/external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl
index 192d0e0..7d6a44b 100644
--- a/external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl
+++ b/external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl
@@ -206,3 +206,5 @@
 typedef VKAPI_ATTR VkResult				(VKAPI_CALL* GetSemaphoreFdKHRFunc)									(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd);
 typedef VKAPI_ATTR VkResult				(VKAPI_CALL* GetRefreshCycleDurationGOOGLEFunc)						(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
 typedef VKAPI_ATTR VkResult				(VKAPI_CALL* GetPastPresentationTimingGOOGLEFunc)					(VkDevice device, VkSwapchainKHR swapchain, deUint32* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
+typedef VKAPI_ATTR VkResult				(VKAPI_CALL* BindBufferMemory2KHRFunc)								(VkDevice device, deUint32 bindInfoCount, const VkBindBufferMemoryInfoKHR* pBindInfos);
+typedef VKAPI_ATTR VkResult				(VKAPI_CALL* BindImageMemory2KHRFunc)								(VkDevice device, deUint32 bindInfoCount, const VkBindImageMemoryInfoKHR* pBindInfos);
diff --git a/external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl b/external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl
index 8c038ca..5f2be2e 100644
--- a/external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl
+++ b/external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl
@@ -151,3 +151,5 @@
 m_vk.getSemaphoreFdKHR						= (GetSemaphoreFdKHRFunc)						GET_PROC_ADDR("vkGetSemaphoreFdKHR");
 m_vk.getRefreshCycleDurationGOOGLE			= (GetRefreshCycleDurationGOOGLEFunc)			GET_PROC_ADDR("vkGetRefreshCycleDurationGOOGLE");
 m_vk.getPastPresentationTimingGOOGLE		= (GetPastPresentationTimingGOOGLEFunc)			GET_PROC_ADDR("vkGetPastPresentationTimingGOOGLE");
+m_vk.bindBufferMemory2KHR					= (BindBufferMemory2KHRFunc)					GET_PROC_ADDR("vkBindBufferMemory2KHR");
+m_vk.bindImageMemory2KHR					= (BindImageMemory2KHRFunc)						GET_PROC_ADDR("vkBindImageMemory2KHR");
diff --git a/external/vulkancts/framework/vulkan/vkNullDriverImpl.inl b/external/vulkancts/framework/vulkan/vkNullDriverImpl.inl
index d7c502b..cbf5dba 100644
--- a/external/vulkancts/framework/vulkan/vkNullDriverImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkNullDriverImpl.inl
@@ -1388,6 +1388,22 @@
 	return VK_SUCCESS;
 }
 
+VKAPI_ATTR VkResult VKAPI_CALL bindBufferMemory2KHR (VkDevice device, deUint32 bindInfoCount, const VkBindBufferMemoryInfoKHR* pBindInfos)
+{
+	DE_UNREF(device);
+	DE_UNREF(bindInfoCount);
+	DE_UNREF(pBindInfos);
+	return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL bindImageMemory2KHR (VkDevice device, deUint32 bindInfoCount, const VkBindImageMemoryInfoKHR* pBindInfos)
+{
+	DE_UNREF(device);
+	DE_UNREF(bindInfoCount);
+	DE_UNREF(pBindInfos);
+	return VK_SUCCESS;
+}
+
 static const tcu::StaticFunctionLibrary::Entry s_platformFunctions[] =
 {
 	VK_NULL_FUNC_ENTRY(vkCreateInstance,						createInstance),
@@ -1603,5 +1619,7 @@
 	VK_NULL_FUNC_ENTRY(vkGetSemaphoreFdKHR,						getSemaphoreFdKHR),
 	VK_NULL_FUNC_ENTRY(vkGetRefreshCycleDurationGOOGLE,			getRefreshCycleDurationGOOGLE),
 	VK_NULL_FUNC_ENTRY(vkGetPastPresentationTimingGOOGLE,		getPastPresentationTimingGOOGLE),
+	VK_NULL_FUNC_ENTRY(vkBindBufferMemory2KHR,					bindBufferMemory2KHR),
+	VK_NULL_FUNC_ENTRY(vkBindImageMemory2KHR,					bindImageMemory2KHR),
 };
 
diff --git a/external/vulkancts/framework/vulkan/vkStrUtil.inl b/external/vulkancts/framework/vulkan/vkStrUtil.inl
index d7e1a91..4d12a86 100644
--- a/external/vulkancts/framework/vulkan/vkStrUtil.inl
+++ b/external/vulkancts/framework/vulkan/vkStrUtil.inl
@@ -415,3 +415,5 @@
 std::ostream&	operator<<	(std::ostream& s, const VkPresentTimeGOOGLE& value);
 std::ostream&	operator<<	(std::ostream& s, const VkPresentTimesInfoGOOGLE& value);
 std::ostream&	operator<<	(std::ostream& s, const VkPhysicalDeviceVariablePointerFeaturesKHR& value);
+std::ostream&	operator<<	(std::ostream& s, const VkBindBufferMemoryInfoKHR& value);
+std::ostream&	operator<<	(std::ostream& s, const VkBindImageMemoryInfoKHR& value);
diff --git a/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl b/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl
index f3e0f6d..9df12a9 100644
--- a/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl
@@ -227,6 +227,8 @@
 		case VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR:					return "VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR";
 		case VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR:									return "VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR";
 		case VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR:						return "VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR";
+		case VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR:									return "VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR";
+		case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR:									return "VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR";
 		default:																			return DE_NULL;
 	}
 }
@@ -1052,6 +1054,7 @@
 		tcu::Format::BitDesc(VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR,			"VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR"),
 		tcu::Format::BitDesc(VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR,	"VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR"),
 		tcu::Format::BitDesc(VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR,				"VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR"),
+		tcu::Format::BitDesc(VK_IMAGE_CREATE_ALIAS_BIT_KHR,							"VK_IMAGE_CREATE_ALIAS_BIT_KHR"),
 	};
 	return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
 }
@@ -4312,3 +4315,27 @@
 	s << '}';
 	return s;
 }
+
+std::ostream& operator<< (std::ostream& s, const VkBindBufferMemoryInfoKHR& value)
+{
+	s << "VkBindBufferMemoryInfoKHR = {\n";
+	s << "\tsType = " << value.sType << '\n';
+	s << "\tpNext = " << value.pNext << '\n';
+	s << "\tbuffer = " << value.buffer << '\n';
+	s << "\tmemory = " << value.memory << '\n';
+	s << "\tmemoryOffset = " << value.memoryOffset << '\n';
+	s << '}';
+	return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkBindImageMemoryInfoKHR& value)
+{
+	s << "VkBindImageMemoryInfoKHR = {\n";
+	s << "\tsType = " << value.sType << '\n';
+	s << "\tpNext = " << value.pNext << '\n';
+	s << "\timage = " << value.image << '\n';
+	s << "\tmemory = " << value.memory << '\n';
+	s << "\tmemoryOffset = " << value.memoryOffset << '\n';
+	s << '}';
+	return s;
+}
diff --git a/external/vulkancts/framework/vulkan/vkStructTypes.inl b/external/vulkancts/framework/vulkan/vkStructTypes.inl
index 3faba91..f186ed7 100644
--- a/external/vulkancts/framework/vulkan/vkStructTypes.inl
+++ b/external/vulkancts/framework/vulkan/vkStructTypes.inl
@@ -1971,3 +1971,21 @@
 	VkBool32		variablePointers;
 };
 
+struct VkBindBufferMemoryInfoKHR
+{
+	VkStructureType	sType;
+	const void*		pNext;
+	VkBuffer		buffer;
+	VkDeviceMemory	memory;
+	VkDeviceSize	memoryOffset;
+};
+
+struct VkBindImageMemoryInfoKHR
+{
+	VkStructureType	sType;
+	const void*		pNext;
+	VkImage			image;
+	VkDeviceMemory	memory;
+	VkDeviceSize	memoryOffset;
+};
+
diff --git a/external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl b/external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl
index 80636fa..7630125 100644
--- a/external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl
+++ b/external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl
@@ -151,3 +151,5 @@
 virtual VkResult	getSemaphoreFdKHR						(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd) const = 0;
 virtual VkResult	getRefreshCycleDurationGOOGLE			(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) const = 0;
 virtual VkResult	getPastPresentationTimingGOOGLE			(VkDevice device, VkSwapchainKHR swapchain, deUint32* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings) const = 0;
+virtual VkResult	bindBufferMemory2KHR					(VkDevice device, deUint32 bindInfoCount, const VkBindBufferMemoryInfoKHR* pBindInfos) const = 0;
+virtual VkResult	bindImageMemory2KHR						(VkDevice device, deUint32 bindInfoCount, const VkBindImageMemoryInfoKHR* pBindInfos) const = 0;
diff --git a/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp b/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
index 9816c44..8c756b6 100644
--- a/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
+++ b/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
@@ -1,4 +1,4 @@
-/*-------------------------------------------------------------------------
+/*-------------------------------------------------------------------------
  * Vulkan Conformance Tests
  * ------------------------
  *
@@ -695,6 +695,7 @@
 		"VK_KHR_dedicated_allocation",
 		"VK_KHR_variable_pointers",
 		"VK_KHR_relaxed_block_layout",
+		"VK_KHR_bind_memory2",
 	};
 
 	checkKhrExtensions(results, extensions, DE_LENGTH_OF_ARRAY(s_allowedDeviceKhrExtensions), s_allowedDeviceKhrExtensions);
diff --git a/external/vulkancts/modules/vulkan/memory/CMakeLists.txt b/external/vulkancts/modules/vulkan/memory/CMakeLists.txt
index c670d55..4ee5209 100644
--- a/external/vulkancts/modules/vulkan/memory/CMakeLists.txt
+++ b/external/vulkancts/modules/vulkan/memory/CMakeLists.txt
@@ -13,6 +13,8 @@
 	vktMemoryPipelineBarrierTests.cpp
 	vktMemoryRequirementsTests.cpp
 	vktMemoryRequirementsTests.hpp
+	vktMemoryBindingTests.cpp
+	vktMemoryBindingTests.hpp
 	)
 
 set(DEQP_VK_MEMORY_LIBS
diff --git a/external/vulkancts/modules/vulkan/memory/vktMemoryBindingTests.cpp b/external/vulkancts/modules/vulkan/memory/vktMemoryBindingTests.cpp
new file mode 100644
index 0000000..b1ad7b2
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/memory/vktMemoryBindingTests.cpp
@@ -0,0 +1,1019 @@
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Memory binding test excercising VK_KHR_bind_memory2 extension.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktMemoryBindingTests.hpp"
+
+#include "vktTestCase.hpp"
+#include "tcuTestLog.hpp"
+
+#include "vkPlatform.hpp"
+#include "gluVarType.hpp"
+#include "deStringUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRefUtil.hpp"
+#include "deSharedPtr.hpp"
+#include "vktTestCase.hpp"
+#include "vkTypeUtil.hpp"
+
+#include <algorithm>
+
+namespace vkt
+{
+namespace memory
+{
+namespace
+{
+
+using namespace vk;
+
+typedef const VkMemoryDedicatedAllocateInfoKHR								ConstDedicatedInfo;
+typedef de::SharedPtr<Move<VkDeviceMemory> >								MemoryRegionPtr;
+typedef std::vector<MemoryRegionPtr>										MemoryRegionsList;
+typedef de::SharedPtr<Move<VkBuffer> >										BufferPtr;
+typedef std::vector<BufferPtr>												BuffersList;
+typedef de::SharedPtr<Move<VkImage> >										ImagePtr;
+typedef std::vector<ImagePtr>												ImagesList;
+typedef std::vector<VkBindBufferMemoryInfoKHR>								BindBufferMemoryInfosList;
+typedef std::vector<VkBindImageMemoryInfoKHR>								BindImageMemoryInfosList;
+
+class MemoryMappingRAII
+{
+public:
+										MemoryMappingRAII					(const DeviceInterface&	deviceInterface,
+																			 const VkDevice&		device,
+																			 VkDeviceMemory			deviceMemory,
+																			 VkDeviceSize			offset,
+																			 VkDeviceSize			size,
+																			 VkMemoryMapFlags		flags)
+										: vk								(deviceInterface)
+										, dev								(device)
+										, memory							(deviceMemory)
+										, hostPtr							(DE_NULL)
+
+	{
+		vk.mapMemory(dev, memory, offset, size, flags, &hostPtr);
+	}
+
+										~MemoryMappingRAII					()
+	{
+		vk.unmapMemory(dev, memory);
+		hostPtr = DE_NULL;
+	}
+
+	void*								ptr									()
+	{
+		return hostPtr;
+	}
+
+	void								flush								(VkDeviceSize			offset,
+																			 VkDeviceSize			size)
+	{
+		const VkMappedMemoryRange		range								= makeMemoryRange(offset, size);
+		VK_CHECK(vk.flushMappedMemoryRanges(dev, 1u, &range));
+	}
+
+protected:
+	const DeviceInterface&				vk;
+	const VkDevice&						dev;
+	VkDeviceMemory						memory;
+	void*								hostPtr;
+
+	const VkMappedMemoryRange			makeMemoryRange						(VkDeviceSize			offset,
+																			 VkDeviceSize			size)
+	{
+		const VkMappedMemoryRange		range								=
+		{
+			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+			DE_NULL,
+			memory,
+			offset,
+			size
+		};
+		return range;
+	}
+};
+
+class SimpleRandomGenerator
+{
+public:
+										SimpleRandomGenerator				(deUint32				seed)
+										: value								(seed)
+	{}
+	deUint32							getNext								()
+	{
+		value += 1;
+		value ^= (value << 21);
+		value ^= (value >> 15);
+		value ^= (value << 4);
+		return value;
+	}
+protected:
+	deUint32							value;
+};
+
+struct BindingCaseParameters
+{
+	VkBufferCreateFlags					flags;
+	VkBufferUsageFlags					usage;
+	VkSharingMode						sharing;
+	VkDeviceSize						bufferSize;
+	VkExtent3D							imageSize;
+	deUint32							targetsCount;
+};
+
+BindingCaseParameters					makeBindingCaseParameters			(deUint32				targetsCount,
+																			 deUint32				width,
+																			 deUint32				height)
+{
+	BindingCaseParameters				params;
+	deMemset(&params, 0, sizeof(BindingCaseParameters));
+	params.imageSize.width = width;
+	params.imageSize.height = height;
+	params.imageSize.depth = 1;
+	params.bufferSize = params.imageSize.width * params.imageSize.height * params.imageSize.depth * sizeof(deUint32);
+	params.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+	params.targetsCount = targetsCount;
+	return params;
+}
+
+BindingCaseParameters					makeBindingCaseParameters			(deUint32				targetsCount,
+																			 VkBufferUsageFlags		usage,
+																			 VkSharingMode			sharing,
+																			 VkDeviceSize			bufferSize)
+{
+	BindingCaseParameters				params								=
+	{
+		0,																	// VkBufferCreateFlags	flags;
+		usage,																// VkBufferUsageFlags	usage;
+		sharing,															// VkSharingMode		sharing;
+		bufferSize,															// VkDeviceSize			bufferSize;
+		{0u, 0u, 0u},														// VkExtent3D			imageSize;
+		targetsCount														// deUint32				targetsCount;
+	};
+	return params;
+}
+
+VkImageCreateInfo						makeImageCreateInfo					(BindingCaseParameters&	params)
+{
+	const VkImageCreateInfo				imageParams							=
+	{
+		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,								// VkStructureType		sType;
+		DE_NULL,															// const void*			pNext;
+		0u,																	// VkImageCreateFlags	flags;
+		VK_IMAGE_TYPE_2D,													// VkImageType			imageType;
+		VK_FORMAT_R8G8B8A8_UINT,											// VkFormat				format;
+		params.imageSize,													// VkExtent3D			extent;
+		1u,																	// deUint32				mipLevels;
+		1u,																	// deUint32				arrayLayers;
+		VK_SAMPLE_COUNT_1_BIT,												// VkSampleCountFlagBits samples;
+		VK_IMAGE_TILING_LINEAR,												// VkImageTiling		tiling;
+		VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags	usage;
+		VK_SHARING_MODE_EXCLUSIVE,											// VkSharingMode		sharingMode;
+		0u,																	// deUint32				queueFamilyIndexCount;
+		DE_NULL,															// const deUint32*		pQueueFamilyIndices;
+		VK_IMAGE_LAYOUT_UNDEFINED,											// VkImageLayout		initialLayout;
+	};
+	return imageParams;
+}
+
+VkBufferCreateInfo						makeBufferCreateInfo				(Context&				ctx,
+																			 BindingCaseParameters&	params)
+{
+	const deUint32						queueFamilyIndex					= ctx.getUniversalQueueFamilyIndex();
+	VkBufferCreateInfo					bufferParams						=
+	{
+		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,								// VkStructureType		sType;
+		DE_NULL,															// const void*			pNext;
+		params.flags,														// VkBufferCreateFlags	flags;
+		params.bufferSize,													// VkDeviceSize			size;
+		params.usage,														// VkBufferUsageFlags	usage;
+		params.sharing,														// VkSharingMode		sharingMode;
+		1u,																	// uint32_t				queueFamilyIndexCount;
+		&queueFamilyIndex,													// const uint32_t*		pQueueFamilyIndices;
+	};
+	return bufferParams;
+}
+
+const VkMemoryAllocateInfo				makeMemoryAllocateInfo				(VkMemoryRequirements&	memReqs,
+																			 ConstDedicatedInfo*	next)
+{
+	const deUint32						heapTypeIndex						= (deUint32)deCtz32(memReqs.memoryTypeBits);
+	const VkMemoryAllocateInfo			allocateParams						=
+	{
+		VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,								// VkStructureType		sType;
+		next,																// const void*			pNext;
+		memReqs.size,														// VkDeviceSize			allocationSize;
+		heapTypeIndex,														// uint32_t				memoryTypeIndex;
+	};
+	return allocateParams;
+}
+
+enum MemoryHostVisibility
+{
+	MemoryAny,
+	MemoryHostVisible
+};
+
+deUint32								selectMatchingMemoryType			(Context&				ctx,
+																			 VkMemoryRequirements&	memReqs,
+																			 MemoryHostVisibility	memoryVisibility)
+{
+	const VkPhysicalDevice				vkPhysicalDevice					= ctx.getPhysicalDevice();
+	const InstanceInterface&			vkInstance							= ctx.getInstanceInterface();
+	VkPhysicalDeviceMemoryProperties	memoryProperties;
+
+	vkInstance.getPhysicalDeviceMemoryProperties(vkPhysicalDevice, &memoryProperties);
+	if (memoryVisibility == MemoryHostVisible)
+	{
+		for (deUint32 typeNdx = 0; typeNdx < memoryProperties.memoryTypeCount; ++typeNdx)
+		{
+			const deBool				isInAllowed							= (memReqs.memoryTypeBits & (1u << typeNdx)) != 0u;
+			const deBool				hasRightProperties					= (memoryProperties.memoryTypes[typeNdx].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0u;
+			if (isInAllowed && hasRightProperties)
+				return typeNdx;
+		}
+	}
+	return (deUint32)deCtz32(memReqs.memoryTypeBits);
+}
+
+const VkMemoryAllocateInfo				makeMemoryAllocateInfo				(Context&				ctx,
+																			 VkMemoryRequirements&	memReqs,
+																			 MemoryHostVisibility	memoryVisibility)
+{
+	const deUint32						heapTypeIndex						= selectMatchingMemoryType(ctx, memReqs, memoryVisibility);
+	const VkMemoryAllocateInfo			allocateParams						=
+	{
+		VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,								// VkStructureType		sType;
+		DE_NULL,															// const void*			pNext;
+		memReqs.size,														// VkDeviceSize			allocationSize;
+		heapTypeIndex,														// uint32_t				memoryTypeIndex;
+	};
+	return allocateParams;
+}
+
+ConstDedicatedInfo						makeDedicatedAllocationInfo			(VkBuffer				buffer)
+{
+	ConstDedicatedInfo					dedicatedAllocationInfo				=
+	{
+		VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,				// VkStructureType		sType
+		DE_NULL,															// const void*			pNext
+		DE_NULL,															// VkImage				image
+		buffer																// VkBuffer				buffer
+	};
+	return dedicatedAllocationInfo;
+}
+
+ConstDedicatedInfo						makeDedicatedAllocationInfo			(VkImage				image)
+{
+	ConstDedicatedInfo					dedicatedAllocationInfo				=
+	{
+		VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,				// VkStructureType		sType
+		DE_NULL,															// const void*			pNext
+		image,																// VkImage				image
+		DE_NULL																// VkBuffer				buffer
+	};
+	return dedicatedAllocationInfo;
+}
+
+const VkBindBufferMemoryInfoKHR			makeBufferMemoryBindingInfo			(VkBuffer				buffer,
+																			 VkDeviceMemory			memory)
+{
+	const VkBindBufferMemoryInfoKHR		bufferMemoryBinding					=
+	{
+		VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR,						// VkStructureType		sType;
+		DE_NULL,															// const void*			pNext;
+		buffer,																// VkBuffer				buffer;
+		memory,																// VkDeviceMemory		memory;
+		0u,																	// VkDeviceSize			memoryOffset;
+	};
+	return bufferMemoryBinding;
+}
+
+const VkBindImageMemoryInfoKHR			makeImageMemoryBindingInfo			(VkImage				image,
+																			 VkDeviceMemory			memory)
+{
+	const VkBindImageMemoryInfoKHR		imageMemoryBinding					=
+	{
+		VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR,						// VkStructureType		sType;
+		DE_NULL,															// const void*			pNext;
+		image,																// VkImage				image;
+		memory,																// VkDeviceMemory		memory;
+		0u,																	// VkDeviceSize			memoryOffset;
+	};
+	return imageMemoryBinding;
+}
+
+enum TransferDirection
+{
+	TransferToResource														= 0,
+	TransferFromResource													= 1
+};
+
+const VkBufferMemoryBarrier				makeMemoryBarrierInfo				(VkBuffer				buffer,
+																			 VkDeviceSize			size,
+																			 TransferDirection		direction)
+{
+	const deBool fromRes													= direction == TransferFromResource;
+	const VkAccessFlags					srcMask								= static_cast<VkAccessFlags>(fromRes ? VK_ACCESS_HOST_WRITE_BIT : VK_ACCESS_TRANSFER_WRITE_BIT);
+	const VkAccessFlags					dstMask								= static_cast<VkAccessFlags>(fromRes ? VK_ACCESS_TRANSFER_READ_BIT : VK_ACCESS_HOST_READ_BIT);
+	const VkBufferMemoryBarrier			bufferBarrier						=
+	{
+		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,							// VkStructureType		sType;
+		DE_NULL,															// const void*			pNext;
+		srcMask,															// VkAccessFlags		srcAccessMask;
+		dstMask,															// VkAccessFlags		dstAccessMask;
+		VK_QUEUE_FAMILY_IGNORED,											// deUint32				srcQueueFamilyIndex;
+		VK_QUEUE_FAMILY_IGNORED,											// deUint32				dstQueueFamilyIndex;
+		buffer,																// VkBuffer				buffer;
+		0u,																	// VkDeviceSize			offset;
+		size																// VkDeviceSize			size;
+	};
+	return bufferBarrier;
+}
+
+const VkImageMemoryBarrier				makeMemoryBarrierInfo				(VkImage				image,
+																			 VkAccessFlags			srcAccess,
+																			 VkAccessFlags			dstAccess,
+																			 VkImageLayout			oldLayout,
+																			 VkImageLayout			newLayout)
+{
+	const VkImageAspectFlags			aspect								= VK_IMAGE_ASPECT_COLOR_BIT;
+	const VkImageMemoryBarrier			imageBarrier						=
+	{
+		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,								// VkStructureType		sType;
+		DE_NULL,															// const void*			pNext;
+		srcAccess,															// VkAccessFlags		srcAccessMask;
+		dstAccess,															// VkAccessFlags		dstAccessMask;
+		oldLayout,															// VkImageLayout		oldLayout;
+		newLayout,															// VkImageLayout		newLayout;
+		VK_QUEUE_FAMILY_IGNORED,											// deUint32				srcQueueFamilyIndex;
+		VK_QUEUE_FAMILY_IGNORED,											// deUint32				dstQueueFamilyIndex;
+		image,																// VkImage				image;
+		{																	// VkImageSubresourceRange subresourceRange;
+			aspect,															// VkImageAspectFlags	aspect;
+			0u,																// deUint32				baseMipLevel;
+			1u,																// deUint32				mipLevels;
+			0u,																// deUint32				baseArraySlice;
+			1u,																// deUint32				arraySize;
+		}
+	};
+	return imageBarrier;
+}
+
+const VkCommandBufferBeginInfo			makeCommandBufferInfo				()
+{
+	const VkCommandBufferBeginInfo		cmdBufferBeginInfo					=
+	{
+		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+		DE_NULL,
+		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+		static_cast<const VkCommandBufferInheritanceInfo*>(DE_NULL)
+	};
+	return cmdBufferBeginInfo;
+}
+
+const VkSubmitInfo						makeSubmitInfo						(const VkCommandBuffer&	commandBuffer)
+{
+	const VkSubmitInfo					submitInfo							=
+	{
+		VK_STRUCTURE_TYPE_SUBMIT_INFO,										// VkStructureType		sType;
+		DE_NULL,															// const void*			pNext;
+		0u,																	// deUint32				waitSemaphoreCount;
+		DE_NULL,															// const VkSemaphore*	pWaitSemaphores;
+		(const VkPipelineStageFlags*)DE_NULL,								// const VkPipelineStageFlags* flags;
+		1u,																	// deUint32				commandBufferCount;
+		&commandBuffer,														// const VkCommandBuffer* pCommandBuffers;
+		0u,																	// deUint32				signalSemaphoreCount;
+		DE_NULL																// const VkSemaphore*	pSignalSemaphores;
+	};
+	return submitInfo;
+}
+
+Move<VkCommandBuffer>					createCommandBuffer					(const DeviceInterface&	vk,
+																			 VkDevice				device,
+																			 VkCommandPool			commandPool)
+{
+	const VkCommandBufferAllocateInfo allocInfo =
+	{
+		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+		DE_NULL,
+		commandPool,
+		VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+		1
+	};
+	return allocateCommandBuffer(vk, device, &allocInfo);
+}
+
+
+template<typename TTarget>
+void									createBindingTargets				(std::vector<de::SharedPtr<Move<TTarget> > >&
+																									targets,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params);
+
+template<>
+void									createBindingTargets<VkBuffer>		(BuffersList&			targets,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	const deUint32						count								= params.targetsCount;
+	const VkDevice						vkDevice							= ctx.getDevice();
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+
+	targets.reserve(count);
+	for (deUint32 i = 0u; i < count; ++i)
+	{
+		VkBufferCreateInfo				bufferParams						= makeBufferCreateInfo(ctx, params);
+		targets.push_back(BufferPtr(new Move<VkBuffer>(createBuffer(vk, vkDevice, &bufferParams))));
+	}
+}
+
+template<>
+void									createBindingTargets<VkImage>		(ImagesList&			targets,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	const deUint32						count								= params.targetsCount;
+	const VkDevice						vkDevice							= ctx.getDevice();
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+
+	targets.reserve(count);
+	for (deUint32 i = 0u; i < count; ++i)
+	{
+		VkImageCreateInfo				imageParams							= makeImageCreateInfo(params);
+		targets.push_back(ImagePtr(new Move<VkImage>(createImage(vk, vkDevice, &imageParams))));
+	}
+}
+
+template<typename TTarget, deBool TDedicated>
+void									createMemory						(std::vector<de::SharedPtr<Move<TTarget> > >&
+																									targets,
+																			 MemoryRegionsList&		memory,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params);
+
+template<>
+void									createMemory<VkBuffer, DE_FALSE>	(BuffersList&			targets,
+																			 MemoryRegionsList&		memory,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	DE_UNREF(params);
+	const deUint32						count								= static_cast<deUint32>(targets.size());
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+	const VkDevice						vkDevice							= ctx.getDevice();
+
+	memory.reserve(count);
+	for (deUint32 i = 0; i < count; ++i)
+	{
+		VkMemoryRequirements			memReqs;
+
+		vk.getBufferMemoryRequirements(vkDevice, **targets[i], &memReqs);
+
+		const VkMemoryAllocateInfo		memAlloc							= makeMemoryAllocateInfo(memReqs, DE_NULL);
+		VkDeviceMemory					rawMemory							= DE_NULL;
+
+		vk.allocateMemory(vkDevice, &memAlloc, (VkAllocationCallbacks*)DE_NULL, &rawMemory);
+		memory.push_back(MemoryRegionPtr(new Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL))));
+	}
+}
+
+template<>
+void									createMemory<VkImage, DE_FALSE>		(ImagesList&			targets,
+																			 MemoryRegionsList&		memory,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	DE_UNREF(params);
+	const deUint32						count								= static_cast<deUint32>(targets.size());
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+	const VkDevice						vkDevice							= ctx.getDevice();
+
+	memory.reserve(count);
+	for (deUint32 i = 0; i < count; ++i)
+	{
+		VkMemoryRequirements			memReqs;
+		vk.getImageMemoryRequirements(vkDevice, **targets[i], &memReqs);
+
+		const VkMemoryAllocateInfo		memAlloc							= makeMemoryAllocateInfo(memReqs, DE_NULL);
+		VkDeviceMemory					rawMemory							= DE_NULL;
+
+		vk.allocateMemory(vkDevice, &memAlloc, (VkAllocationCallbacks*)DE_NULL, &rawMemory);
+		memory.push_back(de::SharedPtr<Move<VkDeviceMemory> >(new Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL))));
+	}
+}
+
+template<>
+void									createMemory<VkBuffer, DE_TRUE>		(BuffersList&			targets,
+																			 MemoryRegionsList&		memory,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	DE_UNREF(params);
+	const deUint32						count								= static_cast<deUint32>(targets.size());
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+	const VkDevice						vkDevice							= ctx.getDevice();
+
+	memory.reserve(count);
+	for (deUint32 i = 0; i < count; ++i)
+	{
+		VkMemoryRequirements			memReqs;
+
+		vk.getBufferMemoryRequirements(vkDevice, **targets[i], &memReqs);
+
+		ConstDedicatedInfo				dedicatedAllocationInfo				= makeDedicatedAllocationInfo(**targets[i]);;
+		const VkMemoryAllocateInfo		memAlloc							= makeMemoryAllocateInfo(memReqs, &dedicatedAllocationInfo);
+		VkDeviceMemory					rawMemory							= DE_NULL;
+
+		vk.allocateMemory(vkDevice, &memAlloc, static_cast<VkAllocationCallbacks*>(DE_NULL), &rawMemory);
+		memory.push_back(MemoryRegionPtr(new Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL))));
+	}
+}
+
+template<>
+void									createMemory<VkImage, DE_TRUE>		(ImagesList&			targets,
+																			 MemoryRegionsList&		memory,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	DE_UNREF(params);
+	const deUint32						count								= static_cast<deUint32>(targets.size());
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+	const VkDevice						vkDevice							= ctx.getDevice();
+
+	memory.reserve(count);
+	for (deUint32 i = 0; i < count; ++i)
+	{
+		VkMemoryRequirements			memReqs;
+		vk.getImageMemoryRequirements(vkDevice, **targets[i], &memReqs);
+
+		ConstDedicatedInfo				dedicatedAllocationInfo				= makeDedicatedAllocationInfo(**targets[i]);
+		const VkMemoryAllocateInfo		memAlloc							= makeMemoryAllocateInfo(memReqs, &dedicatedAllocationInfo);
+		VkDeviceMemory					rawMemory							= DE_NULL;
+
+		vk.allocateMemory(vkDevice, &memAlloc, static_cast<VkAllocationCallbacks*>(DE_NULL), &rawMemory);
+		memory.push_back(MemoryRegionPtr(new Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL))));
+	}
+}
+
+template<typename TTarget>
+void									makeBinding							(std::vector<de::SharedPtr<Move<TTarget> > >&
+																									targets,
+																			 MemoryRegionsList&		memory,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params);
+
+template<>
+void									makeBinding<VkBuffer>				(BuffersList&			targets,
+																			 MemoryRegionsList&		memory,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	DE_UNREF(params);
+	const deUint32						count								= static_cast<deUint32>(targets.size());
+	const VkDevice						vkDevice							= ctx.getDevice();
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+	BindBufferMemoryInfosList			bindMemoryInfos;
+
+	for (deUint32 i = 0; i < count; ++i)
+	{
+		bindMemoryInfos.push_back(makeBufferMemoryBindingInfo(**targets[i], **memory[i]));
+	}
+
+	VK_CHECK(vk.bindBufferMemory2KHR(vkDevice, count, &bindMemoryInfos.front()));
+}
+
+template<>
+void									makeBinding<VkImage>				(ImagesList&			targets,
+																			 MemoryRegionsList&		memory,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	DE_UNREF(params);
+	const deUint32						count								= static_cast<deUint32>(targets.size());
+	const VkDevice						vkDevice							= ctx.getDevice();
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+	BindImageMemoryInfosList			bindMemoryInfos;
+
+	for (deUint32 i = 0; i < count; ++i)
+	{
+		bindMemoryInfos.push_back(makeImageMemoryBindingInfo(**targets[i], **memory[i]));
+	}
+
+	VK_CHECK(vk.bindImageMemory2KHR(vkDevice, count, &bindMemoryInfos.front()));
+}
+
+template <typename TTarget>
+void									fillUpResource						(Move<VkBuffer>&		source,
+																			 Move<TTarget>&			target,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params);
+
+template <>
+void									fillUpResource<VkBuffer>			(Move<VkBuffer>&		source,
+																			 Move<VkBuffer>&		target,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+	const VkDevice						vkDevice							= ctx.getDevice();
+	const VkQueue						queue								= ctx.getUniversalQueue();
+
+	const VkBufferMemoryBarrier			srcBufferBarrier					= makeMemoryBarrierInfo(*source, params.bufferSize, TransferFromResource);
+	const VkBufferMemoryBarrier			dstBufferBarrier					= makeMemoryBarrierInfo(*target, params.bufferSize, TransferToResource);
+
+	const VkCommandBufferBeginInfo		cmdBufferBeginInfo					= makeCommandBufferInfo();
+	Move<VkCommandPool>					commandPool							= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, 0);
+	Move<VkCommandBuffer>				cmdBuffer							= createCommandBuffer(vk, vkDevice, *commandPool);
+	VkBufferCopy						bufferCopy							= { 0u, 0u, params.bufferSize };
+
+	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
+	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &srcBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
+	vk.cmdCopyBuffer(*cmdBuffer, *source, *target, 1, &bufferCopy);
+	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &dstBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
+	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+	const VkSubmitInfo					submitInfo							= makeSubmitInfo(*cmdBuffer);
+	Move<VkFence>						fence								= createFence(vk, vkDevice);
+
+	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
+	VK_CHECK(vk.waitForFences(vkDevice, 1, &*fence, DE_TRUE, ~(0ull)));
+}
+
+template <>
+void									fillUpResource<VkImage>				(Move<VkBuffer>&		source,
+																			 Move<VkImage>&			target,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+	const VkDevice						vkDevice							= ctx.getDevice();
+	const VkQueue						queue								= ctx.getUniversalQueue();
+
+	const VkBufferMemoryBarrier			srcBufferBarrier					= makeMemoryBarrierInfo(*source, params.bufferSize, TransferFromResource);
+	const VkImageMemoryBarrier			preImageBarrier						= makeMemoryBarrierInfo(*target, 0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+	const VkImageMemoryBarrier			dstImageBarrier						= makeMemoryBarrierInfo(*target, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+
+	const VkCommandBufferBeginInfo		cmdBufferBeginInfo					= makeCommandBufferInfo();
+	Move<VkCommandPool>					commandPool							= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, 0);
+	Move<VkCommandBuffer>				cmdBuffer							= createCommandBuffer(vk, vkDevice, *commandPool);
+
+	const VkBufferImageCopy				copyRegion							=
+	{
+		0u,																	// VkDeviceSize			bufferOffset;
+		params.imageSize.width,												// deUint32				bufferRowLength;
+		params.imageSize.height,											// deUint32				bufferImageHeight;
+		{
+			VK_IMAGE_ASPECT_COLOR_BIT,										// VkImageAspectFlags	aspect;
+			0u,																// deUint32				mipLevel;
+			0u,																// deUint32				baseArrayLayer;
+			1u,																// deUint32				layerCount;
+		},																	// VkImageSubresourceLayers imageSubresource;
+		{ 0, 0, 0 },														// VkOffset3D			imageOffset;
+		params.imageSize													// VkExtent3D			imageExtent;
+	};
+
+	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
+	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &srcBufferBarrier, 1, &preImageBarrier);
+	vk.cmdCopyBufferToImage(*cmdBuffer, *source, *target, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, (&copyRegion));
+	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &dstImageBarrier);
+	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+	const VkSubmitInfo					submitInfo							= makeSubmitInfo(*cmdBuffer);
+	Move<VkFence>						fence								= createFence(vk, vkDevice);
+
+	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
+	VK_CHECK(vk.waitForFences(vkDevice, 1, &*fence, DE_TRUE, ~(0ull)));
+}
+
+template <typename TTarget>
+void									readUpResource						(Move<TTarget>&			source,
+																			 Move<VkBuffer>&		target,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params);
+
+template <>
+void									readUpResource						(Move<VkBuffer>&		source,
+																			 Move<VkBuffer>&		target,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	fillUpResource(source, target, ctx, params);
+}
+
+template <>
+void									readUpResource						(Move<VkImage>&			source,
+																			 Move<VkBuffer>&		target,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+	const VkDevice						vkDevice							= ctx.getDevice();
+	const VkQueue						queue								= ctx.getUniversalQueue();
+
+	const VkImageMemoryBarrier			srcImageBarrier						= makeMemoryBarrierInfo(*source, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
+	const VkBufferMemoryBarrier			dstBufferBarrier					= makeMemoryBarrierInfo(*target, params.bufferSize, TransferToResource);
+	const VkImageMemoryBarrier			postImageBarrier					= makeMemoryBarrierInfo(*source, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
+
+	const VkCommandBufferBeginInfo		cmdBufferBeginInfo					= makeCommandBufferInfo();
+	Move<VkCommandPool>					commandPool							= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, 0);
+	Move<VkCommandBuffer>				cmdBuffer							= createCommandBuffer(vk, vkDevice, *commandPool);
+
+	const VkBufferImageCopy				copyRegion							=
+	{
+		0u,																	// VkDeviceSize			bufferOffset;
+		params.imageSize.width,												// deUint32				bufferRowLength;
+		params.imageSize.height,											// deUint32				bufferImageHeight;
+		{
+			VK_IMAGE_ASPECT_COLOR_BIT,										// VkImageAspectFlags	aspect;
+			0u,																// deUint32				mipLevel;
+			0u,																// deUint32				baseArrayLayer;
+			1u,																// deUint32				layerCount;
+		},																	// VkImageSubresourceLayers imageSubresource;
+		{ 0, 0, 0 },														// VkOffset3D			imageOffset;
+		params.imageSize													// VkExtent3D			imageExtent;
+	};
+
+	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
+	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &srcImageBarrier);
+	vk.cmdCopyImageToBuffer(*cmdBuffer, *source, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *target, 1, (&copyRegion));
+	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &dstBufferBarrier, 1, &postImageBarrier);
+	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+	const VkSubmitInfo					submitInfo							= makeSubmitInfo(*cmdBuffer);
+	Move<VkFence>						fence								= createFence(vk, vkDevice);
+
+	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
+	VK_CHECK(vk.waitForFences(vkDevice, 1, &*fence, DE_TRUE, ~(0ull)));
+}
+
+void									createBuffer						(Move<VkBuffer>&		buffer,
+																			 Move<VkDeviceMemory>&	memory,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+	const VkDevice						vkDevice							= ctx.getDevice();
+	VkBufferCreateInfo					bufferParams						= makeBufferCreateInfo(ctx, params);
+	VkMemoryRequirements				memReqs;
+
+	buffer = createBuffer(vk, vkDevice, &bufferParams);
+	vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs);
+
+	const VkMemoryAllocateInfo			memAlloc							= makeMemoryAllocateInfo(ctx, memReqs, MemoryHostVisible);
+	VkDeviceMemory						rawMemory							= DE_NULL;
+
+	vk.allocateMemory(vkDevice, &memAlloc, static_cast<VkAllocationCallbacks*>(DE_NULL), &rawMemory);
+	memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL));
+	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, *memory, 0u));
+}
+
+void									pushData							(VkDeviceMemory			memory,
+																			 deUint32				dataSeed,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+	const VkDevice						vkDevice							= ctx.getDevice();
+	MemoryMappingRAII					hostMemory							(vk, vkDevice, memory, 0u, params.bufferSize, 0u);
+	deUint8*							hostBuffer							= static_cast<deUint8*>(hostMemory.ptr());
+	SimpleRandomGenerator				random								(dataSeed);
+
+	for (deUint32 i = 0u; i < params.bufferSize; ++i)
+	{
+		hostBuffer[i] = static_cast<deUint8>(random.getNext() & 0xFFu);
+	}
+	hostMemory.flush(0u, params.bufferSize);
+}
+
+deBool									checkData							(VkDeviceMemory			memory,
+																			 deUint32				dataSeed,
+																			 Context&				ctx,
+																			 BindingCaseParameters	params)
+{
+	const DeviceInterface&				vk									= ctx.getDeviceInterface();
+	const VkDevice						vkDevice							= ctx.getDevice();
+	MemoryMappingRAII					hostMemory							(vk, vkDevice, memory, 0u, params.bufferSize, 0u);
+	deUint8*							hostBuffer							= static_cast<deUint8*>(hostMemory.ptr());
+	SimpleRandomGenerator				random								(dataSeed);
+
+	for (deUint32 i = 0u; i < params.bufferSize; ++i)
+	{
+		if (hostBuffer[i] != static_cast<deUint8>(random.getNext() & 0xFFu) )
+			return DE_FALSE;
+	}
+	return DE_TRUE;
+}
+
+template<typename TTarget, deBool TDedicated>
+class MemoryBindingInstance : public TestInstance
+{
+public:
+										MemoryBindingInstance				(Context&				ctx,
+																			 BindingCaseParameters	params)
+										: TestInstance						(ctx)
+										, m_params							(params)
+	{
+	}
+
+	virtual tcu::TestStatus				iterate								(void)
+	{
+		const std::vector<std::string>&	extensions							= m_context.getDeviceExtensions();
+		const deBool					isSupported							= std::find(extensions.begin(), extensions.end(), "VK_KHR_bind_memory2") != extensions.end();
+		if (!isSupported)
+		{
+			TCU_THROW(NotSupportedError, "Not supported");
+		}
+
+		std::vector<de::SharedPtr<Move<TTarget> > >
+										targets;
+		MemoryRegionsList				memory;
+
+		createBindingTargets<TTarget>(targets, m_context, m_params);
+		createMemory<TTarget, TDedicated>(targets, memory, m_context, m_params);
+		makeBinding<TTarget>(targets, memory, m_context, m_params);
+
+		Move<VkBuffer>					srcBuffer;
+		Move<VkDeviceMemory>			srcMemory;
+
+		createBuffer(srcBuffer, srcMemory, m_context, m_params);
+		pushData(*srcMemory, 1, m_context, m_params);
+
+		Move<VkBuffer>					dstBuffer;
+		Move<VkDeviceMemory>			dstMemory;
+
+		createBuffer(dstBuffer, dstMemory, m_context, m_params);
+
+		deBool							passed								= DE_TRUE;
+		for (deUint32 i = 0; passed && i < m_params.targetsCount; ++i)
+		{
+			fillUpResource(srcBuffer, *targets[i], m_context, m_params);
+			readUpResource(*targets[i], dstBuffer, m_context, m_params);
+			passed = checkData(*dstMemory, 1, m_context, m_params);
+		}
+
+		return passed ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Failed");
+	}
+private:
+	BindingCaseParameters				m_params;
+};
+
+template<typename TTarget, deBool TDedicated>
+class AliasedMemoryBindingInstance : public TestInstance
+{
+public:
+										AliasedMemoryBindingInstance		(Context&				ctx,
+																			 BindingCaseParameters	params)
+										: TestInstance						(ctx)
+										, m_params							(params)
+	{
+	}
+
+	virtual tcu::TestStatus				iterate								(void)
+	{
+		const std::vector<std::string>&	extensions							= m_context.getDeviceExtensions();
+		const deBool					isSupported							= std::find(extensions.begin(), extensions.end(), "VK_KHR_bind_memory2") != extensions.end();
+		if (!isSupported)
+		{
+			TCU_THROW(NotSupportedError, "Not supported");
+		}
+
+		std::vector<de::SharedPtr<Move<TTarget> > >
+										targets[2];
+		MemoryRegionsList				memory;
+
+		for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(targets); ++i)
+			createBindingTargets<TTarget>(targets[i], m_context, m_params);
+		createMemory<TTarget, TDedicated>(targets[0], memory, m_context, m_params);
+		for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(targets); ++i)
+			makeBinding<TTarget>(targets[i], memory, m_context, m_params);
+
+		Move<VkBuffer>					srcBuffer;
+		Move<VkDeviceMemory>			srcMemory;
+
+		createBuffer(srcBuffer, srcMemory, m_context, m_params);
+		pushData(*srcMemory, 2, m_context, m_params);
+
+		Move<VkBuffer>					dstBuffer;
+		Move<VkDeviceMemory>			dstMemory;
+
+		createBuffer(dstBuffer, dstMemory, m_context, m_params);
+
+		deBool							passed								= DE_TRUE;
+		for (deUint32 i = 0; passed && i < m_params.targetsCount; ++i)
+		{
+			fillUpResource(srcBuffer, *(targets[0][i]), m_context, m_params);
+			readUpResource(*(targets[1][i]), dstBuffer, m_context, m_params);
+			passed = checkData(*dstMemory, 2, m_context, m_params);
+		}
+
+		return passed ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Failed");
+	}
+private:
+	BindingCaseParameters				m_params;
+};
+
+template<typename TInstance>
+class MemoryBindingTest : public TestCase
+{
+public:
+										MemoryBindingTest					(tcu::TestContext&		testCtx,
+																			 const std::string&		name,
+																			 const std::string&		description,
+																			 BindingCaseParameters	params)
+										: TestCase							(testCtx, name, description)
+										, m_params							(params)
+	{
+	}
+
+	virtual								~MemoryBindingTest					(void)
+	{
+	}
+
+	virtual TestInstance*				createInstance						(Context&				ctx) const
+	{
+		return new TInstance(ctx, m_params);
+	}
+
+private:
+	BindingCaseParameters				m_params;
+};
+
+} // unnamed namespace
+
+tcu::TestCaseGroup* createMemoryBindingTests (tcu::TestContext& testCtx)
+{
+	de::MovePtr<tcu::TestCaseGroup>		group								(new tcu::TestCaseGroup(testCtx, "binding", "Memory binding tests."));
+
+	de::MovePtr<tcu::TestCaseGroup>		regular								(new tcu::TestCaseGroup(testCtx, "regular", "Basic memory binding tests."));
+	de::MovePtr<tcu::TestCaseGroup>		aliasing							(new tcu::TestCaseGroup(testCtx, "aliasing", "Memory binding tests with aliasing of two resources."));
+
+	de::MovePtr<tcu::TestCaseGroup>		regular_suballocated				(new tcu::TestCaseGroup(testCtx, "suballocated", "Basic memory binding tests with suballocated memory."));
+	de::MovePtr<tcu::TestCaseGroup>		regular_dedicated					(new tcu::TestCaseGroup(testCtx, "dedicated", "Basic memory binding tests with deditatedly allocated memory."));
+
+	de::MovePtr<tcu::TestCaseGroup>		aliasing_suballocated				(new tcu::TestCaseGroup(testCtx, "suballocated", "Memory binding tests with aliasing of two resources with suballocated mamory."));
+
+	const VkDeviceSize					allocationSizes[]					= {	33, 257, 4087, 8095, 1*1024*1024 + 1	};
+
+	for (deUint32 sizeNdx = 0u; sizeNdx < DE_LENGTH_OF_ARRAY(allocationSizes); ++sizeNdx )
+	{
+		const VkDeviceSize				bufferSize							= allocationSizes[sizeNdx];
+		const BindingCaseParameters		params								= makeBindingCaseParameters(10, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, bufferSize);
+		std::ostringstream				testName;
+
+		testName << "buffer_" << bufferSize;
+		regular_suballocated->addChild(new MemoryBindingTest<MemoryBindingInstance<VkBuffer, DE_FALSE> >(testCtx, testName.str(), " ", params));
+		regular_dedicated->addChild(new MemoryBindingTest<MemoryBindingInstance<VkBuffer, DE_TRUE> >(testCtx, testName.str(), " ", params));
+		aliasing_suballocated->addChild(new MemoryBindingTest<AliasedMemoryBindingInstance<VkBuffer, DE_FALSE> >(testCtx, testName.str(), " ", params));
+	}
+
+	const deUint32						imageSizes[]						= {	8, 33, 257	};
+
+	for (deUint32 widthNdx = 0u; widthNdx < DE_LENGTH_OF_ARRAY(imageSizes); ++widthNdx )
+	for (deUint32 heightNdx = 0u; heightNdx < DE_LENGTH_OF_ARRAY(imageSizes); ++heightNdx )
+	{
+		const deUint32					width								= imageSizes[widthNdx];
+		const deUint32					height								= imageSizes[heightNdx];
+		const BindingCaseParameters		regularparams						= makeBindingCaseParameters(10, width, height);
+		std::ostringstream				testName;
+
+		testName << "image_" << width << '_' << height;
+		regular_suballocated->addChild(new MemoryBindingTest<MemoryBindingInstance<VkImage, DE_FALSE> >(testCtx, testName.str(), " ", regularparams));
+		regular_dedicated->addChild(new MemoryBindingTest<MemoryBindingInstance<VkImage, DE_TRUE> >(testCtx, testName.str(), "", regularparams));
+		aliasing_suballocated->addChild(new MemoryBindingTest<AliasedMemoryBindingInstance<VkImage, DE_FALSE> >(testCtx, testName.str(), " ", regularparams));
+	}
+
+	regular->addChild(regular_suballocated.release());
+	regular->addChild(regular_dedicated.release());
+
+	aliasing->addChild(aliasing_suballocated.release());
+
+	group->addChild(regular.release());
+	group->addChild(aliasing.release());
+
+	return group.release();
+}
+
+} // memory
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/memory/vktMemoryBindingTests.hpp b/external/vulkancts/modules/vulkan/memory/vktMemoryBindingTests.hpp
new file mode 100644
index 0000000..75c486a
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/memory/vktMemoryBindingTests.hpp
@@ -0,0 +1,39 @@
+#ifndef _VKTMEMORYBINDINGTESTS_HPP
+#define _VKTMEMORYBINDINGTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Memory binding test excercising VK_KHR_bind_memory2 extension.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace memory
+{
+
+tcu::TestCaseGroup* createMemoryBindingTests (tcu::TestContext& testCtx);
+
+} // memory
+} // vkt
+
+#endif // _VKTMEMORYBINDINGTESTS_HPP
diff --git a/external/vulkancts/modules/vulkan/memory/vktMemoryTests.cpp b/external/vulkancts/modules/vulkan/memory/vktMemoryTests.cpp
index 23e3bb3..e3ba1c0 100644
--- a/external/vulkancts/modules/vulkan/memory/vktMemoryTests.cpp
+++ b/external/vulkancts/modules/vulkan/memory/vktMemoryTests.cpp
@@ -27,6 +27,7 @@
 #include "vktMemoryMappingTests.hpp"
 #include "vktMemoryPipelineBarrierTests.hpp"
 #include "vktMemoryRequirementsTests.hpp"
+#include "vktMemoryBindingTests.hpp"
 #include "vktTestGroupUtil.hpp"
 
 namespace vkt
@@ -45,6 +46,7 @@
 	memoryTests->addChild(createMappingTests			(testCtx));
 	memoryTests->addChild(createPipelineBarrierTests	(testCtx));
 	memoryTests->addChild(createRequirementsTests		(testCtx));
+	memoryTests->addChild(createMemoryBindingTests		(testCtx));
 }
 
 } // anonymous
diff --git a/external/vulkancts/mustpass/1.0.2/vk-default.txt b/external/vulkancts/mustpass/1.0.2/vk-default.txt
index 828d634..1968c33 100644
--- a/external/vulkancts/mustpass/1.0.2/vk-default.txt
+++ b/external/vulkancts/mustpass/1.0.2/vk-default.txt
@@ -43552,6 +43552,48 @@
 dEQP-VK.memory.requirements.extended.image.sparse_aliased_tiling_linear
 dEQP-VK.memory.requirements.extended.image.sparse_aliased_tiling_optimal
 dEQP-VK.memory.requirements.extended.image.sparse_residency_aliased_tiling_optimal
+dEQP-VK.memory.binding.regular.suballocated.buffer_33
+dEQP-VK.memory.binding.regular.suballocated.buffer_257
+dEQP-VK.memory.binding.regular.suballocated.buffer_4087
+dEQP-VK.memory.binding.regular.suballocated.buffer_8095
+dEQP-VK.memory.binding.regular.suballocated.buffer_1048577
+dEQP-VK.memory.binding.regular.suballocated.image_8_8
+dEQP-VK.memory.binding.regular.suballocated.image_8_33
+dEQP-VK.memory.binding.regular.suballocated.image_8_257
+dEQP-VK.memory.binding.regular.suballocated.image_33_8
+dEQP-VK.memory.binding.regular.suballocated.image_33_33
+dEQP-VK.memory.binding.regular.suballocated.image_33_257
+dEQP-VK.memory.binding.regular.suballocated.image_257_8
+dEQP-VK.memory.binding.regular.suballocated.image_257_33
+dEQP-VK.memory.binding.regular.suballocated.image_257_257
+dEQP-VK.memory.binding.regular.dedicated.buffer_33
+dEQP-VK.memory.binding.regular.dedicated.buffer_257
+dEQP-VK.memory.binding.regular.dedicated.buffer_4087
+dEQP-VK.memory.binding.regular.dedicated.buffer_8095
+dEQP-VK.memory.binding.regular.dedicated.buffer_1048577
+dEQP-VK.memory.binding.regular.dedicated.image_8_8
+dEQP-VK.memory.binding.regular.dedicated.image_8_33
+dEQP-VK.memory.binding.regular.dedicated.image_8_257
+dEQP-VK.memory.binding.regular.dedicated.image_33_8
+dEQP-VK.memory.binding.regular.dedicated.image_33_33
+dEQP-VK.memory.binding.regular.dedicated.image_33_257
+dEQP-VK.memory.binding.regular.dedicated.image_257_8
+dEQP-VK.memory.binding.regular.dedicated.image_257_33
+dEQP-VK.memory.binding.regular.dedicated.image_257_257
+dEQP-VK.memory.binding.aliasing.suballocated.buffer_33
+dEQP-VK.memory.binding.aliasing.suballocated.buffer_257
+dEQP-VK.memory.binding.aliasing.suballocated.buffer_4087
+dEQP-VK.memory.binding.aliasing.suballocated.buffer_8095
+dEQP-VK.memory.binding.aliasing.suballocated.buffer_1048577
+dEQP-VK.memory.binding.aliasing.suballocated.image_8_8
+dEQP-VK.memory.binding.aliasing.suballocated.image_8_33
+dEQP-VK.memory.binding.aliasing.suballocated.image_8_257
+dEQP-VK.memory.binding.aliasing.suballocated.image_33_8
+dEQP-VK.memory.binding.aliasing.suballocated.image_33_33
+dEQP-VK.memory.binding.aliasing.suballocated.image_33_257
+dEQP-VK.memory.binding.aliasing.suballocated.image_257_8
+dEQP-VK.memory.binding.aliasing.suballocated.image_257_33
+dEQP-VK.memory.binding.aliasing.suballocated.image_257_257
 dEQP-VK.pipeline.stencil.format.s8_uint.states.front_fail_decc_pass_repl_dfail_inv_comp_not_equal_back_fail_decc_pass_repl_dfail_keep_comp_less
 dEQP-VK.pipeline.stencil.format.s8_uint.states.front_fail_incc_pass_keep_dfail_inv_comp_not_equal_back_fail_decc_pass_repl_dfail_inv_comp_not_equal
 dEQP-VK.pipeline.stencil.format.s8_uint.states.front_fail_wrap_pass_decw_dfail_wrap_comp_less_back_fail_incc_pass_keep_dfail_inv_comp_not_equal
diff --git a/external/vulkancts/scripts/src/vulkan.h.in b/external/vulkancts/scripts/src/vulkan.h.in
index d9b59d2..e9e3053 100644
--- a/external/vulkancts/scripts/src/vulkan.h.in
+++ b/external/vulkancts/scripts/src/vulkan.h.in
@@ -281,6 +281,8 @@
     VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146002,
     VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = 1000146003,
     VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = 1000146004,
+	VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR = 1000157000,
+    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR = 1000157001,
     VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
     VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO,
     VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1),
@@ -952,6 +954,7 @@
     VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = 0x00000020,
     VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = 0x00000080,
     VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR = 0x00000100,
+	VK_IMAGE_CREATE_ALIAS_BIT_KHR = 0x00000400,
     VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkImageCreateFlagBits;
 typedef VkFlags VkImageCreateFlags;
@@ -5036,6 +5039,41 @@
     VkBool32           variablePointers;
 } VkPhysicalDeviceVariablePointerFeaturesKHR;
 
+#define VK_KHR_bind_memory2 1
+#define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1
+#define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2"
+
+typedef struct VkBindBufferMemoryInfoKHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkBuffer           buffer;
+    VkDeviceMemory     memory;
+    VkDeviceSize       memoryOffset;
+} VkBindBufferMemoryInfoKHR;
+
+typedef struct VkBindImageMemoryInfoKHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkImage            image;
+    VkDeviceMemory     memory;
+    VkDeviceSize       memoryOffset;
+} VkBindImageMemoryInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfoKHR* pBindInfos);
+typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfoKHR* pBindInfos);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2KHR(
+    VkDevice                                    device,
+    uint32_t                                    bindInfoCount,
+    const VkBindBufferMemoryInfoKHR*            pBindInfos);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR(
+    VkDevice                                    device,
+    uint32_t                                    bindInfoCount,
+    const VkBindImageMemoryInfoKHR*             pBindInfos);
+#endif
 
 #ifdef __cplusplus
 }