layers: Add push descriptor validation

Add validation of CmdPushDescriptorSet(WithTemplate) descriptor state
updates, removing the code disabling later use of the recorded data.

Change-Id: If9c4345e67c974f36e7a5356a517f411e470c2c5
diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp
index f220520..7c0ab0d 100644
--- a/layers/descriptor_sets.cpp
+++ b/layers/descriptor_sets.cpp
@@ -843,7 +843,7 @@
                                           caller, kVUIDUndefined, "VUID-VkDescriptorImageInfo-imageLayout-00344", &hit_error);
                         if (hit_error) {
                             *error =
-                                "Image layout specified at vkUpdateDescriptorSets() or vkUpdateDescriptorSetWithTemplate() time "
+                                "Image layout specified at vkUpdateDescriptorSet* or vkCmdPushDescriptorSet* time "
                                 "doesn't match actual image layout at time descriptor is used. See previous error callback for "
                                 "specific details.";
                             return false;
@@ -935,6 +935,15 @@
 void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers() {
     core_validation::InvalidateCommandBuffers(device_data_, cb_bindings, {HandleToUint64(set_), kVulkanObjectTypeDescriptorSet});
 }
+
+// Loop through the write updates to do for a push descriptor set, ignoring dstSet
+void cvdescriptorset::DescriptorSet::PerformPushDescriptorsUpdate(uint32_t write_count, const VkWriteDescriptorSet *p_wds) {
+    assert(IsPushDescriptor());
+    for (uint32_t i = 0; i < write_count; i++) {
+        PerformWriteUpdate(&p_wds[i]);
+    }
+}
+
 // Perform write update in given update struct
 void cvdescriptorset::DescriptorSet::PerformWriteUpdate(const VkWriteDescriptorSet *update) {
     // Perform update on a per-binding basis as consecutive updates roll over to next binding
@@ -1706,11 +1715,15 @@
 }
 
 cvdescriptorset::DecodedTemplateUpdate::DecodedTemplateUpdate(layer_data *device_data, VkDescriptorSet descriptorSet,
-                                                              const TEMPLATE_STATE *template_state, const void *pData) {
+                                                              const TEMPLATE_STATE *template_state, const void *pData,
+                                                              VkDescriptorSetLayout push_layout) {
     auto const &create_info = template_state->create_info;
     inline_infos.resize(create_info.descriptorUpdateEntryCount);  // Make sure we have one if we need it
     desc_writes.reserve(create_info.descriptorUpdateEntryCount);  // emplaced, so reserved without initialization
-    auto layout_obj = GetDescriptorSetLayout(device_data, create_info.descriptorSetLayout);
+    VkDescriptorSetLayout effective_dsl = create_info.templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
+                                              ? create_info.descriptorSetLayout
+                                              : push_layout;
+    auto layout_obj = GetDescriptorSetLayout(device_data, effective_dsl);
 
     // Create a WriteDescriptorSet struct for each template update entry
     for (uint32_t i = 0; i < create_info.descriptorUpdateEntryCount; i++) {
@@ -1802,7 +1815,6 @@
     uint64_t layout_handle = HandleToUint64(p_layout_->GetDescriptorSetLayout());
     if (IsPushDescriptor()) {
         string_sprintf(&out, "Push Descriptors defined with VkDescriptorSetLayout 0x%" PRIxLEAST64, layout_handle);
-        out = "<push descriptors>";
     } else {
         string_sprintf(&out, "VkDescriptorSet 0x%" PRIxLEAST64 "allocated with VkDescriptorSetLayout 0x%" PRIxLEAST64,
                        HandleToUint64(set_), layout_handle);
@@ -1810,6 +1822,23 @@
     return out;
 };
 
+// Loop through the write updates to validate for a push descriptor set, ignoring dstSet
+bool cvdescriptorset::DescriptorSet::ValidatePushDescriptorsUpdate(const debug_report_data *report_data, uint32_t write_count,
+                                                                   const VkWriteDescriptorSet *p_wds, const char *func_name) {
+    assert(IsPushDescriptor());
+    bool skip = false;
+    for (uint32_t i = 0; i < write_count; i++) {
+        std::string error_code;
+        std::string error_str;
+        if (!ValidateWriteUpdate(report_data, &p_wds[i], func_name, &error_code, &error_str)) {
+            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
+                            HandleToUint64(p_layout_->GetDescriptorSetLayout()), error_code, "%s failed update validation: %s.",
+                            func_name, error_str.c_str());
+        }
+    }
+    return skip;
+}
+
 // Validate the state for a given write update but don't actually perform the update
 //  If an error would occur for this update, return false and fill in details in error_msg string
 bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data *report_data, const VkWriteDescriptorSet *update,
@@ -2334,7 +2363,7 @@
     for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
         auto layout = GetDescriptorSetLayout(dev_data, p_alloc_info->pSetLayouts[i]);
         if (layout) {  // nullptr layout indicates no valid layout handle for this device, validated/logged in object_tracker
-            if (layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR) {
+            if (layout->IsPushDescriptor()) {
                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
                                 HandleToUint64(p_alloc_info->pSetLayouts[i]), "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-00308",
                                 "Layout 0x%" PRIxLEAST64 " specified at pSetLayouts[%" PRIu32