Merge pull request #373 from cdavis5e/bind-memory2

Support the VK_KHR_bind_memory2 extension.
diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md
index 0077861..a4de56f 100644
--- a/Docs/MoltenVK_Runtime_UserGuide.md
+++ b/Docs/MoltenVK_Runtime_UserGuide.md
@@ -223,6 +223,7 @@
 
 - `VK_KHR_16bit_storage`
 - `VK_KHR_8bit_storage`
+- `VK_KHR_bind_memory2`
 - `VK_KHR_dedicated_allocation`
 - `VK_KHR_descriptor_update_template`
 - `VK_KHR_get_memory_requirements2`
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
index bc1af21..3acd3d4 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
@@ -283,6 +283,8 @@
 	ADD_PROC_ADDR(vkCmdExecuteCommands);
 
 	// Supported extensions:
+	ADD_PROC_ADDR(vkBindBufferMemory2KHR);
+	ADD_PROC_ADDR(vkBindImageMemory2KHR);
 	ADD_PROC_ADDR(vkCreateDescriptorUpdateTemplateKHR);
 	ADD_PROC_ADDR(vkDestroyDescriptorUpdateTemplateKHR);
 	ADD_PROC_ADDR(vkUpdateDescriptorSetWithTemplateKHR);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKResource.h b/MoltenVK/MoltenVK/GPUObjects/MVKResource.h
index 5e3adfc..4128eec 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKResource.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKResource.h
@@ -47,6 +47,9 @@
 	/** Binds this resource to the specified offset within the specified memory allocation. */
 	virtual VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset);
 
+	/** Binds this resource according to the specified bind information. */
+	virtual VkResult bindDeviceMemory2(const void* pBindInfo);
+
 	/** Returns the device memory underlying this resource. */
 	inline MVKDeviceMemory* getDeviceMemory() { return _deviceMemory; }
 
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm b/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm
index c535fd5..b2806a5 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm
@@ -20,6 +20,18 @@
 #include "MVKCommandBuffer.h"
 
 
+struct MVKBindDeviceMemoryInfo {
+	VkStructureType sType;
+	void* pNext;
+	union {
+		VkBuffer buffer;
+		VkImage image;
+	};
+	VkDeviceMemory memory;
+	VkDeviceSize memoryOffset;
+};
+
+
 #pragma mark MVKResource
 
 VkResult MVKResource::bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) {
@@ -33,6 +45,11 @@
 	return VK_SUCCESS;
 }
 
+VkResult MVKResource::bindDeviceMemory2(const void* pBindInfo) {
+	auto* mvkBindInfo = (const MVKBindDeviceMemoryInfo*)pBindInfo;
+	return bindDeviceMemory((MVKDeviceMemory*)mvkBindInfo->memory, mvkBindInfo->memoryOffset);
+}
+
 // Returns whether the specified global memory barrier requires a sync between this
 // texture and host memory for the purpose of the host reading texture memory.
 bool MVKResource::needsHostReadSync(VkPipelineStageFlags srcStageMask,
diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
index f2a2c6c..791100f 100644
--- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def
+++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
@@ -32,6 +32,7 @@
 
 MVK_EXTENSION(KHR_16bit_storage, KHR_16BIT_STORAGE)
 MVK_EXTENSION(KHR_8bit_storage, KHR_8BIT_STORAGE)
+MVK_EXTENSION(KHR_bind_memory2, KHR_BIND_MEMORY_2)
 MVK_EXTENSION(KHR_dedicated_allocation, KHR_DEDICATED_ALLOCATION)
 MVK_EXTENSION(KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE)
 MVK_EXTENSION(KHR_get_memory_requirements2, KHR_GET_MEMORY_REQUIREMENTS_2)
diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
index b468859..869f8a0 100644
--- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm
+++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
@@ -1475,6 +1475,40 @@
 
 
 #pragma mark -
+#pragma mark VK_KHR_bind_memory2 extension
+
+MVK_PUBLIC_SYMBOL VkResult vkBindBufferMemory2KHR(
+    VkDevice                                       device,
+    uint32_t                                       bindInfoCount,
+    const VkBindBufferMemoryInfoKHR*               pBindInfos) {
+    VkResult res;
+    for (uint32_t i = 0; i < bindInfoCount; ++i) {
+        MVKBuffer* mvkBuff = (MVKBuffer*)pBindInfos[i].buffer;
+        res = mvkBuff->bindDeviceMemory2(&pBindInfos[i]);
+        if (res != VK_SUCCESS) {
+            break;
+        }
+    }
+    return res;
+}
+
+MVK_PUBLIC_SYMBOL VkResult vkBindImageMemory2KHR(
+    VkDevice                                       device,
+    uint32_t                                       bindInfoCount,
+    const VkBindImageMemoryInfoKHR*                pBindInfos) {
+    VkResult res;
+    for (uint32_t i = 0; i < bindInfoCount; ++i) {
+        MVKImage* mvkImg = (MVKImage*)pBindInfos[i].image;
+        res = mvkImg->bindDeviceMemory2(&pBindInfos[i]);
+        if (res != VK_SUCCESS) {
+            break;
+        }
+    }
+    return res;
+}
+
+
+#pragma mark -
 #pragma mark VK_KHR_descriptor_update_template extension
 
 MVK_PUBLIC_SYMBOL VkResult vkCreateDescriptorUpdateTemplateKHR(