layers: Add DescriptorSet interface for allocation

Create a top-level "Validate" and "Perform" interface for the
vkAllocateDescriptorSets() function in DescriptorSet class.

Refactor AllocateDescriptorSets() in core_validation to use the
new interface. All checks are now performed in a "Pre" function
and all state updates are recorded in a "Post" function.
diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp
index 0530f40..ede1b5a 100644
--- a/layers/descriptor_sets.cpp
+++ b/layers/descriptor_sets.cpp
@@ -1222,3 +1222,96 @@
     // All checks passed so update contents are good
     return true;
 }
+// Verify that the state at allocate time is correct, but don't actually allocate the sets yet
+bool cvdescriptorset::ValidateAllocateDescriptorSets(
+    const debug_report_data *report_data, const VkDescriptorSetAllocateInfo *p_alloc_info,
+    const std::unordered_map<VkDescriptorSetLayout, cvdescriptorset::DescriptorSetLayout *> &set_layout_map,
+    const std::unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE *> &pool_map) {
+    bool skip_call = false;
+    uint32_t requiredDescriptorsByType[VK_DESCRIPTOR_TYPE_RANGE_SIZE]{};
+
+    for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
+        auto layout_it = set_layout_map.find(p_alloc_info->pSetLayouts[i]);
+        if (layout_it == set_layout_map.end()) {
+            skip_call |=
+                log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
+                        reinterpret_cast<const uint64_t &>(p_alloc_info->pSetLayouts[i]), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
+                        "Unable to find set layout node for layout 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call",
+                        reinterpret_cast<const uint64_t &>(p_alloc_info->pSetLayouts[i]));
+        }
+        // Count total descriptors required per type
+        for (uint32_t j = 0; j < layout_it->second->GetBindingCount(); ++j) {
+            const auto &binding_layout = layout_it->second->GetDescriptorSetLayoutBindingPtrFromIndex(j);
+            uint32_t typeIndex = static_cast<uint32_t>(binding_layout->descriptorType);
+            requiredDescriptorsByType[typeIndex] += binding_layout->descriptorCount;
+        }
+    }
+    auto pool_it = pool_map.find(p_alloc_info->descriptorPool);
+    if (pool_it == pool_map.end()) {
+        skip_call |=
+            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
+                    reinterpret_cast<const uint64_t &>(p_alloc_info->descriptorPool), __LINE__, DRAWSTATE_INVALID_POOL, "DS",
+                    "Unable to find pool node for pool 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call",
+                    reinterpret_cast<const uint64_t &>(p_alloc_info->descriptorPool));
+    } else { // Make sure pool has all the available descriptors before calling down chain
+        // Track number of descriptorSets allowable in this pool
+        if (pool_it->second->availableSets < p_alloc_info->descriptorSetCount) {
+            skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
+                                 reinterpret_cast<uint64_t &>(pool_it->second->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY,
+                                 "DS", "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64
+                                       ". This pool only has %d descriptorSets remaining.",
+                                 p_alloc_info->descriptorSetCount, reinterpret_cast<uint64_t &>(pool_it->second->pool),
+                                 pool_it->second->availableSets);
+        }
+        // Determine whether descriptor counts are satisfiable
+        for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) {
+            if (requiredDescriptorsByType[i] > pool_it->second->availableDescriptorTypeCount[i]) {
+                skip_call |=
+                    log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
+                            reinterpret_cast<const uint64_t &>(pool_it->second->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY,
+                            "DS", "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64
+                                  ". This pool only has %d descriptors of this type remaining.",
+                            requiredDescriptorsByType[i], string_VkDescriptorType(VkDescriptorType(i)),
+                            reinterpret_cast<uint64_t &>(pool_it->second->pool), pool_it->second->availableDescriptorTypeCount[i]);
+            }
+        }
+    }
+    return skip_call;
+}
+// Decrement allocated sets from the pool and insert new sets into set_map
+void cvdescriptorset::PerformAllocateDescriptorSets(
+    const VkDescriptorSetAllocateInfo *p_alloc_info, const VkDescriptorSet *descriptor_sets,
+    std::unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE *> *pool_map,
+    std::unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> *set_map,
+    const std::unordered_map<VkDescriptorSetLayout, cvdescriptorset::DescriptorSetLayout *> &layout_map,
+    const std::unordered_map<VkBuffer, BUFFER_NODE> &buffer_map,
+    const std::unordered_map<VkDeviceMemory, DEVICE_MEM_INFO> &mem_obj_map,
+    const std::unordered_map<VkBufferView, VkBufferViewCreateInfo> &buffer_view_map,
+    const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> &sampler_map,
+    const std::unordered_map<VkImageView, VkImageViewCreateInfo> &image_view_map,
+    const std::unordered_map<VkImage, IMAGE_NODE> &image_map,
+    const std::unordered_map<VkImage, VkSwapchainKHR> &image_to_swapchain_map,
+    const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> &swapchain_map) {
+    auto pool_state = (*pool_map)[p_alloc_info->descriptorPool];
+    /* Account for sets allocated from pool */
+    pool_state->availableSets -= p_alloc_info->descriptorSetCount;
+    /* Create tracking object for each descriptor set; insert into
+     * global map and the pool's set.
+     */
+    for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
+        auto layout_state = layout_map.find(p_alloc_info->pSetLayouts[i])->second;
+        // Account for individual descriptors allocated from pool
+        for (uint32_t j = 0; j < layout_state->GetBindingCount(); ++j) {
+            const auto &binding_layout = layout_state->GetDescriptorSetLayoutBindingPtrFromIndex(j);
+            uint32_t type_index = static_cast<uint32_t>(binding_layout->descriptorType);
+            pool_state->availableDescriptorTypeCount[type_index] -= binding_layout->descriptorCount;
+        }
+        auto new_ds =
+            new cvdescriptorset::DescriptorSet(descriptor_sets[i], layout_state, &buffer_map, &mem_obj_map, &buffer_view_map,
+                                               &sampler_map, &image_view_map, &image_map, &image_to_swapchain_map, &swapchain_map);
+
+        pool_state->sets.insert(new_ds);
+        new_ds->in_use.store(0);
+        (*set_map)[descriptor_sets[i]] = new_ds;
+    }
+}