v98: replace vkUpdateDescriptors() by vkUpdateDescriptorSets()

Only slightly tested.

Conflicts:
	include/vulkan.h
diff --git a/include/vkLayer.h b/include/vkLayer.h
index e19b706..65656a0 100644
--- a/include/vkLayer.h
+++ b/include/vkLayer.h
@@ -93,7 +93,7 @@
     PFN_vkResetDescriptorPool ResetDescriptorPool;
     PFN_vkAllocDescriptorSets AllocDescriptorSets;
     PFN_vkClearDescriptorSets ClearDescriptorSets;
-    PFN_vkUpdateDescriptors UpdateDescriptors;
+    PFN_vkUpdateDescriptorSets UpdateDescriptorSets;
     PFN_vkCreateDynamicViewportState CreateDynamicViewportState;
     PFN_vkCreateDynamicRasterState CreateDynamicRasterState;
     PFN_vkCreateDynamicColorBlendState CreateDynamicColorBlendState;
diff --git a/include/vulkan.h b/include/vulkan.h
index 30d2fb7..ed0ad2f 100644
--- a/include/vulkan.h
+++ b/include/vulkan.h
@@ -33,7 +33,7 @@
 #include "vk_platform.h"
 
 // Vulkan API version supported by this file
-#define VK_API_VERSION VK_MAKE_VERSION(0, 97, 2)
+#define VK_API_VERSION VK_MAKE_VERSION(0, 98, 0)
 
 #ifdef __cplusplus
 extern "C"
@@ -799,8 +799,8 @@
     VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO                     = 2,
     VK_STRUCTURE_TYPE_MEMORY_OPEN_INFO                      = 3,
     VK_STRUCTURE_TYPE_PEER_MEMORY_OPEN_INFO                 = 4,
-    VK_STRUCTURE_TYPE_BUFFER_VIEW_ATTACH_INFO               = 5,
-    VK_STRUCTURE_TYPE_IMAGE_VIEW_ATTACH_INFO                = 6,
+//    VK_STRUCTURE_TYPE_BUFFER_VIEW_ATTACH_INFO               = 5,
+//    VK_STRUCTURE_TYPE_IMAGE_VIEW_ATTACH_INFO                = 6,
     VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO                = 7,
     VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO     = 8,
     VK_STRUCTURE_TYPE_DEPTH_STENCIL_VIEW_CREATE_INFO        = 9,
@@ -840,14 +840,11 @@
     VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER                 = 43,
     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER                  = 44,
     VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO           = 45,
-    VK_STRUCTURE_TYPE_UPDATE_SAMPLERS                       = 46,
-    VK_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES               = 47,
-    VK_STRUCTURE_TYPE_UPDATE_IMAGES                         = 48,
-    VK_STRUCTURE_TYPE_UPDATE_BUFFERS                        = 49,
-    VK_STRUCTURE_TYPE_UPDATE_AS_COPY                        = 50,
-    VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO                  = 51,
-    VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO           = 52,
-    VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE                   = 53,
+    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET                  = 46,
+    VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET                   = 47,
+    VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO                  = 48,
+    VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO           = 49,
+    VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE                   = 50,
 
     VK_ENUM_RANGE(STRUCTURE_TYPE, APPLICATION_INFO, MAPPED_MEMORY_RANGE)
 } VkStructureType;
@@ -1412,79 +1409,44 @@
     VkFormatFeatureFlags                        optimalTilingFeatures;      // Format features in case of optimal tiling
 } VkFormatProperties;
 
-typedef struct VkBufferViewAttachInfo_
+typedef struct VkDescriptorInfo_
 {
-    VkStructureType                             sType;                      // Must be VK_STRUCTURE_TYPE_BUFFER_VIEW_ATTACH_INFO
+    VkBufferView                                bufferView;                 // Buffer view to write to the descriptor (in case it's a buffer descriptor, otherwise should be VK_NULL_HANDLE)
+    VkSampler                                   sampler;                    // Sampler to write to the descriptor (in case it's a SAMPLER or COMBINED_IMAGE_SAMPLER descriptor, otherwise should be VK_NULL_HANDLE)
+    VkImageView                                 imageView;                  // Image view to write to the descriptor (in case it's a SAMPLED_IMAGE, STORAGE_IMAGE, or COMBINED_IMAGE_SAMPLER descriptor, otherwise should be VK_NULL_HANDLE)
+    VkImageLayout                               imageLayout;                // Layout the image is expected to be in when accessed using this descriptor (only used if <imageView> is not VK_NULL_HANDLE)
+} VkDescriptorInfo;
+
+typedef struct VkWriteDescriptorSet_
+{
+    VkStructureType                             sType;                      // Must be VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET
     const void*                                 pNext;                      // Pointer to next structure
-    VkBufferView                                view;
-} VkBufferViewAttachInfo;
 
-typedef struct VkImageViewAttachInfo_
+    VkDescriptorSet                             destSet;                    // Destination descriptor set
+    uint32_t                                    destBinding;                // Binding within the destination descriptor set to write
+    uint32_t                                    destArrayElement;           // Array element within the destination binding to write
+
+    uint32_t                                    count;                      // Number of descriptors to write (determines the size of the array pointed by <pDescriptors>)
+
+    VkDescriptorType                            descriptorType;             // Descriptor type to write (determines which fields of the array pointed by <pDescriptors> are going to be used)
+    const VkDescriptorInfo*                     pDescriptors;               // Array of info structures describing the descriptors to write
+} VkWriteDescriptorSet;
+
+typedef struct VkCopyDescriptorSet_
 {
-    VkStructureType                             sType;                      // Must be VK_STRUCTURE_TYPE_IMAGE_VIEW_ATTACH_INFO
+    VkStructureType                             sType;                      // Must be VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET
     const void*                                 pNext;                      // Pointer to next structure
-    VkImageView                                 view;
-    VkImageLayout                               layout;
-} VkImageViewAttachInfo;
 
-typedef struct VkUpdateSamplers_
-{
-    VkStructureType                             sType;                      // Must be VK_STRUCTURE_TYPE_UPDATE_SAMPLERS
-    const void*                                 pNext;                      // Pointer to next structure
-    uint32_t                                    binding;                    // Binding of the sampler (array)
-    uint32_t                                    arrayIndex;                 // First element of the array to update or zero otherwise
-    uint32_t                                    count;                      // Number of elements to update
-    const VkSampler*                            pSamplers;
-} VkUpdateSamplers;
+    VkDescriptorSet                             srcSet;                     // Source descriptor set
+    uint32_t                                    srcBinding;                 // Binding within the source descriptor set to copy from
+    uint32_t                                    srcArrayElement;            // Array element within the source binding to copy from
 
-typedef struct VkSamplerImageViewInfo_
-{
-    VkSampler                                   sampler;
-    const VkImageViewAttachInfo*                pImageView;
-} VkSamplerImageViewInfo;
+    VkDescriptorSet                             destSet;                    // Destination descriptor set
+    uint32_t                                    destBinding;                // Binding within the destination descriptor set to copy to
+    uint32_t                                    destArrayElement;           // Array element within the destination binding to copy to
 
-typedef struct VkUpdateSamplerTextures_
-{
-    VkStructureType                             sType;                      // Must be VK_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES
-    const void*                                 pNext;                      // Pointer to next structure
-    uint32_t                                    binding;                    // Binding of the combined texture sampler (array)
-    uint32_t                                    arrayIndex;                 // First element of the array to update or zero otherwise
-    uint32_t                                    count;                      // Number of elements to update
-    const VkSamplerImageViewInfo*               pSamplerImageViews;
-} VkUpdateSamplerTextures;
-
-typedef struct VkUpdateImages_
-{
-    VkStructureType                             sType;                     // Must be VK_STRUCTURE_TYPE_UPDATE_IMAGES
-    const void*                                 pNext;                     // Pointer to next structure
-    VkDescriptorType                            descriptorType;
-    uint32_t                                    binding;                   // Binding of the image (array)
-    uint32_t                                    arrayIndex;                // First element of the array to update or zero otherwise
-    uint32_t                                    count;                     // Number of elements to update
-    const VkImageViewAttachInfo*                pImageViews;
-} VkUpdateImages;
-
-typedef struct VkUpdateBuffers_
-{
-    VkStructureType                             sType;                    // Must be VK_STRUCTURE_TYPE_UPDATE_BUFFERS
-    const void*                                 pNext;                    // Pointer to next structure
-    VkDescriptorType                            descriptorType;
-    uint32_t                                    binding;                  // Binding of the buffer (array)
-    uint32_t                                    arrayIndex;               // First element of the array to update or zero otherwise
-    uint32_t                                    count;                    // Number of elements to update
-    const VkBufferViewAttachInfo*               pBufferViews;
-} VkUpdateBuffers;
-
-typedef struct VkUpdateAsCopy_
-{
-    VkStructureType                             sType;                      // Must be VK_STRUCTURE_TYPE_UPDATE_AS_COPY
-    const void*                                 pNext;                      // Pointer to next structure
-    VkDescriptorType                            descriptorType;
-    VkDescriptorSet                             descriptorSet;
-    uint32_t                                    binding;
-    uint32_t                                    arrayElement;
-    uint32_t                                    count;
-} VkUpdateAsCopy;
+    uint32_t                                    count;                      // Number of descriptors to copy
+} VkCopyDescriptorSet;
 
 typedef struct VkBufferCreateInfo_
 {
@@ -2190,7 +2152,7 @@
 typedef VkResult (VKAPI *PFN_vkResetDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool);
 typedef VkResult (VKAPI *PFN_vkAllocDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorSetUsage setUsage, uint32_t count, const VkDescriptorSetLayout* pSetLayouts, VkDescriptorSet* pDescriptorSets, uint32_t* pCount);
 typedef void     (VKAPI *PFN_vkClearDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, const VkDescriptorSet* pDescriptorSets);
-typedef void     (VKAPI *PFN_vkUpdateDescriptors)(VkDevice device, VkDescriptorSet descriptorSet, uint32_t updateCount, const void** ppUpdateArray);
+typedef VkResult (VKAPI *PFN_vkUpdateDescriptorSets)(VkDevice device, uint32_t writeCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t copyCount, const VkCopyDescriptorSet* pDescriptorCopies);
 typedef VkResult (VKAPI *PFN_vkCreateDynamicViewportState)(VkDevice device, const VkDynamicVpStateCreateInfo* pCreateInfo, VkDynamicVpState* pState);
 typedef VkResult (VKAPI *PFN_vkCreateDynamicRasterState)(VkDevice device, const VkDynamicRsStateCreateInfo* pCreateInfo, VkDynamicRsState* pState);
 typedef VkResult (VKAPI *PFN_vkCreateDynamicColorBlendState)(VkDevice device, const VkDynamicCbStateCreateInfo* pCreateInfo, VkDynamicCbState* pState);
@@ -2650,11 +2612,12 @@
     uint32_t                                    count,
     const VkDescriptorSet*                      pDescriptorSets);
 
-void VKAPI vkUpdateDescriptors(
+VkResult VKAPI vkUpdateDescriptorSets(
     VkDevice                                    device,
-    VkDescriptorSet                             descriptorSet,
-    uint32_t                                    updateCount,
-    const void**                                ppUpdateArray);
+    uint32_t                                    writeCount,
+    const VkWriteDescriptorSet*                 pDescriptorWrites,
+    uint32_t                                    copyCount,
+    const VkCopyDescriptorSet*                  pDescriptorCopies);
 
 // State object functions
 
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index d90b1ee..c78488d 100755
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -577,11 +577,8 @@
     char str[1024];
     switch (pUpdateStruct->sType)
     {
-        case VK_STRUCTURE_TYPE_UPDATE_SAMPLERS:
-        case VK_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES:
-        case VK_STRUCTURE_TYPE_UPDATE_IMAGES:
-        case VK_STRUCTURE_TYPE_UPDATE_BUFFERS:
-        case VK_STRUCTURE_TYPE_UPDATE_AS_COPY:
+        case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
+        case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
             return 1;
         default:
             sprintf(str, "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
@@ -595,16 +592,10 @@
     char str[1024];
     switch (pUpdateStruct->sType)
     {
-        case VK_STRUCTURE_TYPE_UPDATE_SAMPLERS:
-            return ((VkUpdateSamplers*)pUpdateStruct)->binding;
-        case VK_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES:
-            return ((VkUpdateSamplerTextures*)pUpdateStruct)->binding;
-        case VK_STRUCTURE_TYPE_UPDATE_IMAGES:
-            return ((VkUpdateImages*)pUpdateStruct)->binding;
-        case VK_STRUCTURE_TYPE_UPDATE_BUFFERS:
-            return ((VkUpdateBuffers*)pUpdateStruct)->binding;
-        case VK_STRUCTURE_TYPE_UPDATE_AS_COPY:
-            return ((VkUpdateAsCopy*)pUpdateStruct)->binding;
+        case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
+            return ((VkWriteDescriptorSet*)pUpdateStruct)->destBinding;
+        case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
+            return ((VkCopyDescriptorSet*)pUpdateStruct)->destBinding;
         default:
             sprintf(str, "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
             layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_INVALID_UPDATE_STRUCT, "DS", str);
@@ -617,17 +608,11 @@
     char str[1024];
     switch (pUpdateStruct->sType)
     {
-        case VK_STRUCTURE_TYPE_UPDATE_SAMPLERS:
-            return (((VkUpdateSamplers*)pUpdateStruct)->arrayIndex);
-        case VK_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES:
-            return (((VkUpdateSamplerTextures*)pUpdateStruct)->arrayIndex);
-        case VK_STRUCTURE_TYPE_UPDATE_IMAGES:
-            return (((VkUpdateImages*)pUpdateStruct)->arrayIndex);
-        case VK_STRUCTURE_TYPE_UPDATE_BUFFERS:
-            return (((VkUpdateBuffers*)pUpdateStruct)->arrayIndex);
-        case VK_STRUCTURE_TYPE_UPDATE_AS_COPY:
+        case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
+            return ((VkWriteDescriptorSet*)pUpdateStruct)->destArrayElement;
+        case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
             // TODO : Need to understand this case better and make sure code is correct
-            return (((VkUpdateAsCopy*)pUpdateStruct)->arrayElement);
+            return ((VkCopyDescriptorSet*)pUpdateStruct)->destArrayElement;
         default:
             sprintf(str, "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
             layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_INVALID_UPDATE_STRUCT, "DS", str);
@@ -640,17 +625,11 @@
     char str[1024];
     switch (pUpdateStruct->sType)
     {
-        case VK_STRUCTURE_TYPE_UPDATE_SAMPLERS:
-            return (((VkUpdateSamplers*)pUpdateStruct)->count);
-        case VK_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES:
-            return (((VkUpdateSamplerTextures*)pUpdateStruct)->count);
-        case VK_STRUCTURE_TYPE_UPDATE_IMAGES:
-            return (((VkUpdateImages*)pUpdateStruct)->count);
-        case VK_STRUCTURE_TYPE_UPDATE_BUFFERS:
-            return (((VkUpdateBuffers*)pUpdateStruct)->count);
-        case VK_STRUCTURE_TYPE_UPDATE_AS_COPY:
+        case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
+            return ((VkWriteDescriptorSet*)pUpdateStruct)->count;
+        case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
             // TODO : Need to understand this case better and make sure code is correct
-            return (((VkUpdateAsCopy*)pUpdateStruct)->count);
+            return ((VkCopyDescriptorSet*)pUpdateStruct)->count;
         default:
             sprintf(str, "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
             layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_INVALID_UPDATE_STRUCT, "DS", str);
@@ -694,20 +673,12 @@
     char str[1024];
     switch (pUpdateStruct->sType)
     {
-        case VK_STRUCTURE_TYPE_UPDATE_SAMPLERS:
-            actualType = VK_DESCRIPTOR_TYPE_SAMPLER;
+        case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
+            actualType = ((VkWriteDescriptorSet*)pUpdateStruct)->descriptorType;
             break;
-        case VK_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES:
-            actualType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-            break;
-        case VK_STRUCTURE_TYPE_UPDATE_IMAGES:
-            actualType = ((VkUpdateImages*)pUpdateStruct)->descriptorType;
-            break;
-        case VK_STRUCTURE_TYPE_UPDATE_BUFFERS:
-            actualType = ((VkUpdateBuffers*)pUpdateStruct)->descriptorType;
-            break;
-        case VK_STRUCTURE_TYPE_UPDATE_AS_COPY:
-            actualType = ((VkUpdateAsCopy*)pUpdateStruct)->descriptorType;
+        case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
+            /* no need to validate */
+            return 1;
             break;
         default:
             sprintf(str, "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
@@ -726,61 +697,27 @@
 static GENERIC_HEADER* shadowUpdateNode(GENERIC_HEADER* pUpdate)
 {
     GENERIC_HEADER* pNewNode = NULL;
-    VkUpdateSamplers* pUS = NULL;
-    VkUpdateSamplerTextures* pUST = NULL;
-    VkUpdateBuffers* pUB = NULL;
-    VkUpdateImages* pUI = NULL;
-    VkUpdateAsCopy* pUAC = NULL;
+    VkWriteDescriptorSet* pWDS = NULL;
+    VkCopyDescriptorSet* pCDS = NULL;
     size_t array_size = 0;
     size_t base_array_size = 0;
     size_t total_array_size = 0;
     size_t baseBuffAddr = 0;
-    VkImageViewAttachInfo** ppLocalImageViews = NULL;
-    VkBufferViewAttachInfo** ppLocalBufferViews = NULL;
     char str[1024];
     switch (pUpdate->sType)
     {
-        case VK_STRUCTURE_TYPE_UPDATE_SAMPLERS:
-            pUS = new VkUpdateSamplers;
-            pNewNode = (GENERIC_HEADER*)pUS;
-            memcpy(pUS, pUpdate, sizeof(VkUpdateSamplers));
-            pUS->pSamplers = new VkSampler[pUS->count];
-            array_size = sizeof(VkSampler) * pUS->count;
-            memcpy((void*)pUS->pSamplers, ((VkUpdateSamplers*)pUpdate)->pSamplers, array_size);
+        case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
+            pWDS = new VkWriteDescriptorSet;
+            pNewNode = (GENERIC_HEADER*)pWDS;
+            memcpy(pWDS, pUpdate, sizeof(VkWriteDescriptorSet));
+            pWDS->pDescriptors = new VkDescriptorInfo[pWDS->count];
+            array_size = sizeof(VkDescriptorInfo) * pWDS->count;
+            memcpy((void*)pWDS->pDescriptors, ((VkWriteDescriptorSet*)pUpdate)->pDescriptors, array_size);
             break;
-        case VK_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES:
-            pUST = new VkUpdateSamplerTextures;
-            pNewNode = (GENERIC_HEADER*)pUST;
-            memcpy(pUST, pUpdate, sizeof(VkUpdateSamplerTextures));
-            pUST->pSamplerImageViews = new VkSamplerImageViewInfo[pUST->count];
-            array_size = sizeof(VkSamplerImageViewInfo) * pUST->count;
-            memcpy((void*)pUST->pSamplerImageViews, ((VkUpdateSamplerTextures*)pUpdate)->pSamplerImageViews, array_size);
-            for (uint32_t i = 0; i < pUST->count; i++) {
-                VkImageViewAttachInfo** ppIV = (VkImageViewAttachInfo**)&pUST->pSamplerImageViews[i].pImageView;
-                *ppIV = new VkImageViewAttachInfo;
-                memcpy((void*)*ppIV, ((VkUpdateSamplerTextures*)pUpdate)->pSamplerImageViews[i].pImageView, sizeof(VkImageViewAttachInfo));
-            }
-            break;
-        case VK_STRUCTURE_TYPE_UPDATE_IMAGES:
-            pUI = new VkUpdateImages;
-            pNewNode = (GENERIC_HEADER*)pUI;
-            memcpy(pUI, pUpdate, sizeof(VkUpdateImages));
-            pUI->pImageViews = new VkImageViewAttachInfo[pUI->count];
-            array_size = (sizeof(VkImageViewAttachInfo) * pUI->count);
-            memcpy((void*)pUI->pImageViews, ((VkUpdateImages*)pUpdate)->pImageViews, array_size);
-            break;
-        case VK_STRUCTURE_TYPE_UPDATE_BUFFERS:
-            pUB = new VkUpdateBuffers;
-            pNewNode = (GENERIC_HEADER*)pUB;
-            memcpy(pUB, pUpdate, sizeof(VkUpdateBuffers));
-            pUB->pBufferViews = new VkBufferViewAttachInfo[pUB->count];
-            array_size = (sizeof(VkBufferViewAttachInfo) * pUB->count);
-            memcpy((void*)pUB->pBufferViews, ((VkUpdateBuffers*)pUpdate)->pBufferViews, array_size);
-            break;
-        case VK_STRUCTURE_TYPE_UPDATE_AS_COPY:
-            pUAC = new VkUpdateAsCopy;
-            pUpdate = (GENERIC_HEADER*)pUAC;
-            memcpy(pUAC, pUpdate, sizeof(VkUpdateAsCopy));
+        case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
+            pCDS = new VkCopyDescriptorSet;
+            pUpdate = (GENERIC_HEADER*)pCDS;
+            memcpy(pCDS, pUpdate, sizeof(VkCopyDescriptorSet));
             break;
         default:
             sprintf(str, "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdate->sType), pUpdate->sType);
@@ -791,19 +728,28 @@
     pNewNode->pNext = NULL;
     return pNewNode;
 }
-// For given ds, update its mapping based on ppUpdateArray
-static bool32_t dsUpdate(VkDescriptorSet ds, uint32_t updateCount, const void** ppUpdateArray)
+// update DS mappings based on ppUpdateArray
+static bool32_t dsUpdate(VkStructureType type, uint32_t updateCount, const void* pUpdateArray)
 {
+    const VkWriteDescriptorSet *pWDS = NULL;
+    const VkCopyDescriptorSet *pCDS = NULL;
     bool32_t result = 1;
-    SET_NODE* pSet = getSetNode(ds);
+
+    if (type == VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET)
+        pWDS = (const VkWriteDescriptorSet *) pUpdateArray;
+    else
+        pCDS = (const VkCopyDescriptorSet *) pUpdateArray;
+
     loader_platform_thread_lock_mutex(&globalLock);
-    g_lastBoundDescriptorSet = pSet->set;
     LAYOUT_NODE* pLayout = NULL;
     VkDescriptorSetLayoutCreateInfo* pLayoutCI = NULL;
     // TODO : If pCIList is NULL, flag error
     // Perform all updates
     for (uint32_t i = 0; i < updateCount; i++) {
-        GENERIC_HEADER* pUpdate = (GENERIC_HEADER*)ppUpdateArray[i];
+        VkDescriptorSet ds = (pWDS) ? pWDS->destSet : pCDS->destSet;
+        SET_NODE* pSet = setMap[ds]; // getSetNode() without locking
+        g_lastBoundDescriptorSet = pSet->set;
+        GENERIC_HEADER* pUpdate = (pWDS) ? (GENERIC_HEADER*) &pWDS[i] : (GENERIC_HEADER*) &pCDS[i];
         pLayout = pSet->pLayout;
         // First verify valid update struct
         if (!validUpdateStruct(pUpdate)) {
@@ -876,40 +822,17 @@
         pFreeUpdate = pShadowUpdate;
         pShadowUpdate = (GENERIC_HEADER*)pShadowUpdate->pNext;
         uint32_t index = 0;
-        VkUpdateSamplers* pUS = NULL;
-        VkUpdateSamplerTextures* pUST = NULL;
-        VkUpdateImages* pUI = NULL;
-        VkUpdateBuffers* pUB = NULL;
+        VkWriteDescriptorSet * pWDS = NULL;
+        VkCopyDescriptorSet * pCDS = NULL;
         void** ppToFree = NULL;
         switch (pFreeUpdate->sType)
         {
-            case VK_STRUCTURE_TYPE_UPDATE_SAMPLERS:
-                pUS = (VkUpdateSamplers*)pFreeUpdate;
-                if (pUS->pSamplers)
-                    delete[] pUS->pSamplers;
+            case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
+                pWDS = (VkWriteDescriptorSet*)pFreeUpdate;
+                if (pWDS->pDescriptors)
+                    delete[] pWDS->pDescriptors;
                 break;
-            case VK_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES:
-                pUST = (VkUpdateSamplerTextures*)pFreeUpdate;
-                if (pUST->pSamplerImageViews) {
-                    for (index = 0; index < pUST->count; index++) {
-                        if (pUST->pSamplerImageViews[index].pImageView) {
-                            delete pUST->pSamplerImageViews[index].pImageView;
-                        }
-                    }
-                    delete[] pUST->pSamplerImageViews;
-                }
-                break;
-            case VK_STRUCTURE_TYPE_UPDATE_IMAGES:
-                pUI = (VkUpdateImages*)pFreeUpdate;
-                if (pUI->pImageViews)
-                    delete[] pUI->pImageViews;
-                break;
-            case VK_STRUCTURE_TYPE_UPDATE_BUFFERS:
-                pUB = (VkUpdateBuffers*)pFreeUpdate;
-                if (pUB->pBufferViews)
-                    delete[] pUB->pBufferViews;
-                break;
-            case VK_STRUCTURE_TYPE_UPDATE_AS_COPY:
+            case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
                 break;
             default:
                 assert(0);
@@ -1104,6 +1027,7 @@
 // Common Dot dumping code
 static void dsCoreDumpDot(const VkDescriptorSet ds, FILE* pOutFile)
 {
+#if 0
     SET_NODE* pSet = getSetNode(ds);
     if (pSet) {
         POOL_NODE* pPool = getPoolNode(pSet->pool);
@@ -1226,6 +1150,7 @@
         fprintf(pOutFile, "}\n");
         fprintf(pOutFile, "}\n");
     }
+#endif
 }
 // Dump subgraph w/ DS info
 static void dsDumpDot(const VkCmdBuffer cb, FILE* pOutFile)
@@ -1859,14 +1784,13 @@
     nextTable.ClearDescriptorSets(device, descriptorPool, count, pDescriptorSets);
 }
 
-VK_LAYER_EXPORT void VKAPI vkUpdateDescriptors(VkDevice device, VkDescriptorSet descriptorSet, uint32_t updateCount, const void** ppUpdateArray)
+VK_LAYER_EXPORT VkResult VKAPI vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t copyCount, const VkCopyDescriptorSet* pDescriptorCopies)
 {
-    SET_NODE* pSet = getSetNode(descriptorSet);
-
-    // pUpdateChain is an array of VK_UPDATE_* struct ptrs defining the mappings for the descriptors
-    if (dsUpdate(descriptorSet, updateCount, ppUpdateArray)) {
-        nextTable.UpdateDescriptors(device, descriptorSet, updateCount, ppUpdateArray);
-    }
+    if (dsUpdate(VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, writeCount, pDescriptorWrites) &&
+        dsUpdate(VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET, copyCount, pDescriptorCopies))
+        return nextTable.UpdateDescriptorSets(device, writeCount, pDescriptorWrites, copyCount, pDescriptorCopies);
+    else
+        return VK_ERROR_UNKNOWN;
 }
 
 VK_LAYER_EXPORT VkResult VKAPI vkCreateDynamicViewportState(VkDevice device, const VkDynamicVpStateCreateInfo* pCreateInfo, VkDynamicVpState* pState)
@@ -2761,8 +2685,8 @@
         return (void*) vkAllocDescriptorSets;
     if (!strcmp(funcName, "vkClearDescriptorSets"))
         return (void*) vkClearDescriptorSets;
-    if (!strcmp(funcName, "vkUpdateDescriptors"))
-        return (void*) vkUpdateDescriptors;
+    if (!strcmp(funcName, "vkUpdateDescriptorSets"))
+        return (void*) vkUpdateDescriptorSets;
     if (!strcmp(funcName, "vkCreateDynamicViewportState"))
         return (void*) vkCreateDynamicViewportState;
     if (!strcmp(funcName, "vkCreateDynamicRasterState"))
diff --git a/layers/draw_state.h b/layers/draw_state.h
index 1915e71..a7b0a20 100644
--- a/layers/draw_state.h
+++ b/layers/draw_state.h
@@ -108,13 +108,13 @@
 typedef struct _IMAGE_NODE {
     VkImageView             image;
     VkImageViewCreateInfo createInfo;
-    VkImageViewAttachInfo attachInfo;
+    VkDescriptorInfo descriptorInfo;
 } IMAGE_NODE;
 
 typedef struct _BUFFER_NODE {
     VkBufferView             buffer;
     VkBufferViewCreateInfo createInfo;
-    VkBufferViewAttachInfo attachInfo;
+    VkDescriptorInfo descriptorInfo;
 } BUFFER_NODE;
 
 typedef struct _DYNAMIC_STATE_NODE {
diff --git a/layers/glave_snapshot.c b/layers/glave_snapshot.c
index 1c15544..358fb99 100644
--- a/layers/glave_snapshot.c
+++ b/layers/glave_snapshot.c
@@ -1144,14 +1144,6 @@
     nextTable.ClearDescriptorSets(device, descriptorPool, count, pDescriptorSets);
 }
 
-VK_LAYER_EXPORT void VKAPI vkUpdateDescriptors(VkDevice device, VkDescriptorSet descriptorSet, uint32_t updateCount, const void** ppUpdateArray)
-{
-    loader_platform_thread_lock_mutex(&objLock);
-    ll_increment_use_count((void*)descriptorSet, VK_OBJECT_TYPE_DESCRIPTOR_SET);
-    loader_platform_thread_unlock_mutex(&objLock);
-    nextTable.UpdateDescriptors(device, descriptorSet, updateCount, ppUpdateArray);
-}
-
 VK_LAYER_EXPORT VkResult VKAPI vkCreateDynamicViewportState(VkDevice device, const VkDynamicVpStateCreateInfo* pCreateInfo, VkDynamicVpState* pState)
 {
     loader_platform_thread_lock_mutex(&objLock);
diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp
index 2ee5d78..f91518d 100644
--- a/layers/param_checker.cpp
+++ b/layers/param_checker.cpp
@@ -1034,10 +1034,10 @@
     nextTable.ClearDescriptorSets(device, descriptorPool, count, pDescriptorSets);
 }
 
-VK_LAYER_EXPORT void VKAPI vkUpdateDescriptors(VkDevice device, VkDescriptorSet descriptorSet, uint32_t updateCount, const void** ppUpdateArray)
+VK_LAYER_EXPORT VkResult VKAPI vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t copyCount, const VkCopyDescriptorSet* pDescriptorCopies)
 {
 
-    nextTable.UpdateDescriptors(device, descriptorSet, updateCount, ppUpdateArray);
+    return nextTable.UpdateDescriptorSets(device, writeCount, pDescriptorWrites, copyCount, pDescriptorCopies);
 }
 
 VK_LAYER_EXPORT VkResult VKAPI vkCreateDynamicViewportState(VkDevice device, const VkDynamicVpStateCreateInfo* pCreateInfo, VkDynamicVpState* pState)
diff --git a/loader/gpa_helper.h b/loader/gpa_helper.h
index 28c10cf..eb8d1fb 100644
--- a/loader/gpa_helper.h
+++ b/loader/gpa_helper.h
@@ -166,8 +166,8 @@
         return (void*) vkAllocDescriptorSets;
     if (!strcmp(name, "ClearDescriptorSets"))
         return (void*) vkClearDescriptorSets;
-    if (!strcmp(name, "UpdateDescriptors"))
-        return (void*) vkUpdateDescriptors;
+    if (!strcmp(name, "UpdateDescriptorSets"))
+        return (void*) vkUpdateDescriptorSets;
     if (!strcmp(name, "CreateDynamicViewportState"))
         return (void*) vkCreateDynamicViewportState;
     if (!strcmp(name, "CreateDynamicRasterState"))
diff --git a/loader/table_ops.h b/loader/table_ops.h
index 49107bb..37e3774 100644
--- a/loader/table_ops.h
+++ b/loader/table_ops.h
@@ -99,7 +99,7 @@
     table->ResetDescriptorPool = (PFN_vkResetDescriptorPool) gpa(gpu, "vkResetDescriptorPool");
     table->AllocDescriptorSets = (PFN_vkAllocDescriptorSets) gpa(gpu, "vkAllocDescriptorSets");
     table->ClearDescriptorSets = (PFN_vkClearDescriptorSets) gpa(gpu, "vkClearDescriptorSets");
-    table->UpdateDescriptors = (PFN_vkUpdateDescriptors) gpa(gpu, "vkUpdateDescriptors");
+    table->UpdateDescriptorSets = (PFN_vkUpdateDescriptorSets) gpa(gpu, "vkUpdateDescriptorSets");
     table->CreateDynamicViewportState = (PFN_vkCreateDynamicViewportState) gpa(gpu, "vkCreateDynamicViewportState");
     table->CreateDynamicRasterState = (PFN_vkCreateDynamicRasterState) gpa(gpu, "vkCreateDynamicRasterState");
     table->CreateDynamicColorBlendState = (PFN_vkCreateDynamicColorBlendState) gpa(gpu, "vkCreateDynamicColorBlendState");
@@ -300,8 +300,8 @@
         return (void *) table->AllocDescriptorSets;
     if (!strcmp(name, "ClearDescriptorSets"))
         return (void *) table->ClearDescriptorSets;
-    if (!strcmp(name, "UpdateDescriptors"))
-        return (void *) table->UpdateDescriptors;
+    if (!strcmp(name, "UpdateDescriptorSets"))
+        return (void *) table->UpdateDescriptorSets;
     if (!strcmp(name, "CreateDynamicViewportState"))
         return (void *) table->CreateDynamicViewportState;
     if (!strcmp(name, "CreateDynamicRasterState"))
diff --git a/loader/trampoline.c b/loader/trampoline.c
index d07be99..082a5c2 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -602,13 +602,13 @@
     disp->ClearDescriptorSets(device, descriptorPool, count, pDescriptorSets);
 }
 
-LOADER_EXPORT void VKAPI vkUpdateDescriptors(VkDevice device, VkDescriptorSet descriptorSet, uint32_t updateCount, const void** ppUpdateArray)
+LOADER_EXPORT VkResult VKAPI vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t copyCount, const VkCopyDescriptorSet* pDescriptorCopies)
 {
     const VkLayerDispatchTable *disp;
 
     disp = loader_get_dispatch(device);
 
-    disp->UpdateDescriptors(device, descriptorSet, updateCount, ppUpdateArray);
+    return disp->UpdateDescriptorSets(device, writeCount, pDescriptorWrites, copyCount, pDescriptorCopies);
 }
 
 LOADER_EXPORT VkResult VKAPI vkCreateDynamicViewportState(VkDevice device, const VkDynamicVpStateCreateInfo* pCreateInfo, VkDynamicVpState* pState)
diff --git a/loader/vulkan.def b/loader/vulkan.def
index a01e30e..2d92c89 100644
--- a/loader/vulkan.def
+++ b/loader/vulkan.def
@@ -93,7 +93,6 @@
    vkResetDescriptorPool
    vkAllocDescriptorSets
    vkClearDescriptorSets
-   vkUpdateDescriptors
    vkCreateDynamicViewportState
    vkCreateDynamicRasterState
    vkCreateDynamicColorBlendState
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 05fb363..4393d1d 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -1237,20 +1237,26 @@
     err = vkCreateSampler(m_device->device(), &sampler_ci, &sampler);
     ASSERT_VK_SUCCESS(err);
 
-    VkUpdateSamplers *pSamplerUpdate = (VkUpdateSamplers*)malloc(sizeof(VkUpdateSamplers));
+    VkDescriptorInfo descriptor_info;
+    memset(&descriptor_info, 0, sizeof(descriptor_info));
+    descriptor_info.sampler = sampler;
+
+    VkWriteDescriptorSet descriptor_write;
+    memset(&descriptor_write, 0, sizeof(descriptor_write));
+    descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+    descriptor_write.destSet = descriptorSet;
+    descriptor_write.count = 1;
     // This is a mismatched type for the layout which expects BUFFER
-    pSamplerUpdate->sType      = VK_STRUCTURE_TYPE_UPDATE_SAMPLERS;
-    pSamplerUpdate->pNext      = NULL;
-    pSamplerUpdate->binding    = 0;
-    pSamplerUpdate->arrayIndex = 0;
-    pSamplerUpdate->count      = 1;
-    pSamplerUpdate->pSamplers  = &sampler;
-    const void** ppUpdate = (const void**)&pSamplerUpdate;
-    vkUpdateDescriptors(m_device->device(), descriptorSet, 1, ppUpdate);
+    descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
+    descriptor_write.pDescriptors = &descriptor_info;
+
+    vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
+
     msgType = m_errorMonitor->GetState(&msgString);
+    std::cout << msgString << "\n";
     ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive error after updating BUFFER Descriptor w/ incorrect type of SAMPLER.";
-    if (!strstr(msgString.c_str(),"Descriptor update type of VK_STRUCTURE_TYPE_UPDATE_SAMPLERS does not match ")) {
-        FAIL() << "Error received was not 'Descriptor update type of VK_STRUCTURE_TYPE_UPDATE_SAMPLERS does not match overlapping binding type!'";
+    if (!strstr(msgString.c_str(),"Descriptor update type of VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET does not match ")) {
+        FAIL() << "Error received was not 'Descriptor update type of VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET does not match overlapping binding type!'";
     }
 }
 
@@ -1318,20 +1324,27 @@
     VkSampler sampler;
     err = vkCreateSampler(m_device->device(), &sampler_ci, &sampler);
     ASSERT_VK_SUCCESS(err);
+
+    VkDescriptorInfo descriptor_info;
+    memset(&descriptor_info, 0, sizeof(descriptor_info));
+    descriptor_info.sampler = sampler;
+
+    VkWriteDescriptorSet descriptor_write;
+    memset(&descriptor_write, 0, sizeof(descriptor_write));
+    descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+    descriptor_write.destSet = descriptorSet;
+    descriptor_write.destArrayElement = 1; /* This index out of bounds for the update */
+    descriptor_write.count = 1;
     // This is the wrong type, but out of bounds will be flagged first
-    VkUpdateSamplers *pSamplerUpdate = (VkUpdateSamplers*)malloc(sizeof(VkUpdateSamplers));
-    pSamplerUpdate->sType      = VK_STRUCTURE_TYPE_UPDATE_SAMPLERS;
-    pSamplerUpdate->pNext      = NULL;
-    pSamplerUpdate->binding    = 0;
-    pSamplerUpdate->arrayIndex = 1; /* This index out of bounds for the update */
-    pSamplerUpdate->count      = 1;
-    pSamplerUpdate->pSamplers  = &sampler;
-    const void** ppUpdate = (const void**)&pSamplerUpdate;
-    vkUpdateDescriptors(m_device->device(), descriptorSet, 1, ppUpdate);
+    descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
+    descriptor_write.pDescriptors = &descriptor_info;
+
+    vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
+
     msgType = m_errorMonitor->GetState(&msgString);
     ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive error after updating Descriptor w/ index out of bounds.";
-    if (!strstr(msgString.c_str(),"Descriptor update type of VK_STRUCTURE_TYPE_UPDATE_SAMPLERS is out of bounds for matching binding")) {
-        FAIL() << "Error received was not 'Descriptor update type of VK_STRUCTURE_TYPE_UPDATE_SAMPLERS is out of bounds for matching binding...'";
+    if (!strstr(msgString.c_str(),"Descriptor update type of VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET is out of bounds for matching binding")) {
+        FAIL() << "Error received was not 'Descriptor update type of VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET is out of bounds for matching binding...'";
     }
 }
 
@@ -1399,16 +1412,23 @@
     VkSampler sampler;
     err = vkCreateSampler(m_device->device(), &sampler_ci, &sampler);
     ASSERT_VK_SUCCESS(err);
+
+    VkDescriptorInfo descriptor_info;
+    memset(&descriptor_info, 0, sizeof(descriptor_info));
+    descriptor_info.sampler = sampler;
+
+    VkWriteDescriptorSet descriptor_write;
+    memset(&descriptor_write, 0, sizeof(descriptor_write));
+    descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+    descriptor_write.destSet = descriptorSet;
+    descriptor_write.destBinding = 2;
+    descriptor_write.count = 1;
     // This is the wrong type, but out of bounds will be flagged first
-    VkUpdateSamplers *pSamplerUpdate = (VkUpdateSamplers*)malloc(sizeof(VkUpdateSamplers));
-    pSamplerUpdate->sType      = VK_STRUCTURE_TYPE_UPDATE_SAMPLERS;
-    pSamplerUpdate->pNext      = NULL;
-    pSamplerUpdate->binding    = 2; /* This binding too big for the update */
-    pSamplerUpdate->arrayIndex = 0;
-    pSamplerUpdate->count      = 1;
-    pSamplerUpdate->pSamplers  = &sampler;
-    const void** ppUpdate = (const void**)&pSamplerUpdate;
-    vkUpdateDescriptors(m_device->device(), descriptorSet, 1, ppUpdate);
+    descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
+    descriptor_write.pDescriptors = &descriptor_info;
+
+    vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
+
     msgType = m_errorMonitor->GetState(&msgString);
     ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive error after updating Descriptor w/ count too large for layout.";
     if (!strstr(msgString.c_str()," does not have binding to match update binding ")) {
@@ -1480,16 +1500,23 @@
     VkSampler sampler;
     err = vkCreateSampler(m_device->device(), &sampler_ci, &sampler);
     ASSERT_VK_SUCCESS(err);
+
+
+    VkDescriptorInfo descriptor_info;
+    memset(&descriptor_info, 0, sizeof(descriptor_info));
+    descriptor_info.sampler = sampler;
+
+    VkWriteDescriptorSet descriptor_write;
+    memset(&descriptor_write, 0, sizeof(descriptor_write));
+    descriptor_write.sType = (VkStructureType)0x99999999; /* Intentionally broken struct type */
+    descriptor_write.destSet = descriptorSet;
+    descriptor_write.count = 1;
     // This is the wrong type, but out of bounds will be flagged first
-    VkUpdateSamplers *pSamplerUpdate = (VkUpdateSamplers*)malloc(sizeof(VkUpdateSamplers));
-    pSamplerUpdate->sType      = (VkStructureType)0x99999999; /* Intentionally broken struct type */
-    pSamplerUpdate->pNext      = NULL;
-    pSamplerUpdate->binding    = 0;
-    pSamplerUpdate->arrayIndex = 0;
-    pSamplerUpdate->count      = 1;
-    pSamplerUpdate->pSamplers  = &sampler;
-    const void** ppUpdate = (const void**)&pSamplerUpdate;
-    vkUpdateDescriptors(m_device->device(), descriptorSet, 1, ppUpdate);
+    descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
+    descriptor_write.pDescriptors = &descriptor_info;
+
+    vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
+
     msgType = m_errorMonitor->GetState(&msgString);
     ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive error after updating Descriptor w/ invalid struct type.";
     if (!strstr(msgString.c_str(),"Unexpected UPDATE struct of type ")) {
diff --git a/tests/render_tests.cpp b/tests/render_tests.cpp
index 3e6ad95..b7472e9 100644
--- a/tests/render_tests.cpp
+++ b/tests/render_tests.cpp
@@ -277,7 +277,7 @@
 protected:
     VkImage m_texture;
     VkImageView m_textureView;
-    VkImageViewAttachInfo m_textureViewInfo;
+    VkDescriptorInfo m_descriptorInfo;
     VkDeviceMemory m_textureMem;
 
     VkSampler m_sampler;
@@ -293,8 +293,7 @@
         this->app_info.engineVersion = 1;
         this->app_info.apiVersion = VK_API_VERSION;
 
-        memset(&m_textureViewInfo, 0, sizeof(m_textureViewInfo));
-        m_textureViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ATTACH_INFO;
+        memset(&m_descriptorInfo, 0, sizeof(m_descriptorInfo));
 
         InitFramework();
     }
diff --git a/tests/vkrenderframework.cpp b/tests/vkrenderframework.cpp
index 4dd04c6..5a1da2b 100644
--- a/tests/vkrenderframework.cpp
+++ b/tests/vkrenderframework.cpp
@@ -308,8 +308,8 @@
     tc.count = 1;
     m_type_counts.push_back(tc);
 
-    m_updateBuffers.push_back(vk_testing::DescriptorSet::update(type,
-                m_nextSlot, 0, 1, &constantBuffer.m_bufferViewInfo));
+    m_writes.push_back(vk_testing::Device::write_descriptor_set(vk_testing::DescriptorSet(),
+                m_nextSlot, 0, type, 1, &constantBuffer.m_descriptorInfo));
 
     return m_nextSlot++;
 }
@@ -321,13 +321,12 @@
     tc.count = 1;
     m_type_counts.push_back(tc);
 
-    VkSamplerImageViewInfo tmp = {};
+    VkDescriptorInfo tmp = texture->m_descriptorInfo;
     tmp.sampler = sampler->obj();
-    tmp.pImageView = &texture->m_textureViewInfo;
-    m_samplerTextureInfo.push_back(tmp);
+    m_imageSamplerDescriptors.push_back(tmp);
 
-    m_updateSamplerTextures.push_back(vk_testing::DescriptorSet::update(m_nextSlot, 0, 1,
-                (const VkSamplerImageViewInfo *) NULL));
+    m_writes.push_back(vk_testing::Device::write_descriptor_set(vk_testing::DescriptorSet(),
+                m_nextSlot, 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, NULL));
 
     return m_nextSlot++;
 }
@@ -383,26 +382,24 @@
     m_set = alloc_sets(*m_device, VK_DESCRIPTOR_SET_USAGE_STATIC, m_layout);
 
     // build the update array
-    vector<const void *> update_array;
-
-    for (int i = 0; i < m_updateBuffers.size(); i++) {
-        update_array.push_back(&m_updateBuffers[i]);
-    }
-    for (int i = 0; i < m_updateSamplerTextures.size(); i++) {
-        m_updateSamplerTextures[i].pSamplerImageViews = &m_samplerTextureInfo[i];
-        update_array.push_back(&m_updateSamplerTextures[i]);
+    size_t imageSamplerCount = 0;
+    for (std::vector<VkWriteDescriptorSet>::iterator it = m_writes.begin();
+         it != m_writes.end(); it++) {
+        it->destSet = m_set->obj();
+        if (it->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+            it->pDescriptors = &m_imageSamplerDescriptors[imageSamplerCount++];
     }
 
     // do the updates
     clear_sets(*m_set);
-    m_set->update(update_array);
+    m_device->update_descriptor_sets(m_writes);
 }
 
 VkImageObj::VkImageObj(VkDeviceObj *dev)
 {
     m_device = dev;
-    m_imageInfo.view = VK_NULL_HANDLE;
-    m_imageInfo.layout = VK_IMAGE_LAYOUT_GENERAL;
+    m_descriptorInfo.imageView = VK_NULL_HANDLE;
+    m_descriptorInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
 }
 
 void VkImageObj::ImageMemoryBarrier(
@@ -461,7 +458,7 @@
             VK_MEMORY_INPUT_DEPTH_STENCIL_ATTACHMENT_BIT |
             VK_MEMORY_INPUT_TRANSFER_BIT;
 
-    if (image_layout == m_imageInfo.layout) {
+    if (image_layout == m_descriptorInfo.imageLayout) {
         return;
     }
 
@@ -489,7 +486,7 @@
     }
 
     ImageMemoryBarrier(cmd_buf, aspect, output_mask, input_mask, image_layout);
-    m_imageInfo.layout = image_layout;
+    m_descriptorInfo.imageLayout = image_layout;
 }
 
 void VkImageObj::SetLayout(VkImageAspect aspect,
@@ -660,9 +657,7 @@
     if (colors == NULL)
         colors = tex_colors;
 
-    memset(&m_textureViewInfo,0,sizeof(m_textureViewInfo));
-
-    m_textureViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ATTACH_INFO;
+    memset(&m_descriptorInfo,0,sizeof(m_descriptorInfo));
 
     VkImageViewCreateInfo view = {};
     view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@@ -687,7 +682,7 @@
     /* create image view */
     view.image = obj();
     m_textureView.init(*m_device, view);
-    m_textureViewInfo.view = m_textureView.obj();
+    m_descriptorInfo.imageView = m_textureView.obj();
 
     data = stagingImage.map();
 
@@ -731,7 +726,7 @@
     m_device = device;
     m_commandBuffer = 0;
 
-    memset(&m_bufferViewInfo,0,sizeof(m_bufferViewInfo));
+    memset(&m_descriptorInfo,0,sizeof(m_descriptorInfo));
 }
 
 VkConstantBufferObj::~VkConstantBufferObj()
@@ -747,7 +742,7 @@
     m_device = device;
     m_commandBuffer = 0;
 
-    memset(&m_bufferViewInfo,0,sizeof(m_bufferViewInfo));
+    memset(&m_descriptorInfo,0,sizeof(m_descriptorInfo));
     m_numVertices = constantCount;
     m_stride = constantSize;
 
@@ -768,8 +763,7 @@
     view_info.range  = allocationSize;
     m_bufferView.init(*m_device, view_info);
 
-    this->m_bufferViewInfo.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_ATTACH_INFO;
-    this->m_bufferViewInfo.view = m_bufferView.obj();
+    this->m_descriptorInfo.bufferView = m_bufferView.obj();
 }
 
 void VkConstantBufferObj::Bind(VkCmdBuffer cmdBuffer, VkDeviceSize offset, uint32_t binding)
@@ -888,8 +882,7 @@
     view_info.range  = allocationSize;
     m_bufferView.init(*m_device, view_info);
 
-    this->m_bufferViewInfo.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_ATTACH_INFO;
-    this->m_bufferViewInfo.view = m_bufferView.obj();
+    this->m_descriptorInfo.bufferView = m_bufferView.obj();
 }
 
 void VkIndexBufferObj::Bind(VkCmdBuffer cmdBuffer, VkDeviceSize offset)
diff --git a/tests/vkrenderframework.h b/tests/vkrenderframework.h
index 587dba7..a265bc7 100644
--- a/tests/vkrenderframework.h
+++ b/tests/vkrenderframework.h
@@ -212,7 +212,7 @@
 
     void Bind(VkCmdBuffer cmdBuffer, VkDeviceSize offset, uint32_t binding);
 
-    VkBufferViewAttachInfo     m_bufferViewInfo;
+    VkDescriptorInfo                    m_descriptorInfo;
 
 protected:
     VkDeviceObj                        *m_device;
@@ -251,7 +251,7 @@
 
     void layout( VkImageLayout layout )
     {
-        m_imageInfo.layout = layout;
+        m_descriptorInfo.imageLayout = layout;
     }
 
     VkDeviceMemory memory() const
@@ -296,7 +296,7 @@
 
     VkImageLayout layout() const
     {
-        return ( VkImageLayout )m_imageInfo.layout;
+        return m_descriptorInfo.imageLayout;
     }
     uint32_t width() const
     {
@@ -318,15 +318,15 @@
     VkDeviceObj                        *m_device;
 
     vk_testing::ColorAttachmentView     m_targetView;
-    VkImageViewAttachInfo               m_imageInfo;
+    VkDescriptorInfo                    m_descriptorInfo;
 };
 
 class VkTextureObj : public VkImageObj
 {
 public:
     VkTextureObj(VkDeviceObj *device, uint32_t *colors = NULL);
-    VkImageViewAttachInfo m_textureViewInfo;
 
+    VkDescriptorInfo                    m_descriptorInfo;
 
 protected:
     VkDeviceObj                        *m_device;
@@ -365,10 +365,8 @@
     vector<VkDescriptorTypeCount>       m_type_counts;
     int                                 m_nextSlot;
 
-    vector<VkUpdateBuffers>             m_updateBuffers;
-
-    vector<VkSamplerImageViewInfo>      m_samplerTextureInfo;
-    vector<VkUpdateSamplerTextures>     m_updateSamplerTextures;
+    vector<VkDescriptorInfo>            m_imageSamplerDescriptors;
+    vector<VkWriteDescriptorSet>        m_writes;
 
     vk_testing::DescriptorSetLayout     m_layout;
     vk_testing::PipelineLayout          m_pipeline_layout;
diff --git a/tests/vktestbinding.cpp b/tests/vktestbinding.cpp
index b0d83ca..8579b7e 100644
--- a/tests/vktestbinding.cpp
+++ b/tests/vktestbinding.cpp
@@ -488,6 +488,11 @@
     return err;
 }
 
+VkResult Device::update_descriptor_sets(const std::vector<VkWriteDescriptorSet> &writes, const std::vector<VkCopyDescriptorSet> &copies)
+{
+    return vkUpdateDescriptorSets(obj(), writes.size(), &writes[0], copies.size(), &copies[0]);
+}
+
 void Queue::submit(const std::vector<const CmdBuffer *> &cmds, Fence &fence)
 {
     const std::vector<VkCmdBuffer> cmd_objs = make_objects<VkCmdBuffer>(cmds);
@@ -888,11 +893,6 @@
     vkClearDescriptorSets(dev_->obj(), obj(), set_objs.size(), &set_objs[0]);
 }
 
-void DescriptorSet::update(const std::vector<const void *> &update_array)
-{
-    vkUpdateDescriptors(dev_->obj(), obj(), update_array.size(), const_cast<const void **>(&update_array[0]));
-}
-
 void DynamicVpStateObject::init(const Device &dev, const VkDynamicVpStateCreateInfo &info)
 {
     DERIVED_OBJECT_TYPE_INIT(vkCreateDynamicViewportState, dev, VK_OBJECT_TYPE_DYNAMIC_VP_STATE, &info);
diff --git a/tests/vktestbinding.h b/tests/vktestbinding.h
index 93b2722..89aee53 100644
--- a/tests/vktestbinding.h
+++ b/tests/vktestbinding.h
@@ -235,6 +235,19 @@
     VkResult wait(const std::vector<const Fence *> &fences, bool wait_all, uint64_t timeout);
     VkResult wait(const Fence &fence) { return wait(std::vector<const Fence *>(1, &fence), true, (uint64_t) -1); }
 
+    // vkUpdateDescriptorSets()
+    VkResult update_descriptor_sets(const std::vector<VkWriteDescriptorSet> &writes, const std::vector<VkCopyDescriptorSet> &copies);
+    VkResult update_descriptor_sets(const std::vector<VkWriteDescriptorSet> &writes) { return update_descriptor_sets(writes, std::vector<VkCopyDescriptorSet>()); }
+
+    static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
+                                                     VkDescriptorType type, uint32_t count, const VkDescriptorInfo *descriptors);
+    static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
+                                                     VkDescriptorType type, const std::vector<VkDescriptorInfo> &descriptors);
+
+    static VkCopyDescriptorSet copy_descriptor_set(const DescriptorSet &src_set, uint32_t src_binding, uint32_t src_array_element,
+                                                   const DescriptorSet &dst_set, uint32_t dst_binding, uint32_t dst_array_element,
+                                                   uint32_t count);
+
 private:
     enum QueueIndex {
         GRAPHICS,
@@ -548,27 +561,8 @@
 
 class DescriptorSet : public DerivedObject<VkDescriptorSet, Object, VK_OBJECT_TYPE_DESCRIPTOR_SET> {
 public:
+    explicit DescriptorSet() : DerivedObject() {}
     explicit DescriptorSet(const Device &dev, VkDescriptorSet set) : DerivedObject(dev, set) {}
-
-    // vkUpdateDescriptors()
-    void update(const std::vector<const void *> &update_array);
-
-    static VkUpdateSamplers update(uint32_t binding, uint32_t index, uint32_t count, const VkSampler *samplers);
-    static VkUpdateSamplers update(uint32_t binding, uint32_t index, const std::vector<VkSampler> &samplers);
-
-    static VkUpdateSamplerTextures update(uint32_t binding, uint32_t index, uint32_t count, const VkSamplerImageViewInfo *textures);
-    static VkUpdateSamplerTextures update(uint32_t binding, uint32_t index, const std::vector<VkSamplerImageViewInfo> &textures);
-
-    static VkUpdateImages update(VkDescriptorType type, uint32_t binding, uint32_t index, uint32_t count, const VkImageViewAttachInfo *views);
-    static VkUpdateImages update(VkDescriptorType type, uint32_t binding, uint32_t index, const std::vector<VkImageViewAttachInfo> &views);
-
-    static VkUpdateBuffers update(VkDescriptorType type, uint32_t binding, uint32_t index, uint32_t count, const VkBufferViewAttachInfo *views);
-    static VkUpdateBuffers update(VkDescriptorType type, uint32_t binding, uint32_t index, const std::vector<VkBufferViewAttachInfo> &views);
-
-    static VkUpdateAsCopy update(VkDescriptorType type, uint32_t binding, uint32_t index, uint32_t count, const DescriptorSet &set);
-
-    static VkBufferViewAttachInfo attach_info(const BufferView &view);
-    static VkImageViewAttachInfo attach_info(const ImageView &view, VkImageLayout layout);
 };
 
 class DynamicVpStateObject : public DerivedObject<VkDynamicVpState, DynamicStateObject, VK_OBJECT_TYPE_DYNAMIC_VP_STATE> {
@@ -792,103 +786,41 @@
     return info;
 }
 
-inline VkBufferViewAttachInfo DescriptorSet::attach_info(const BufferView &view)
+inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
+                                                         VkDescriptorType type, uint32_t count, const VkDescriptorInfo *descriptors)
 {
-    VkBufferViewAttachInfo info = {};
-    info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_ATTACH_INFO;
-    info.view = view.obj();
-    return info;
+    VkWriteDescriptorSet write = {};
+    write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+    write.destSet = set.obj();
+    write.destBinding = binding;
+    write.destArrayElement = array_element;
+    write.count = count;
+    write.descriptorType = type;
+    write.pDescriptors = descriptors;
+    return write;
 }
 
-inline VkImageViewAttachInfo DescriptorSet::attach_info(const ImageView &view, VkImageLayout layout)
+inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
+                                                         VkDescriptorType type, const std::vector<VkDescriptorInfo> &descriptors)
 {
-    VkImageViewAttachInfo info = {};
-    info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ATTACH_INFO;
-    info.view = view.obj();
-    info.layout = layout;
-    return info;
+    return write_descriptor_set(set, binding, array_element, type, descriptors.size(), &descriptors[0]);
 }
 
-inline VkUpdateSamplers DescriptorSet::update(uint32_t binding, uint32_t index, uint32_t count, const VkSampler *samplers)
+inline VkCopyDescriptorSet Device::copy_descriptor_set(const DescriptorSet &src_set, uint32_t src_binding, uint32_t src_array_element,
+                                                       const DescriptorSet &dst_set, uint32_t dst_binding, uint32_t dst_array_element,
+                                                       uint32_t count)
 {
-    VkUpdateSamplers info = {};
-    info.sType = VK_STRUCTURE_TYPE_UPDATE_SAMPLERS;
-    info.binding = binding;
-    info.arrayIndex = index;
-    info.count = count;
-    info.pSamplers = samplers;
-    return info;
-}
+    VkCopyDescriptorSet copy = {};
+    copy.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET;
+    copy.srcSet = src_set.obj();
+    copy.srcBinding = src_binding;
+    copy.srcArrayElement = src_array_element;
+    copy.destSet = dst_set.obj();
+    copy.destBinding = dst_binding;
+    copy.destArrayElement = dst_array_element;
+    copy.count = count;
 
-inline VkUpdateSamplers DescriptorSet::update(uint32_t binding, uint32_t index, const std::vector<VkSampler> &samplers)
-{
-    return update(binding, index, samplers.size(), &samplers[0]);
-}
-
-inline VkUpdateSamplerTextures DescriptorSet::update(uint32_t binding, uint32_t index, uint32_t count, const VkSamplerImageViewInfo *textures)
-{
-    VkUpdateSamplerTextures info = {};
-    info.sType = VK_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES;
-    info.binding = binding;
-    info.arrayIndex = index;
-    info.count = count;
-    info.pSamplerImageViews = textures;
-    return info;
-}
-
-inline VkUpdateSamplerTextures DescriptorSet::update(uint32_t binding, uint32_t index, const std::vector<VkSamplerImageViewInfo> &textures)
-{
-    return update(binding, index, textures.size(), &textures[0]);
-}
-
-inline VkUpdateImages DescriptorSet::update(VkDescriptorType type, uint32_t binding, uint32_t index, uint32_t count,
-                                               const VkImageViewAttachInfo *views)
-{
-    VkUpdateImages info = {};
-    info.sType = VK_STRUCTURE_TYPE_UPDATE_IMAGES;
-    info.descriptorType = type;
-    info.binding = binding;
-    info.arrayIndex = index;
-    info.count = count;
-    info.pImageViews = views;
-    return info;
-}
-
-inline VkUpdateImages DescriptorSet::update(VkDescriptorType type, uint32_t binding, uint32_t index,
-                                               const std::vector<VkImageViewAttachInfo> &views)
-{
-    return update(type, binding, index, views.size(), &views[0]);
-}
-
-inline VkUpdateBuffers DescriptorSet::update(VkDescriptorType type, uint32_t binding, uint32_t index, uint32_t count,
-                                                const VkBufferViewAttachInfo *views)
-{
-    VkUpdateBuffers info = {};
-    info.sType = VK_STRUCTURE_TYPE_UPDATE_BUFFERS;
-    info.descriptorType = type;
-    info.binding = binding;
-    info.arrayIndex = index;
-    info.count = count;
-    info.pBufferViews = views;
-    return info;
-}
-
-inline VkUpdateBuffers DescriptorSet::update(VkDescriptorType type, uint32_t binding, uint32_t index,
-                                                const std::vector<VkBufferViewAttachInfo> &views)
-{
-    return update(type, binding, index, views.size(), &views[0]);
-}
-
-inline VkUpdateAsCopy DescriptorSet::update(VkDescriptorType type, uint32_t binding, uint32_t index, uint32_t count, const DescriptorSet &set)
-{
-    VkUpdateAsCopy info = {};
-    info.sType = VK_STRUCTURE_TYPE_UPDATE_AS_COPY;
-    info.descriptorType = type;
-    info.binding = binding;
-    info.arrayElement = index;
-    info.count = count;
-    info.descriptorSet = set.obj();
-    return info;
+    return copy;
 }
 
 inline VkCmdBufferCreateInfo CmdBuffer::create_info(uint32_t queueNodeIndex)
diff --git a/vulkan.py b/vulkan.py
index c173fc1..f18ab68 100755
--- a/vulkan.py
+++ b/vulkan.py
@@ -583,11 +583,12 @@
              Param("uint32_t", "count"),
              Param("const VkDescriptorSet*", "pDescriptorSets")]),
 
-        Proto("void", "UpdateDescriptors",
+        Proto("VkResult", "UpdateDescriptorSets",
             [Param("VkDevice", "device"),
-             Param("VkDescriptorSet", "descriptorSet"),
-             Param("uint32_t", "updateCount"),
-             Param("const void**", "ppUpdateArray")]),
+             Param("uint32_t", "writeCount"),
+             Param("const VkWriteDescriptorSet*", "pDescriptorWrites"),
+             Param("uint32_t", "copyCount"),
+             Param("const VkCopyDescriptorSet*", "pDescriptorCopies")]),
 
         Proto("VkResult", "CreateDynamicViewportState",
             [Param("VkDevice", "device"),