layers: Fix Android build
[platform/upstream/Vulkan-LoaderAndValidationLayers.git] / layers / descriptor_sets.cpp
1 /* Copyright (c) 2015-2016 The Khronos Group Inc.
2  * Copyright (c) 2015-2016 Valve Corporation
3  * Copyright (c) 2015-2016 LunarG, Inc.
4  * Copyright (C) 2015-2016 Google Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Author: Tobin Ehlis <tobine@google.com>
19  *         John Zulauf <jzulauf@lunarg.com>
20  */
21
22 // Allow use of STL min and max functions in Windows
23 #define NOMINMAX
24
25 #include "descriptor_sets.h"
26 #include "vk_enum_string_helper.h"
27 #include "vk_safe_struct.h"
28 #include "buffer_validation.h"
29 #include <sstream>
30 #include <algorithm>
31
32 struct BindingNumCmp {
33     bool operator()(const VkDescriptorSetLayoutBinding *a, const VkDescriptorSetLayoutBinding *b) const {
34         return a->binding < b->binding;
35     }
36 };
37
38 // Construct DescriptorSetLayout instance from given create info
39 // Proactively reserve and resize as possible, as the reallocation was visible in profiling
40 cvdescriptorset::DescriptorSetLayout::DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info,
41                                                           const VkDescriptorSetLayout layout)
42     : layout_(layout), flags_(p_create_info->flags), binding_count_(0), descriptor_count_(0), dynamic_descriptor_count_(0) {
43     binding_type_stats_ = {0, 0, 0};
44     std::set<const VkDescriptorSetLayoutBinding *, BindingNumCmp> sorted_bindings;
45     const uint32_t input_bindings_count = p_create_info->bindingCount;
46     // Sort the input bindings in binding number order, eliminating duplicates
47     for (uint32_t i = 0; i < input_bindings_count; i++) {
48         sorted_bindings.insert(p_create_info->pBindings + i);
49     }
50
51     // Store the create info in the sorted order from above
52     std::map<uint32_t, uint32_t> binding_to_dyn_count;
53     uint32_t index = 0;
54     binding_count_ = static_cast<uint32_t>(sorted_bindings.size());
55     bindings_.reserve(binding_count_);
56     binding_to_index_map_.reserve(binding_count_);
57     for (auto input_binding : sorted_bindings) {
58         // Add to binding and map, s.t. it is robust to invalid duplication of binding_num
59         const auto binding_num = input_binding->binding;
60         binding_to_index_map_[binding_num] = index++;
61         bindings_.emplace_back(input_binding);
62         auto &binding_info = bindings_.back();
63
64         descriptor_count_ += binding_info.descriptorCount;
65         if (binding_info.descriptorCount > 0) {
66             non_empty_bindings_.insert(binding_num);
67         }
68
69         if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
70             binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
71             binding_to_dyn_count[binding_num] = binding_info.descriptorCount;
72             dynamic_descriptor_count_ += binding_info.descriptorCount;
73             binding_type_stats_.dynamic_buffer_count++;
74         } else if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
75                    (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)) {
76             binding_type_stats_.non_dynamic_buffer_count++;
77         } else {
78             binding_type_stats_.image_sampler_count++;
79         }
80     }
81     assert(bindings_.size() == binding_count_);
82     uint32_t global_index = 0;
83     binding_to_global_index_range_map_.reserve(binding_count_);
84     // Vector order is finalized so create maps of bindings to descriptors and descriptors to indices
85     for (uint32_t i = 0; i < binding_count_; ++i) {
86         auto binding_num = bindings_[i].binding;
87         auto final_index = global_index + bindings_[i].descriptorCount;
88         binding_to_global_index_range_map_[binding_num] = IndexRange(global_index, final_index);
89         if (final_index != global_index) {
90             global_start_to_index_map_[global_index] = i;
91         }
92         global_index = final_index;
93     }
94
95     // Now create dyn offset array mapping for any dynamic descriptors
96     uint32_t dyn_array_idx = 0;
97     binding_to_dynamic_array_idx_map_.reserve(binding_to_dyn_count.size());
98     for (const auto &bc_pair : binding_to_dyn_count) {
99         binding_to_dynamic_array_idx_map_[bc_pair.first] = dyn_array_idx;
100         dyn_array_idx += bc_pair.second;
101     }
102 }
103
104 // Validate descriptor set layout create info
105 bool cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(debug_report_data *report_data,
106                                                               const VkDescriptorSetLayoutCreateInfo *create_info) {
107     bool skip = false;
108     std::unordered_set<uint32_t> bindings;
109     for (uint32_t i = 0; i < create_info->bindingCount; ++i) {
110         if (!bindings.insert(create_info->pBindings[i].binding).second) {
111             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
112                             VALIDATION_ERROR_0500022e, "DS", "duplicated binding number in VkDescriptorSetLayoutBinding. %s",
113                             validation_error_map[VALIDATION_ERROR_0500022e]);
114         }
115     }
116     return skip;
117 }
118
119 // Return valid index or "end" i.e. binding_count_;
120 // The asserts in "Get" are reduced to the set where no valid answer(like null or 0) could be given
121 // Common code for all binding lookups.
122 uint32_t cvdescriptorset::DescriptorSetLayout::GetIndexFromBinding(uint32_t binding) const {
123     const auto &bi_itr = binding_to_index_map_.find(binding);
124     if (bi_itr != binding_to_index_map_.cend()) return bi_itr->second;
125     return GetBindingCount();
126 }
127 VkDescriptorSetLayoutBinding const *cvdescriptorset::DescriptorSetLayout::GetDescriptorSetLayoutBindingPtrFromIndex(
128     const uint32_t index) const {
129     if (index >= bindings_.size()) return nullptr;
130     return bindings_[index].ptr();
131 }
132 // Return descriptorCount for given index, 0 if index is unavailable
133 uint32_t cvdescriptorset::DescriptorSetLayout::GetDescriptorCountFromIndex(const uint32_t index) const {
134     if (index >= bindings_.size()) return 0;
135     return bindings_[index].descriptorCount;
136 }
137 // For the given index, return descriptorType
138 VkDescriptorType cvdescriptorset::DescriptorSetLayout::GetTypeFromIndex(const uint32_t index) const {
139     assert(index < bindings_.size());
140     if (index < bindings_.size()) return bindings_[index].descriptorType;
141     return VK_DESCRIPTOR_TYPE_MAX_ENUM;
142 }
143 // For the given index, return stageFlags
144 VkShaderStageFlags cvdescriptorset::DescriptorSetLayout::GetStageFlagsFromIndex(const uint32_t index) const {
145     assert(index < bindings_.size());
146     if (index < bindings_.size()) return bindings_[index].stageFlags;
147     return VkShaderStageFlags(0);
148 }
149
150 // For the given global index, return index
151 uint32_t cvdescriptorset::DescriptorSetLayout::GetIndexFromGlobalIndex(const uint32_t global_index) const {
152     auto start_it = global_start_to_index_map_.upper_bound(global_index);
153     uint32_t index = binding_count_;
154     assert(start_it != global_start_to_index_map_.cbegin());
155     if (start_it != global_start_to_index_map_.cbegin()) {
156         --start_it;
157         index = start_it->second;
158 #ifndef NDEBUG
159         const auto &range = GetGlobalIndexRangeFromBinding(bindings_[index].binding);
160         assert(range.start <= global_index && global_index < range.end);
161 #endif
162     }
163     return index;
164 }
165
166 // For the given binding, return the global index range
167 // As start and end are often needed in pairs, get both with a single hash lookup.
168 const cvdescriptorset::IndexRange &cvdescriptorset::DescriptorSetLayout::GetGlobalIndexRangeFromBinding(
169     const uint32_t binding) const {
170     assert(binding_to_global_index_range_map_.count(binding));
171     // In error case max uint32_t so index is out of bounds to break ASAP
172     const static IndexRange kInvalidRange = {0xFFFFFFFF, 0xFFFFFFFF};
173     const auto &range_it = binding_to_global_index_range_map_.find(binding);
174     if (range_it != binding_to_global_index_range_map_.end()) {
175         return range_it->second;
176     }
177     return kInvalidRange;
178 }
179
180 // For given binding, return ptr to ImmutableSampler array
181 VkSampler const *cvdescriptorset::DescriptorSetLayout::GetImmutableSamplerPtrFromBinding(const uint32_t binding) const {
182     const auto &bi_itr = binding_to_index_map_.find(binding);
183     if (bi_itr != binding_to_index_map_.end()) {
184         return bindings_[bi_itr->second].pImmutableSamplers;
185     }
186     return nullptr;
187 }
188 // Move to next valid binding having a non-zero binding count
189 uint32_t cvdescriptorset::DescriptorSetLayout::GetNextValidBinding(const uint32_t binding) const {
190     auto it = non_empty_bindings_.upper_bound(binding);
191     assert(it != non_empty_bindings_.cend());
192     if (it != non_empty_bindings_.cend()) return *it;
193     return GetMaxBinding() + 1;
194 }
195 // For given index, return ptr to ImmutableSampler array
196 VkSampler const *cvdescriptorset::DescriptorSetLayout::GetImmutableSamplerPtrFromIndex(const uint32_t index) const {
197     if (index < bindings_.size()) {
198         return bindings_[index].pImmutableSamplers;
199     }
200     return nullptr;
201 }
202 // If our layout is compatible with rh_ds_layout, return true,
203 //  else return false and fill in error_msg will description of what causes incompatibility
204 bool cvdescriptorset::DescriptorSetLayout::IsCompatible(DescriptorSetLayout const *const rh_ds_layout,
205                                                         std::string *error_msg) const {
206     // Trivial case
207     if (layout_ == rh_ds_layout->GetDescriptorSetLayout()) return true;
208     if (descriptor_count_ != rh_ds_layout->descriptor_count_) {
209         std::stringstream error_str;
210         error_str << "DescriptorSetLayout " << layout_ << " has " << descriptor_count_ << " descriptors, but DescriptorSetLayout "
211                   << rh_ds_layout->GetDescriptorSetLayout() << ", which comes from pipelineLayout, has "
212                   << rh_ds_layout->descriptor_count_ << " descriptors.";
213         *error_msg = error_str.str();
214         return false;  // trivial fail case
215     }
216     // Descriptor counts match so need to go through bindings one-by-one
217     //  and verify that type and stageFlags match
218     for (auto binding : bindings_) {
219         // TODO : Do we also need to check immutable samplers?
220         // VkDescriptorSetLayoutBinding *rh_binding;
221         if (binding.descriptorCount != rh_ds_layout->GetDescriptorCountFromBinding(binding.binding)) {
222             std::stringstream error_str;
223             error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << layout_ << " has a descriptorCount of "
224                       << binding.descriptorCount << " but binding " << binding.binding << " for DescriptorSetLayout "
225                       << rh_ds_layout->GetDescriptorSetLayout() << ", which comes from pipelineLayout, has a descriptorCount of "
226                       << rh_ds_layout->GetDescriptorCountFromBinding(binding.binding);
227             *error_msg = error_str.str();
228             return false;
229         } else if (binding.descriptorType != rh_ds_layout->GetTypeFromBinding(binding.binding)) {
230             std::stringstream error_str;
231             error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << layout_ << " is type '"
232                       << string_VkDescriptorType(binding.descriptorType) << "' but binding " << binding.binding
233                       << " for DescriptorSetLayout " << rh_ds_layout->GetDescriptorSetLayout()
234                       << ", which comes from pipelineLayout, is type '"
235                       << string_VkDescriptorType(rh_ds_layout->GetTypeFromBinding(binding.binding)) << "'";
236             *error_msg = error_str.str();
237             return false;
238         } else if (binding.stageFlags != rh_ds_layout->GetStageFlagsFromBinding(binding.binding)) {
239             std::stringstream error_str;
240             error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << layout_ << " has stageFlags "
241                       << binding.stageFlags << " but binding " << binding.binding << " for DescriptorSetLayout "
242                       << rh_ds_layout->GetDescriptorSetLayout() << ", which comes from pipelineLayout, has stageFlags "
243                       << rh_ds_layout->GetStageFlagsFromBinding(binding.binding);
244             *error_msg = error_str.str();
245             return false;
246         }
247     }
248     return true;
249 }
250
251 bool cvdescriptorset::DescriptorSetLayout::IsNextBindingConsistent(const uint32_t binding) const {
252     if (!binding_to_index_map_.count(binding + 1)) return false;
253     auto const &bi_itr = binding_to_index_map_.find(binding);
254     if (bi_itr != binding_to_index_map_.end()) {
255         const auto &next_bi_itr = binding_to_index_map_.find(binding + 1);
256         if (next_bi_itr != binding_to_index_map_.end()) {
257             auto type = bindings_[bi_itr->second].descriptorType;
258             auto stage_flags = bindings_[bi_itr->second].stageFlags;
259             auto immut_samp = bindings_[bi_itr->second].pImmutableSamplers ? true : false;
260             if ((type != bindings_[next_bi_itr->second].descriptorType) ||
261                 (stage_flags != bindings_[next_bi_itr->second].stageFlags) ||
262                 (immut_samp != (bindings_[next_bi_itr->second].pImmutableSamplers ? true : false))) {
263                 return false;
264             }
265             return true;
266         }
267     }
268     return false;
269 }
270 // Starting at offset descriptor of given binding, parse over update_count
271 //  descriptor updates and verify that for any binding boundaries that are crossed, the next binding(s) are all consistent
272 //  Consistency means that their type, stage flags, and whether or not they use immutable samplers matches
273 //  If so, return true. If not, fill in error_msg and return false
274 bool cvdescriptorset::DescriptorSetLayout::VerifyUpdateConsistency(uint32_t current_binding, uint32_t offset, uint32_t update_count,
275                                                                    const char *type, const VkDescriptorSet set,
276                                                                    std::string *error_msg) const {
277     // Verify consecutive bindings match (if needed)
278     auto orig_binding = current_binding;
279     // Track count of descriptors in the current_bindings that are remaining to be updated
280     auto binding_remaining = GetDescriptorCountFromBinding(current_binding);
281     // First, it's legal to offset beyond your own binding so handle that case
282     //  Really this is just searching for the binding in which the update begins and adjusting offset accordingly
283     while (offset >= binding_remaining) {
284         // Advance to next binding, decrement offset by binding size
285         offset -= binding_remaining;
286         binding_remaining = GetDescriptorCountFromBinding(++current_binding);
287     }
288     binding_remaining -= offset;
289     while (update_count > binding_remaining) {  // While our updates overstep current binding
290         // Verify next consecutive binding matches type, stage flags & immutable sampler use
291         if (!IsNextBindingConsistent(current_binding++)) {
292             std::stringstream error_str;
293             error_str << "Attempting " << type << " descriptor set " << set << " binding #" << orig_binding << " with #"
294                       << update_count << " descriptors being updated but this update oversteps the bounds of this binding and the "
295                                          "next binding is not consistent with current binding so this update is invalid.";
296             *error_msg = error_str.str();
297             return false;
298         }
299         // For sake of this check consider the bindings updated and grab count for next binding
300         update_count -= binding_remaining;
301         binding_remaining = GetDescriptorCountFromBinding(current_binding);
302     }
303     return true;
304 }
305
306 cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t count)
307     : required_descriptors_by_type{}, layout_nodes(count, nullptr) {}
308
309 cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const VkDescriptorPool pool,
310                                               const std::shared_ptr<DescriptorSetLayout const> &layout, layer_data *dev_data)
311     : some_update_(false),
312       set_(set),
313       pool_state_(nullptr),
314       p_layout_(layout),
315       device_data_(dev_data),
316       limits_(GetPhysDevProperties(dev_data)->properties.limits) {
317     pool_state_ = GetDescriptorPoolState(dev_data, pool);
318     // Foreach binding, create default descriptors of given type
319     descriptors_.reserve(p_layout_->GetTotalDescriptorCount());
320     for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) {
321         auto type = p_layout_->GetTypeFromIndex(i);
322         switch (type) {
323             case VK_DESCRIPTOR_TYPE_SAMPLER: {
324                 auto immut_sampler = p_layout_->GetImmutableSamplerPtrFromIndex(i);
325                 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) {
326                     if (immut_sampler) {
327                         descriptors_.emplace_back(new SamplerDescriptor(immut_sampler + di));
328                         some_update_ = true;  // Immutable samplers are updated at creation
329                     } else
330                         descriptors_.emplace_back(new SamplerDescriptor(nullptr));
331                 }
332                 break;
333             }
334             case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
335                 auto immut = p_layout_->GetImmutableSamplerPtrFromIndex(i);
336                 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) {
337                     if (immut) {
338                         descriptors_.emplace_back(new ImageSamplerDescriptor(immut + di));
339                         some_update_ = true;  // Immutable samplers are updated at creation
340                     } else
341                         descriptors_.emplace_back(new ImageSamplerDescriptor(nullptr));
342                 }
343                 break;
344             }
345             // ImageDescriptors
346             case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
347             case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
348             case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
349                 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
350                     descriptors_.emplace_back(new ImageDescriptor(type));
351                 break;
352             case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
353             case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
354                 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
355                     descriptors_.emplace_back(new TexelDescriptor(type));
356                 break;
357             case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
358             case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
359             case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
360             case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
361                 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
362                     descriptors_.emplace_back(new BufferDescriptor(type));
363                 break;
364             default:
365                 assert(0);  // Bad descriptor type specified
366                 break;
367         }
368     }
369 }
370
371 cvdescriptorset::DescriptorSet::~DescriptorSet() { InvalidateBoundCmdBuffers(); }
372
373 static std::string string_descriptor_req_view_type(descriptor_req req) {
374     std::string result("");
375     for (unsigned i = 0; i <= VK_IMAGE_VIEW_TYPE_END_RANGE; i++) {
376         if (req & (1 << i)) {
377             if (result.size()) result += ", ";
378             result += string_VkImageViewType(VkImageViewType(i));
379         }
380     }
381
382     if (!result.size()) result = "(none)";
383
384     return result;
385 }
386
387 // Is this sets underlying layout compatible with passed in layout according to "Pipeline Layout Compatibility" in spec?
388 bool cvdescriptorset::DescriptorSet::IsCompatible(DescriptorSetLayout const *const layout, std::string *error) const {
389     return layout->IsCompatible(p_layout_.get(), error);
390 }
391
392 // Validate that the state of this set is appropriate for the given bindings and dynamic_offsets at Draw time
393 //  This includes validating that all descriptors in the given bindings are updated,
394 //  that any update buffers are valid, and that any dynamic offsets are within the bounds of their buffers.
395 // Return true if state is acceptable, or false and write an error message into error string
396 bool cvdescriptorset::DescriptorSet::ValidateDrawState(const std::map<uint32_t, descriptor_req> &bindings,
397                                                        const std::vector<uint32_t> &dynamic_offsets, GLOBAL_CB_NODE *cb_node,
398                                                        const char *caller, std::string *error) const {
399     for (auto binding_pair : bindings) {
400         auto binding = binding_pair.first;
401         if (!p_layout_->HasBinding(binding)) {
402             std::stringstream error_str;
403             error_str << "Attempting to validate DrawState for binding #" << binding
404                       << " which is an invalid binding for this descriptor set.";
405             *error = error_str.str();
406             return false;
407         }
408         IndexRange index_range = p_layout_->GetGlobalIndexRangeFromBinding(binding);
409         auto array_idx = 0;  // Track array idx if we're dealing with array descriptors
410         for (uint32_t i = index_range.start; i < index_range.end; ++i, ++array_idx) {
411             if (!descriptors_[i]->updated) {
412                 std::stringstream error_str;
413                 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
414                           << " is being used in draw but has not been updated.";
415                 *error = error_str.str();
416                 return false;
417             } else {
418                 auto descriptor_class = descriptors_[i]->GetClass();
419                 if (descriptor_class == GeneralBuffer) {
420                     // Verify that buffers are valid
421                     auto buffer = static_cast<BufferDescriptor *>(descriptors_[i].get())->GetBuffer();
422                     auto buffer_node = GetBufferState(device_data_, buffer);
423                     if (!buffer_node) {
424                         std::stringstream error_str;
425                         error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
426                                   << " references invalid buffer " << buffer << ".";
427                         *error = error_str.str();
428                         return false;
429                     } else if (!buffer_node->sparse) {
430                         for (auto mem_binding : buffer_node->GetBoundMemory()) {
431                             if (!GetMemObjInfo(device_data_, mem_binding)) {
432                                 std::stringstream error_str;
433                                 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
434                                           << " uses buffer " << buffer << " that references invalid memory " << mem_binding << ".";
435                                 *error = error_str.str();
436                                 return false;
437                             }
438                         }
439                     } else {
440                         // Enqueue sparse resource validation, as these can only be validated at submit time
441                         auto device_data_copy = device_data_;  // Cannot capture members by value, so make capturable copy.
442                         std::function<bool(void)> function = [device_data_copy, caller, buffer_node]() {
443                             return core_validation::ValidateBufferMemoryIsValid(device_data_copy, buffer_node, caller);
444                         };
445                         cb_node->queue_submit_functions.push_back(function);
446                     }
447                     if (descriptors_[i]->IsDynamic()) {
448                         // Validate that dynamic offsets are within the buffer
449                         auto buffer_size = buffer_node->createInfo.size;
450                         auto range = static_cast<BufferDescriptor *>(descriptors_[i].get())->GetRange();
451                         auto desc_offset = static_cast<BufferDescriptor *>(descriptors_[i].get())->GetOffset();
452                         auto dyn_offset = dynamic_offsets[GetDynamicOffsetIndexFromBinding(binding) + array_idx];
453                         if (VK_WHOLE_SIZE == range) {
454                             if ((dyn_offset + desc_offset) > buffer_size) {
455                                 std::stringstream error_str;
456                                 error_str << "Dynamic descriptor in binding #" << binding << " at global descriptor index " << i
457                                           << " uses buffer " << buffer << " with update range of VK_WHOLE_SIZE has dynamic offset "
458                                           << dyn_offset << " combined with offset " << desc_offset
459                                           << " that oversteps the buffer size of " << buffer_size << ".";
460                                 *error = error_str.str();
461                                 return false;
462                             }
463                         } else {
464                             if ((dyn_offset + desc_offset + range) > buffer_size) {
465                                 std::stringstream error_str;
466                                 error_str << "Dynamic descriptor in binding #" << binding << " at global descriptor index " << i
467                                           << " uses buffer " << buffer << " with dynamic offset " << dyn_offset
468                                           << " combined with offset " << desc_offset << " and range " << range
469                                           << " that oversteps the buffer size of " << buffer_size << ".";
470                                 *error = error_str.str();
471                                 return false;
472                             }
473                         }
474                     }
475                 } else if (descriptor_class == ImageSampler || descriptor_class == Image) {
476                     VkImageView image_view;
477                     VkImageLayout image_layout;
478                     if (descriptor_class == ImageSampler) {
479                         image_view = static_cast<ImageSamplerDescriptor *>(descriptors_[i].get())->GetImageView();
480                         image_layout = static_cast<ImageSamplerDescriptor *>(descriptors_[i].get())->GetImageLayout();
481                     } else {
482                         image_view = static_cast<ImageDescriptor *>(descriptors_[i].get())->GetImageView();
483                         image_layout = static_cast<ImageDescriptor *>(descriptors_[i].get())->GetImageLayout();
484                     }
485                     auto reqs = binding_pair.second;
486
487                     auto image_view_state = GetImageViewState(device_data_, image_view);
488                     if (nullptr == image_view_state) {
489                         // Image view must have been destroyed since initial update. Could potentially flag the descriptor
490                         //  as "invalid" (updated = false) at DestroyImageView() time and detect this error at bind time
491                         std::stringstream error_str;
492                         error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
493                                   << " is using imageView " << image_view << " that has been destroyed.";
494                         *error = error_str.str();
495                         return false;
496                     }
497                     auto image_view_ci = image_view_state->create_info;
498
499                     if ((reqs & DESCRIPTOR_REQ_ALL_VIEW_TYPE_BITS) && (~reqs & (1 << image_view_ci.viewType))) {
500                         // bad view type
501                         std::stringstream error_str;
502                         error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
503                                   << " requires an image view of type " << string_descriptor_req_view_type(reqs) << " but got "
504                                   << string_VkImageViewType(image_view_ci.viewType) << ".";
505                         *error = error_str.str();
506                         return false;
507                     }
508
509                     auto image_node = GetImageState(device_data_, image_view_ci.image);
510                     assert(image_node);
511                     // Verify Image Layout
512                     // Copy first mip level into sub_layers and loop over each mip level to verify layout
513                     VkImageSubresourceLayers sub_layers;
514                     sub_layers.aspectMask = image_view_ci.subresourceRange.aspectMask;
515                     sub_layers.baseArrayLayer = image_view_ci.subresourceRange.baseArrayLayer;
516                     sub_layers.layerCount = image_view_ci.subresourceRange.layerCount;
517                     bool hit_error = false;
518                     for (auto cur_level = image_view_ci.subresourceRange.baseMipLevel;
519                          cur_level < image_view_ci.subresourceRange.levelCount; ++cur_level) {
520                         sub_layers.mipLevel = cur_level;
521                         VerifyImageLayout(device_data_, cb_node, image_node, sub_layers, image_layout, VK_IMAGE_LAYOUT_UNDEFINED,
522                                           caller, VALIDATION_ERROR_046002b0, &hit_error);
523                         if (hit_error) {
524                             *error =
525                                 "Image layout specified at vkUpdateDescriptorSets() time doesn't match actual image layout at "
526                                 "time descriptor is used. See previous error callback for specific details.";
527                             return false;
528                         }
529                     }
530                     // Verify Sample counts
531                     if ((reqs & DESCRIPTOR_REQ_SINGLE_SAMPLE) && image_node->createInfo.samples != VK_SAMPLE_COUNT_1_BIT) {
532                         std::stringstream error_str;
533                         error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
534                                   << " requires bound image to have VK_SAMPLE_COUNT_1_BIT but got "
535                                   << string_VkSampleCountFlagBits(image_node->createInfo.samples) << ".";
536                         *error = error_str.str();
537                         return false;
538                     }
539                     if ((reqs & DESCRIPTOR_REQ_MULTI_SAMPLE) && image_node->createInfo.samples == VK_SAMPLE_COUNT_1_BIT) {
540                         std::stringstream error_str;
541                         error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
542                                   << " requires bound image to have multiple samples, but got VK_SAMPLE_COUNT_1_BIT.";
543                         *error = error_str.str();
544                         return false;
545                     }
546                 }
547             }
548         }
549     }
550     return true;
551 }
552
553 // For given bindings, place any update buffers or images into the passed-in unordered_sets
554 uint32_t cvdescriptorset::DescriptorSet::GetStorageUpdates(const std::map<uint32_t, descriptor_req> &bindings,
555                                                            std::unordered_set<VkBuffer> *buffer_set,
556                                                            std::unordered_set<VkImageView> *image_set) const {
557     auto num_updates = 0;
558     for (auto binding_pair : bindings) {
559         auto binding = binding_pair.first;
560         // If a binding doesn't exist, skip it
561         if (!p_layout_->HasBinding(binding)) {
562             continue;
563         }
564         uint32_t start_idx = p_layout_->GetGlobalIndexRangeFromBinding(binding).start;
565         if (descriptors_[start_idx]->IsStorage()) {
566             if (Image == descriptors_[start_idx]->descriptor_class) {
567                 for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) {
568                     if (descriptors_[start_idx + i]->updated) {
569                         image_set->insert(static_cast<ImageDescriptor *>(descriptors_[start_idx + i].get())->GetImageView());
570                         num_updates++;
571                     }
572                 }
573             } else if (TexelBuffer == descriptors_[start_idx]->descriptor_class) {
574                 for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) {
575                     if (descriptors_[start_idx + i]->updated) {
576                         auto bufferview = static_cast<TexelDescriptor *>(descriptors_[start_idx + i].get())->GetBufferView();
577                         auto bv_state = GetBufferViewState(device_data_, bufferview);
578                         if (bv_state) {
579                             buffer_set->insert(bv_state->create_info.buffer);
580                             num_updates++;
581                         }
582                     }
583                 }
584             } else if (GeneralBuffer == descriptors_[start_idx]->descriptor_class) {
585                 for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) {
586                     if (descriptors_[start_idx + i]->updated) {
587                         buffer_set->insert(static_cast<BufferDescriptor *>(descriptors_[start_idx + i].get())->GetBuffer());
588                         num_updates++;
589                     }
590                 }
591             }
592         }
593     }
594     return num_updates;
595 }
596 // Set is being deleted or updates so invalidate all bound cmd buffers
597 void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers() {
598     core_validation::invalidateCommandBuffers(device_data_, cb_bindings, {HandleToUint64(set_), kVulkanObjectTypeDescriptorSet});
599 }
600 // Perform write update in given update struct
601 void cvdescriptorset::DescriptorSet::PerformWriteUpdate(const VkWriteDescriptorSet *update) {
602     // Perform update on a per-binding basis as consecutive updates roll over to next binding
603     auto descriptors_remaining = update->descriptorCount;
604     auto binding_being_updated = update->dstBinding;
605     auto offset = update->dstArrayElement;
606     uint32_t update_index = 0;
607     while (descriptors_remaining) {
608         uint32_t update_count = std::min(descriptors_remaining, GetDescriptorCountFromBinding(binding_being_updated));
609         auto global_idx = p_layout_->GetGlobalIndexRangeFromBinding(binding_being_updated).start + offset;
610         // Loop over the updates for a single binding at a time
611         for (uint32_t di = 0; di < update_count; ++di, ++update_index) {
612             descriptors_[global_idx + di]->WriteUpdate(update, update_index);
613         }
614         // Roll over to next binding in case of consecutive update
615         descriptors_remaining -= update_count;
616         offset = 0;
617         binding_being_updated++;
618     }
619     if (update->descriptorCount) some_update_ = true;
620
621     InvalidateBoundCmdBuffers();
622 }
623 // Validate Copy update
624 bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data *report_data, const VkCopyDescriptorSet *update,
625                                                         const DescriptorSet *src_set, UNIQUE_VALIDATION_ERROR_CODE *error_code,
626                                                         std::string *error_msg) {
627     // Verify idle ds
628     if (in_use.load()) {
629         // TODO : Re-using Free Idle error code, need copy update idle error code
630         *error_code = VALIDATION_ERROR_2860026a;
631         std::stringstream error_str;
632         error_str << "Cannot call vkUpdateDescriptorSets() to perform copy update on descriptor set " << set_
633                   << " that is in use by a command buffer";
634         *error_msg = error_str.str();
635         return false;
636     }
637     if (!p_layout_->HasBinding(update->dstBinding)) {
638         *error_code = VALIDATION_ERROR_032002b6;
639         std::stringstream error_str;
640         error_str << "DescriptorSet " << set_ << " does not have copy update dest binding of " << update->dstBinding;
641         *error_msg = error_str.str();
642         return false;
643     }
644     if (!src_set->HasBinding(update->srcBinding)) {
645         *error_code = VALIDATION_ERROR_032002b2;
646         std::stringstream error_str;
647         error_str << "DescriptorSet " << set_ << " does not have copy update src binding of " << update->srcBinding;
648         *error_msg = error_str.str();
649         return false;
650     }
651     // src & dst set bindings are valid
652     // Check bounds of src & dst
653     auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
654     if ((src_start_idx + update->descriptorCount) > src_set->GetTotalDescriptorCount()) {
655         // SRC update out of bounds
656         *error_code = VALIDATION_ERROR_032002b4;
657         std::stringstream error_str;
658         error_str << "Attempting copy update from descriptorSet " << update->srcSet << " binding#" << update->srcBinding
659                   << " with offset index of " << src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start
660                   << " plus update array offset of " << update->srcArrayElement << " and update of " << update->descriptorCount
661                   << " descriptors oversteps total number of descriptors in set: " << src_set->GetTotalDescriptorCount();
662         *error_msg = error_str.str();
663         return false;
664     }
665     auto dst_start_idx = p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
666     if ((dst_start_idx + update->descriptorCount) > p_layout_->GetTotalDescriptorCount()) {
667         // DST update out of bounds
668         *error_code = VALIDATION_ERROR_032002b8;
669         std::stringstream error_str;
670         error_str << "Attempting copy update to descriptorSet " << set_ << " binding#" << update->dstBinding
671                   << " with offset index of " << p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start
672                   << " plus update array offset of " << update->dstArrayElement << " and update of " << update->descriptorCount
673                   << " descriptors oversteps total number of descriptors in set: " << p_layout_->GetTotalDescriptorCount();
674         *error_msg = error_str.str();
675         return false;
676     }
677     // Check that types match
678     // TODO : Base default error case going from here is VALIDATION_ERROR_0002b8012ba which covers all consistency issues, need more
679     // fine-grained error codes
680     *error_code = VALIDATION_ERROR_032002ba;
681     auto src_type = src_set->GetTypeFromBinding(update->srcBinding);
682     auto dst_type = p_layout_->GetTypeFromBinding(update->dstBinding);
683     if (src_type != dst_type) {
684         std::stringstream error_str;
685         error_str << "Attempting copy update to descriptorSet " << set_ << " binding #" << update->dstBinding << " with type "
686                   << string_VkDescriptorType(dst_type) << " from descriptorSet " << src_set->GetSet() << " binding #"
687                   << update->srcBinding << " with type " << string_VkDescriptorType(src_type) << ". Types do not match";
688         *error_msg = error_str.str();
689         return false;
690     }
691     // Verify consistency of src & dst bindings if update crosses binding boundaries
692     if ((!src_set->GetLayout()->VerifyUpdateConsistency(update->srcBinding, update->srcArrayElement, update->descriptorCount,
693                                                         "copy update from", src_set->GetSet(), error_msg)) ||
694         (!p_layout_->VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, "copy update to",
695                                              set_, error_msg))) {
696         return false;
697     }
698     // Update parameters all look good and descriptor updated so verify update contents
699     if (!VerifyCopyUpdateContents(update, src_set, src_type, src_start_idx, error_code, error_msg)) return false;
700
701     // All checks passed so update is good
702     return true;
703 }
704 // Perform Copy update
705 void cvdescriptorset::DescriptorSet::PerformCopyUpdate(const VkCopyDescriptorSet *update, const DescriptorSet *src_set) {
706     auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
707     auto dst_start_idx = p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
708     // Update parameters all look good so perform update
709     for (uint32_t di = 0; di < update->descriptorCount; ++di) {
710         auto src = src_set->descriptors_[src_start_idx + di].get();
711         auto dst = descriptors_[dst_start_idx + di].get();
712         if (src->updated) {
713             dst->CopyUpdate(src);
714             some_update_ = true;
715         } else {
716             dst->updated = false;
717         }
718     }
719
720     InvalidateBoundCmdBuffers();
721 }
722
723 // Bind cb_node to this set and this set to cb_node.
724 // Prereq: This should be called for a set that has been confirmed to be active for the given cb_node, meaning it's going
725 //   to be used in a draw by the given cb_node
726 void cvdescriptorset::DescriptorSet::BindCommandBuffer(GLOBAL_CB_NODE *cb_node,
727                                                        const std::map<uint32_t, descriptor_req> &binding_req_map) {
728     // bind cb to this descriptor set
729     cb_bindings.insert(cb_node);
730     // Add bindings for descriptor set, the set's pool, and individual objects in the set
731     cb_node->object_bindings.insert({HandleToUint64(set_), kVulkanObjectTypeDescriptorSet});
732     pool_state_->cb_bindings.insert(cb_node);
733     cb_node->object_bindings.insert({HandleToUint64(pool_state_->pool), kVulkanObjectTypeDescriptorPool});
734     // For the active slots, use set# to look up descriptorSet from boundDescriptorSets, and bind all of that descriptor set's
735     // resources
736     for (auto binding_req_pair : binding_req_map) {
737         auto binding = binding_req_pair.first;
738         auto range = p_layout_->GetGlobalIndexRangeFromBinding(binding);
739         for (uint32_t i = range.start; i < range.end; ++i) {
740             descriptors_[i]->BindCommandBuffer(device_data_, cb_node);
741         }
742     }
743 }
744 void cvdescriptorset::DescriptorSet::FilterAndTrackOneBindingReq(const BindingReqMap::value_type &binding_req_pair,
745                                                                  const BindingReqMap &in_req, BindingReqMap *out_req,
746                                                                  TrackedBindings *bindings) {
747     assert(out_req);
748     assert(bindings);
749     const auto binding = binding_req_pair.first;
750     // Use insert and look at the boolean ("was inserted") in the returned pair to see if this is a new set member.
751     // Saves one hash lookup vs. find ... compare w/ end ... insert.
752     const auto it_bool_pair = bindings->insert(binding);
753     if (it_bool_pair.second) {
754         out_req->emplace(binding_req_pair);
755     }
756 }
757 void cvdescriptorset::DescriptorSet::FilterAndTrackOneBindingReq(const BindingReqMap::value_type &binding_req_pair,
758                                                                  const BindingReqMap &in_req, BindingReqMap *out_req,
759                                                                  TrackedBindings *bindings, uint32_t limit) {
760     if (bindings->size() < limit) FilterAndTrackOneBindingReq(binding_req_pair, in_req, out_req, bindings);
761 }
762
763 void cvdescriptorset::DescriptorSet::FilterAndTrackBindingReqs(GLOBAL_CB_NODE *cb_state, const BindingReqMap &in_req,
764                                                                BindingReqMap *out_req) {
765     TrackedBindings &bound = cached_validation_[cb_state].command_binding_and_usage;
766     if (bound.size() == GetBindingCount()) {
767         return;  // All bindings are bound, out req is empty
768     }
769     for (const auto &binding_req_pair : in_req) {
770         const auto binding = binding_req_pair.first;
771         // If a binding doesn't exist, or has already been bound, skip it
772         if (p_layout_->HasBinding(binding)) {
773             FilterAndTrackOneBindingReq(binding_req_pair, in_req, out_req, &bound);
774         }
775     }
776 }
777
778 void cvdescriptorset::DescriptorSet::FilterAndTrackBindingReqs(GLOBAL_CB_NODE *cb_state, PIPELINE_STATE *pipeline,
779                                                                const BindingReqMap &in_req, BindingReqMap *out_req) {
780     auto &validated = cached_validation_[cb_state];
781     auto &image_sample_val = validated.image_samplers[pipeline];
782     auto *const dynamic_buffers = &validated.dynamic_buffers;
783     auto *const non_dynamic_buffers = &validated.non_dynamic_buffers;
784     const auto &stats = p_layout_->GetBindingTypeStats();
785     for (const auto &binding_req_pair : in_req) {
786         auto binding = binding_req_pair.first;
787         VkDescriptorSetLayoutBinding const *layout_binding = p_layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
788         if (!layout_binding) {
789             continue;
790         }
791         // Caching criteria differs per type.
792         // If image_layout have changed , the image descriptors need to be validated against them.
793         if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
794             (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
795             FilterAndTrackOneBindingReq(binding_req_pair, in_req, out_req, dynamic_buffers, stats.dynamic_buffer_count);
796         } else if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
797                    (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)) {
798             FilterAndTrackOneBindingReq(binding_req_pair, in_req, out_req, non_dynamic_buffers, stats.non_dynamic_buffer_count);
799         } else {
800             // This is rather crude, as the changed layouts may not impact the bound descriptors,
801             // but the simple "versioning" is a simple "dirt" test.
802             auto &version = image_sample_val[binding];  // Take advantage of default construtor zero initialzing new entries
803             if (version != cb_state->image_layout_change_count) {
804                 version = cb_state->image_layout_change_count;
805                 out_req->emplace(binding_req_pair);
806             }
807         }
808     }
809 }
810
811 cvdescriptorset::SamplerDescriptor::SamplerDescriptor(const VkSampler *immut) : sampler_(VK_NULL_HANDLE), immutable_(false) {
812     updated = false;
813     descriptor_class = PlainSampler;
814     if (immut) {
815         sampler_ = *immut;
816         immutable_ = true;
817         updated = true;
818     }
819 }
820 // Validate given sampler. Currently this only checks to make sure it exists in the samplerMap
821 bool cvdescriptorset::ValidateSampler(const VkSampler sampler, const layer_data *dev_data) {
822     return (GetSamplerState(dev_data, sampler) != nullptr);
823 }
824
825 bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type,
826                                           const layer_data *dev_data, UNIQUE_VALIDATION_ERROR_CODE *error_code,
827                                           std::string *error_msg) {
828     // TODO : Defaulting to 00943 for all cases here. Need to create new error codes for various cases.
829     *error_code = VALIDATION_ERROR_15c0028c;
830     auto iv_state = GetImageViewState(dev_data, image_view);
831     if (!iv_state) {
832         std::stringstream error_str;
833         error_str << "Invalid VkImageView: " << image_view;
834         *error_msg = error_str.str();
835         return false;
836     }
837     // Note that when an imageview is created, we validated that memory is bound so no need to re-check here
838     // Validate that imageLayout is compatible with aspect_mask and image format
839     //  and validate that image usage bits are correct for given usage
840     VkImageAspectFlags aspect_mask = iv_state->create_info.subresourceRange.aspectMask;
841     VkImage image = iv_state->create_info.image;
842     VkFormat format = VK_FORMAT_MAX_ENUM;
843     VkImageUsageFlags usage = 0;
844     auto image_node = GetImageState(dev_data, image);
845     if (image_node) {
846         format = image_node->createInfo.format;
847         usage = image_node->createInfo.usage;
848         // Validate that memory is bound to image
849         // TODO: This should have its own valid usage id apart from 2524 which is from CreateImageView case. The only
850         //  the error here occurs is if memory bound to a created imageView has been freed.
851         if (ValidateMemoryIsBoundToImage(dev_data, image_node, "vkUpdateDescriptorSets()", VALIDATION_ERROR_0ac007f8)) {
852             *error_code = VALIDATION_ERROR_0ac007f8;
853             *error_msg = "No memory bound to image.";
854             return false;
855         }
856
857         // KHR_maintenance1 allows rendering into 2D or 2DArray views which slice a 3D image,
858         // but not binding them to descriptor sets.
859         if (image_node->createInfo.imageType == VK_IMAGE_TYPE_3D &&
860             (iv_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_2D ||
861              iv_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)) {
862             *error_code = VALIDATION_ERROR_046002ae;
863             *error_msg = "ImageView must not be a 2D or 2DArray view of a 3D image";
864             return false;
865         }
866     }
867     // First validate that format and layout are compatible
868     if (format == VK_FORMAT_MAX_ENUM) {
869         std::stringstream error_str;
870         error_str << "Invalid image (" << image << ") in imageView (" << image_view << ").";
871         *error_msg = error_str.str();
872         return false;
873     }
874     // TODO : The various image aspect and format checks here are based on general spec language in 11.5 Image Views section under
875     // vkCreateImageView(). What's the best way to create unique id for these cases?
876     bool ds = FormatIsDepthOrStencil(format);
877     switch (image_layout) {
878         case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
879             // Only Color bit must be set
880             if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
881                 std::stringstream error_str;
882                 error_str << "ImageView (" << image_view << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but does "
883                                                             "not have VK_IMAGE_ASPECT_COLOR_BIT set.";
884                 *error_msg = error_str.str();
885                 return false;
886             }
887             // format must NOT be DS
888             if (ds) {
889                 std::stringstream error_str;
890                 error_str << "ImageView (" << image_view
891                           << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but the image format is "
892                           << string_VkFormat(format) << " which is not a color format.";
893                 *error_msg = error_str.str();
894                 return false;
895             }
896             break;
897         case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
898         case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
899             // Depth or stencil bit must be set, but both must NOT be set
900             if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
901                 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
902                     // both  must NOT be set
903                     std::stringstream error_str;
904                     error_str << "ImageView (" << image_view << ") has both STENCIL and DEPTH aspects set";
905                     *error_msg = error_str.str();
906                     return false;
907                 }
908             } else if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
909                 // Neither were set
910                 std::stringstream error_str;
911                 error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout)
912                           << " but does not have STENCIL or DEPTH aspects set";
913                 *error_msg = error_str.str();
914                 return false;
915             }
916             // format must be DS
917             if (!ds) {
918                 std::stringstream error_str;
919                 error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout)
920                           << " but the image format is " << string_VkFormat(format) << " which is not a depth/stencil format.";
921                 *error_msg = error_str.str();
922                 return false;
923             }
924             break;
925         default:
926             // For other layouts if the source is depth/stencil image, both aspect bits must not be set
927             if (ds) {
928                 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
929                     if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
930                         // both  must NOT be set
931                         std::stringstream error_str;
932                         error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout)
933                                   << " and is using depth/stencil image of format " << string_VkFormat(format)
934                                   << " but it has both STENCIL and DEPTH aspects set, which is illegal. When using a depth/stencil "
935                                      "image in a descriptor set, please only set either VK_IMAGE_ASPECT_DEPTH_BIT or "
936                                      "VK_IMAGE_ASPECT_STENCIL_BIT depending on whether it will be used for depth reads or stencil "
937                                      "reads respectively.";
938                         *error_msg = error_str.str();
939                         return false;
940                     }
941                 }
942             }
943             break;
944     }
945     // Now validate that usage flags are correctly set for given type of update
946     //  As we're switching per-type, if any type has specific layout requirements, check those here as well
947     // TODO : The various image usage bit requirements are in general spec language for VkImageUsageFlags bit block in 11.3 Images
948     // under vkCreateImage()
949     // TODO : Need to also validate case VALIDATION_ERROR_15c002a0 where STORAGE_IMAGE & INPUT_ATTACH types must have been created
950     // with identify swizzle
951     std::string error_usage_bit;
952     switch (type) {
953         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
954         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
955             if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
956                 error_usage_bit = "VK_IMAGE_USAGE_SAMPLED_BIT";
957             }
958             break;
959         }
960         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
961             if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
962                 error_usage_bit = "VK_IMAGE_USAGE_STORAGE_BIT";
963             } else if (VK_IMAGE_LAYOUT_GENERAL != image_layout) {
964                 std::stringstream error_str;
965                 // TODO : Need to create custom enum error codes for these cases
966                 if (image_node->shared_presentable) {
967                     if (VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR != image_layout) {
968                         error_str
969                             << "ImageView (" << image_view
970                             << ") of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE type with a front-buffered image is being updated with "
971                                "layout "
972                             << string_VkImageLayout(image_layout)
973                             << " but according to spec section 13.1 Descriptor Types, 'Front-buffered images that report support "
974                                "for "
975                                "VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT must be in the VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR layout.'";
976                         *error_msg = error_str.str();
977                         return false;
978                     }
979                 } else if (VK_IMAGE_LAYOUT_GENERAL != image_layout) {
980                     error_str
981                         << "ImageView (" << image_view << ") of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE type is being updated with layout "
982                         << string_VkImageLayout(image_layout)
983                         << " but according to spec section 13.1 Descriptor Types, 'Load and store operations on storage images can "
984                            "only be done on images in VK_IMAGE_LAYOUT_GENERAL layout.'";
985                     *error_msg = error_str.str();
986                     return false;
987                 }
988             }
989             break;
990         }
991         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
992             if (!(usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
993                 error_usage_bit = "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT";
994             }
995             break;
996         }
997         default:
998             break;
999     }
1000     if (!error_usage_bit.empty()) {
1001         std::stringstream error_str;
1002         error_str << "ImageView (" << image_view << ") with usage mask 0x" << usage
1003                   << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have "
1004                   << error_usage_bit << " set.";
1005         *error_msg = error_str.str();
1006         return false;
1007     }
1008     return true;
1009 }
1010
1011 void cvdescriptorset::SamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
1012     sampler_ = update->pImageInfo[index].sampler;
1013     updated = true;
1014 }
1015
1016 void cvdescriptorset::SamplerDescriptor::CopyUpdate(const Descriptor *src) {
1017     if (!immutable_) {
1018         auto update_sampler = static_cast<const SamplerDescriptor *>(src)->sampler_;
1019         sampler_ = update_sampler;
1020     }
1021     updated = true;
1022 }
1023
1024 void cvdescriptorset::SamplerDescriptor::BindCommandBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
1025     if (!immutable_) {
1026         auto sampler_state = GetSamplerState(dev_data, sampler_);
1027         if (sampler_state) core_validation::AddCommandBufferBindingSampler(cb_node, sampler_state);
1028     }
1029 }
1030
1031 cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(const VkSampler *immut)
1032     : sampler_(VK_NULL_HANDLE), immutable_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
1033     updated = false;
1034     descriptor_class = ImageSampler;
1035     if (immut) {
1036         sampler_ = *immut;
1037         immutable_ = true;
1038     }
1039 }
1040
1041 void cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
1042     updated = true;
1043     const auto &image_info = update->pImageInfo[index];
1044     sampler_ = image_info.sampler;
1045     image_view_ = image_info.imageView;
1046     image_layout_ = image_info.imageLayout;
1047 }
1048
1049 void cvdescriptorset::ImageSamplerDescriptor::CopyUpdate(const Descriptor *src) {
1050     if (!immutable_) {
1051         auto update_sampler = static_cast<const ImageSamplerDescriptor *>(src)->sampler_;
1052         sampler_ = update_sampler;
1053     }
1054     auto image_view = static_cast<const ImageSamplerDescriptor *>(src)->image_view_;
1055     auto image_layout = static_cast<const ImageSamplerDescriptor *>(src)->image_layout_;
1056     updated = true;
1057     image_view_ = image_view;
1058     image_layout_ = image_layout;
1059 }
1060
1061 void cvdescriptorset::ImageSamplerDescriptor::BindCommandBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
1062     // First add binding for any non-immutable sampler
1063     if (!immutable_) {
1064         auto sampler_state = GetSamplerState(dev_data, sampler_);
1065         if (sampler_state) core_validation::AddCommandBufferBindingSampler(cb_node, sampler_state);
1066     }
1067     // Add binding for image
1068     auto iv_state = GetImageViewState(dev_data, image_view_);
1069     if (iv_state) {
1070         core_validation::AddCommandBufferBindingImageView(dev_data, cb_node, iv_state);
1071     }
1072 }
1073
1074 cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type)
1075     : storage_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
1076     updated = false;
1077     descriptor_class = Image;
1078     if (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE == type) storage_ = true;
1079 }
1080
1081 void cvdescriptorset::ImageDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
1082     updated = true;
1083     const auto &image_info = update->pImageInfo[index];
1084     image_view_ = image_info.imageView;
1085     image_layout_ = image_info.imageLayout;
1086 }
1087
1088 void cvdescriptorset::ImageDescriptor::CopyUpdate(const Descriptor *src) {
1089     auto image_view = static_cast<const ImageDescriptor *>(src)->image_view_;
1090     auto image_layout = static_cast<const ImageDescriptor *>(src)->image_layout_;
1091     updated = true;
1092     image_view_ = image_view;
1093     image_layout_ = image_layout;
1094 }
1095
1096 void cvdescriptorset::ImageDescriptor::BindCommandBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
1097     // Add binding for image
1098     auto iv_state = GetImageViewState(dev_data, image_view_);
1099     if (iv_state) {
1100         core_validation::AddCommandBufferBindingImageView(dev_data, cb_node, iv_state);
1101     }
1102 }
1103
1104 cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type)
1105     : storage_(false), dynamic_(false), buffer_(VK_NULL_HANDLE), offset_(0), range_(0) {
1106     updated = false;
1107     descriptor_class = GeneralBuffer;
1108     if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) {
1109         dynamic_ = true;
1110     } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type) {
1111         storage_ = true;
1112     } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) {
1113         dynamic_ = true;
1114         storage_ = true;
1115     }
1116 }
1117 void cvdescriptorset::BufferDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
1118     updated = true;
1119     const auto &buffer_info = update->pBufferInfo[index];
1120     buffer_ = buffer_info.buffer;
1121     offset_ = buffer_info.offset;
1122     range_ = buffer_info.range;
1123 }
1124
1125 void cvdescriptorset::BufferDescriptor::CopyUpdate(const Descriptor *src) {
1126     auto buff_desc = static_cast<const BufferDescriptor *>(src);
1127     updated = true;
1128     buffer_ = buff_desc->buffer_;
1129     offset_ = buff_desc->offset_;
1130     range_ = buff_desc->range_;
1131 }
1132
1133 void cvdescriptorset::BufferDescriptor::BindCommandBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
1134     auto buffer_node = GetBufferState(dev_data, buffer_);
1135     if (buffer_node) core_validation::AddCommandBufferBindingBuffer(dev_data, cb_node, buffer_node);
1136 }
1137
1138 cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type) : buffer_view_(VK_NULL_HANDLE), storage_(false) {
1139     updated = false;
1140     descriptor_class = TexelBuffer;
1141     if (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER == type) storage_ = true;
1142 }
1143
1144 void cvdescriptorset::TexelDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
1145     updated = true;
1146     buffer_view_ = update->pTexelBufferView[index];
1147 }
1148
1149 void cvdescriptorset::TexelDescriptor::CopyUpdate(const Descriptor *src) {
1150     updated = true;
1151     buffer_view_ = static_cast<const TexelDescriptor *>(src)->buffer_view_;
1152 }
1153
1154 void cvdescriptorset::TexelDescriptor::BindCommandBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
1155     auto bv_state = GetBufferViewState(dev_data, buffer_view_);
1156     if (bv_state) {
1157         core_validation::AddCommandBufferBindingBufferView(dev_data, cb_node, bv_state);
1158     }
1159 }
1160
1161 // This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
1162 //  sets, and then calls their respective Validate[Write|Copy]Update functions.
1163 // If the update hits an issue for which the callback returns "true", meaning that the call down the chain should
1164 //  be skipped, then true is returned.
1165 // If there is no issue with the update, then false is returned.
1166 bool cvdescriptorset::ValidateUpdateDescriptorSets(const debug_report_data *report_data, const layer_data *dev_data,
1167                                                    uint32_t write_count, const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
1168                                                    const VkCopyDescriptorSet *p_cds) {
1169     bool skip = false;
1170     // Validate Write updates
1171     for (uint32_t i = 0; i < write_count; i++) {
1172         auto dest_set = p_wds[i].dstSet;
1173         auto set_node = core_validation::GetSetNode(dev_data, dest_set);
1174         if (!set_node) {
1175             skip |=
1176                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
1177                         HandleToUint64(dest_set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS",
1178                         "Cannot call vkUpdateDescriptorSets() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.",
1179                         HandleToUint64(dest_set));
1180         } else {
1181             UNIQUE_VALIDATION_ERROR_CODE error_code;
1182             std::string error_str;
1183             if (!set_node->ValidateWriteUpdate(report_data, &p_wds[i], &error_code, &error_str)) {
1184                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
1185                                 HandleToUint64(dest_set), __LINE__, error_code, "DS",
1186                                 "vkUpdateDescriptorSets() failed write update validation for Descriptor Set 0x%" PRIx64
1187                                 " with error: %s. %s",
1188                                 HandleToUint64(dest_set), error_str.c_str(), validation_error_map[error_code]);
1189             }
1190         }
1191     }
1192     // Now validate copy updates
1193     for (uint32_t i = 0; i < copy_count; ++i) {
1194         auto dst_set = p_cds[i].dstSet;
1195         auto src_set = p_cds[i].srcSet;
1196         auto src_node = core_validation::GetSetNode(dev_data, src_set);
1197         auto dst_node = core_validation::GetSetNode(dev_data, dst_set);
1198         // Object_tracker verifies that src & dest descriptor set are valid
1199         assert(src_node);
1200         assert(dst_node);
1201         UNIQUE_VALIDATION_ERROR_CODE error_code;
1202         std::string error_str;
1203         if (!dst_node->ValidateCopyUpdate(report_data, &p_cds[i], src_node, &error_code, &error_str)) {
1204             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
1205                             HandleToUint64(dst_set), __LINE__, error_code, "DS",
1206                             "vkUpdateDescriptorSets() failed copy update from Descriptor Set 0x%" PRIx64
1207                             " to Descriptor Set 0x%" PRIx64 " with error: %s. %s",
1208                             HandleToUint64(src_set), HandleToUint64(dst_set), error_str.c_str(), validation_error_map[error_code]);
1209         }
1210     }
1211     return skip;
1212 }
1213 // This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
1214 //  sets, and then calls their respective Perform[Write|Copy]Update functions.
1215 // Prerequisite : ValidateUpdateDescriptorSets() should be called and return "false" prior to calling PerformUpdateDescriptorSets()
1216 //  with the same set of updates.
1217 // This is split from the validate code to allow validation prior to calling down the chain, and then update after
1218 //  calling down the chain.
1219 void cvdescriptorset::PerformUpdateDescriptorSets(const layer_data *dev_data, uint32_t write_count,
1220                                                   const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
1221                                                   const VkCopyDescriptorSet *p_cds) {
1222     // Write updates first
1223     uint32_t i = 0;
1224     for (i = 0; i < write_count; ++i) {
1225         auto dest_set = p_wds[i].dstSet;
1226         auto set_node = core_validation::GetSetNode(dev_data, dest_set);
1227         if (set_node) {
1228             set_node->PerformWriteUpdate(&p_wds[i]);
1229         }
1230     }
1231     // Now copy updates
1232     for (i = 0; i < copy_count; ++i) {
1233         auto dst_set = p_cds[i].dstSet;
1234         auto src_set = p_cds[i].srcSet;
1235         auto src_node = core_validation::GetSetNode(dev_data, src_set);
1236         auto dst_node = core_validation::GetSetNode(dev_data, dst_set);
1237         if (src_node && dst_node) {
1238             dst_node->PerformCopyUpdate(&p_cds[i], src_node);
1239         }
1240     }
1241 }
1242 // This helper function carries out the state updates for descriptor updates peformed via update templates. It basically collects
1243 // data and leverages the PerformUpdateDescriptor helper functions to do this.
1244 void cvdescriptorset::PerformUpdateDescriptorSetsWithTemplateKHR(layer_data *device_data, VkDescriptorSet descriptorSet,
1245                                                                  std::unique_ptr<TEMPLATE_STATE> const &template_state,
1246                                                                  const void *pData) {
1247     auto const &create_info = template_state->create_info;
1248
1249     // Create a vector of write structs
1250     std::vector<VkWriteDescriptorSet> desc_writes;
1251     auto layout_obj = GetDescriptorSetLayout(device_data, create_info.descriptorSetLayout);
1252
1253     // Create a WriteDescriptorSet struct for each template update entry
1254     for (uint32_t i = 0; i < create_info.descriptorUpdateEntryCount; i++) {
1255         auto binding_count = layout_obj->GetDescriptorCountFromBinding(create_info.pDescriptorUpdateEntries[i].dstBinding);
1256         auto binding_being_updated = create_info.pDescriptorUpdateEntries[i].dstBinding;
1257         auto dst_array_element = create_info.pDescriptorUpdateEntries[i].dstArrayElement;
1258
1259         desc_writes.reserve(desc_writes.size() + create_info.pDescriptorUpdateEntries[i].descriptorCount);
1260         for (uint32_t j = 0; j < create_info.pDescriptorUpdateEntries[i].descriptorCount; j++) {
1261             desc_writes.emplace_back();
1262             auto &write_entry = desc_writes.back();
1263
1264             size_t offset = create_info.pDescriptorUpdateEntries[i].offset + j * create_info.pDescriptorUpdateEntries[i].stride;
1265             char *update_entry = (char *)(pData) + offset;
1266
1267             if (dst_array_element >= binding_count) {
1268                 dst_array_element = 0;
1269                 binding_being_updated = layout_obj->GetNextValidBinding(binding_being_updated);
1270             }
1271
1272             write_entry.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1273             write_entry.pNext = NULL;
1274             write_entry.dstSet = descriptorSet;
1275             write_entry.dstBinding = binding_being_updated;
1276             write_entry.dstArrayElement = dst_array_element;
1277             write_entry.descriptorCount = 1;
1278             write_entry.descriptorType = create_info.pDescriptorUpdateEntries[i].descriptorType;
1279
1280             switch (create_info.pDescriptorUpdateEntries[i].descriptorType) {
1281                 case VK_DESCRIPTOR_TYPE_SAMPLER:
1282                 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1283                 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1284                 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1285                 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1286                     write_entry.pImageInfo = reinterpret_cast<VkDescriptorImageInfo *>(update_entry);
1287                     break;
1288
1289                 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1290                 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1291                 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1292                 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1293                     write_entry.pBufferInfo = reinterpret_cast<VkDescriptorBufferInfo *>(update_entry);
1294                     break;
1295
1296                 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1297                 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1298                     write_entry.pTexelBufferView = reinterpret_cast<VkBufferView *>(update_entry);
1299                     break;
1300                 default:
1301                     assert(0);
1302                     break;
1303             }
1304             dst_array_element++;
1305         }
1306     }
1307     PerformUpdateDescriptorSets(device_data, static_cast<uint32_t>(desc_writes.size()), desc_writes.data(), 0, NULL);
1308 }
1309 // Validate the state for a given write update but don't actually perform the update
1310 //  If an error would occur for this update, return false and fill in details in error_msg string
1311 bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data *report_data, const VkWriteDescriptorSet *update,
1312                                                          UNIQUE_VALIDATION_ERROR_CODE *error_code, std::string *error_msg) {
1313     // Verify idle ds
1314     if (in_use.load()) {
1315         // TODO : Re-using Free Idle error code, need write update idle error code
1316         *error_code = VALIDATION_ERROR_2860026a;
1317         std::stringstream error_str;
1318         error_str << "Cannot call vkUpdateDescriptorSets() to perform write update on descriptor set " << set_
1319                   << " that is in use by a command buffer";
1320         *error_msg = error_str.str();
1321         return false;
1322     }
1323     // Verify dst binding exists
1324     if (!p_layout_->HasBinding(update->dstBinding)) {
1325         *error_code = VALIDATION_ERROR_15c00276;
1326         std::stringstream error_str;
1327         error_str << "DescriptorSet " << set_ << " does not have binding " << update->dstBinding;
1328         *error_msg = error_str.str();
1329         return false;
1330     } else {
1331         // Make sure binding isn't empty
1332         if (0 == p_layout_->GetDescriptorCountFromBinding(update->dstBinding)) {
1333             *error_code = VALIDATION_ERROR_15c00278;
1334             std::stringstream error_str;
1335             error_str << "DescriptorSet " << set_ << " cannot updated binding " << update->dstBinding << " that has 0 descriptors";
1336             *error_msg = error_str.str();
1337             return false;
1338         }
1339     }
1340     // We know that binding is valid, verify update and do update on each descriptor
1341     auto start_idx = p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
1342     auto type = p_layout_->GetTypeFromBinding(update->dstBinding);
1343     if (type != update->descriptorType) {
1344         *error_code = VALIDATION_ERROR_15c0027e;
1345         std::stringstream error_str;
1346         error_str << "Attempting write update to descriptor set " << set_ << " binding #" << update->dstBinding << " with type "
1347                   << string_VkDescriptorType(type) << " but update type is " << string_VkDescriptorType(update->descriptorType);
1348         *error_msg = error_str.str();
1349         return false;
1350     }
1351     if (update->descriptorCount > (descriptors_.size() - start_idx)) {
1352         *error_code = VALIDATION_ERROR_15c00282;
1353         std::stringstream error_str;
1354         error_str << "Attempting write update to descriptor set " << set_ << " binding #" << update->dstBinding << " with "
1355                   << descriptors_.size() - start_idx
1356                   << " descriptors in that binding and all successive bindings of the set, but update of "
1357                   << update->descriptorCount << " descriptors combined with update array element offset of "
1358                   << update->dstArrayElement << " oversteps the available number of consecutive descriptors";
1359         *error_msg = error_str.str();
1360         return false;
1361     }
1362     // Verify consecutive bindings match (if needed)
1363     if (!p_layout_->VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, "write update to",
1364                                             set_, error_msg)) {
1365         // TODO : Should break out "consecutive binding updates" language into valid usage statements
1366         *error_code = VALIDATION_ERROR_15c00282;
1367         return false;
1368     }
1369     // Update is within bounds and consistent so last step is to validate update contents
1370     if (!VerifyWriteUpdateContents(update, start_idx, error_code, error_msg)) {
1371         std::stringstream error_str;
1372         error_str << "Write update to descriptor in set " << set_ << " binding #" << update->dstBinding
1373                   << " failed with error message: " << error_msg->c_str();
1374         *error_msg = error_str.str();
1375         return false;
1376     }
1377     // All checks passed, update is clean
1378     return true;
1379 }
1380 // For the given buffer, verify that its creation parameters are appropriate for the given type
1381 //  If there's an error, update the error_msg string with details and return false, else return true
1382 bool cvdescriptorset::DescriptorSet::ValidateBufferUsage(BUFFER_STATE const *buffer_node, VkDescriptorType type,
1383                                                          UNIQUE_VALIDATION_ERROR_CODE *error_code, std::string *error_msg) const {
1384     // Verify that usage bits set correctly for given type
1385     auto usage = buffer_node->createInfo.usage;
1386     std::string error_usage_bit;
1387     switch (type) {
1388         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1389             if (!(usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) {
1390                 *error_code = VALIDATION_ERROR_15c0029c;
1391                 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT";
1392             }
1393             break;
1394         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1395             if (!(usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
1396                 *error_code = VALIDATION_ERROR_15c0029e;
1397                 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT";
1398             }
1399             break;
1400         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1401         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1402             if (!(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) {
1403                 *error_code = VALIDATION_ERROR_15c00292;
1404                 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT";
1405             }
1406             break;
1407         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1408         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1409             if (!(usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) {
1410                 *error_code = VALIDATION_ERROR_15c00296;
1411                 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT";
1412             }
1413             break;
1414         default:
1415             break;
1416     }
1417     if (!error_usage_bit.empty()) {
1418         std::stringstream error_str;
1419         error_str << "Buffer (" << buffer_node->buffer << ") with usage mask 0x" << usage
1420                   << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have "
1421                   << error_usage_bit << " set.";
1422         *error_msg = error_str.str();
1423         return false;
1424     }
1425     return true;
1426 }
1427 // For buffer descriptor updates, verify the buffer usage and VkDescriptorBufferInfo struct which includes:
1428 //  1. buffer is valid
1429 //  2. buffer was created with correct usage flags
1430 //  3. offset is less than buffer size
1431 //  4. range is either VK_WHOLE_SIZE or falls in (0, (buffer size - offset)]
1432 //  5. range and offset are within the device's limits
1433 // If there's an error, update the error_msg string with details and return false, else return true
1434 bool cvdescriptorset::DescriptorSet::ValidateBufferUpdate(VkDescriptorBufferInfo const *buffer_info, VkDescriptorType type,
1435                                                           UNIQUE_VALIDATION_ERROR_CODE *error_code, std::string *error_msg) const {
1436     // First make sure that buffer is valid
1437     auto buffer_node = GetBufferState(device_data_, buffer_info->buffer);
1438     // Any invalid buffer should already be caught by object_tracker
1439     assert(buffer_node);
1440     if (ValidateMemoryIsBoundToBuffer(device_data_, buffer_node, "vkUpdateDescriptorSets()", VALIDATION_ERROR_15c00294)) {
1441         *error_code = VALIDATION_ERROR_15c00294;
1442         *error_msg = "No memory bound to buffer.";
1443         return false;
1444     }
1445     // Verify usage bits
1446     if (!ValidateBufferUsage(buffer_node, type, error_code, error_msg)) {
1447         // error_msg will have been updated by ValidateBufferUsage()
1448         return false;
1449     }
1450     // offset must be less than buffer size
1451     if (buffer_info->offset >= buffer_node->createInfo.size) {
1452         *error_code = VALIDATION_ERROR_044002a8;
1453         std::stringstream error_str;
1454         error_str << "VkDescriptorBufferInfo offset of " << buffer_info->offset << " is greater than or equal to buffer "
1455                   << buffer_node->buffer << " size of " << buffer_node->createInfo.size;
1456         *error_msg = error_str.str();
1457         return false;
1458     }
1459     if (buffer_info->range != VK_WHOLE_SIZE) {
1460         // Range must be VK_WHOLE_SIZE or > 0
1461         if (!buffer_info->range) {
1462             *error_code = VALIDATION_ERROR_044002aa;
1463             std::stringstream error_str;
1464             error_str << "VkDescriptorBufferInfo range is not VK_WHOLE_SIZE and is zero, which is not allowed.";
1465             *error_msg = error_str.str();
1466             return false;
1467         }
1468         // Range must be VK_WHOLE_SIZE or <= (buffer size - offset)
1469         if (buffer_info->range > (buffer_node->createInfo.size - buffer_info->offset)) {
1470             *error_code = VALIDATION_ERROR_044002ac;
1471             std::stringstream error_str;
1472             error_str << "VkDescriptorBufferInfo range is " << buffer_info->range << " which is greater than buffer size ("
1473                       << buffer_node->createInfo.size << ") minus requested offset of " << buffer_info->offset;
1474             *error_msg = error_str.str();
1475             return false;
1476         }
1477     }
1478     // Check buffer update sizes against device limits
1479     if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == type || VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) {
1480         auto max_ub_range = limits_.maxUniformBufferRange;
1481         // TODO : If range is WHOLE_SIZE, need to make sure underlying buffer size doesn't exceed device max
1482         if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_ub_range) {
1483             *error_code = VALIDATION_ERROR_15c00298;
1484             std::stringstream error_str;
1485             error_str << "VkDescriptorBufferInfo range is " << buffer_info->range
1486                       << " which is greater than this device's maxUniformBufferRange (" << max_ub_range << ")";
1487             *error_msg = error_str.str();
1488             return false;
1489         }
1490     } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type || VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) {
1491         auto max_sb_range = limits_.maxStorageBufferRange;
1492         // TODO : If range is WHOLE_SIZE, need to make sure underlying buffer size doesn't exceed device max
1493         if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_sb_range) {
1494             *error_code = VALIDATION_ERROR_15c0029a;
1495             std::stringstream error_str;
1496             error_str << "VkDescriptorBufferInfo range is " << buffer_info->range
1497                       << " which is greater than this device's maxStorageBufferRange (" << max_sb_range << ")";
1498             *error_msg = error_str.str();
1499             return false;
1500         }
1501     }
1502     return true;
1503 }
1504
1505 // Verify that the contents of the update are ok, but don't perform actual update
1506 bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDescriptorSet *update, const uint32_t index,
1507                                                                UNIQUE_VALIDATION_ERROR_CODE *error_code,
1508                                                                std::string *error_msg) const {
1509     switch (update->descriptorType) {
1510         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
1511             for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1512                 // Validate image
1513                 auto image_view = update->pImageInfo[di].imageView;
1514                 auto image_layout = update->pImageInfo[di].imageLayout;
1515                 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, error_code, error_msg)) {
1516                     std::stringstream error_str;
1517                     error_str << "Attempted write update to combined image sampler descriptor failed due to: "
1518                               << error_msg->c_str();
1519                     *error_msg = error_str.str();
1520                     return false;
1521                 }
1522             }
1523             // Intentional fall-through to validate sampler
1524         }
1525         case VK_DESCRIPTOR_TYPE_SAMPLER: {
1526             for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1527                 if (!descriptors_[index + di].get()->IsImmutableSampler()) {
1528                     if (!ValidateSampler(update->pImageInfo[di].sampler, device_data_)) {
1529                         *error_code = VALIDATION_ERROR_15c0028a;
1530                         std::stringstream error_str;
1531                         error_str << "Attempted write update to sampler descriptor with invalid sampler: "
1532                                   << update->pImageInfo[di].sampler << ".";
1533                         *error_msg = error_str.str();
1534                         return false;
1535                     }
1536                 } else {
1537                     // TODO : Warn here
1538                 }
1539             }
1540             break;
1541         }
1542         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1543         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1544         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
1545             for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1546                 auto image_view = update->pImageInfo[di].imageView;
1547                 auto image_layout = update->pImageInfo[di].imageLayout;
1548                 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, error_code, error_msg)) {
1549                     std::stringstream error_str;
1550                     error_str << "Attempted write update to image descriptor failed due to: " << error_msg->c_str();
1551                     *error_msg = error_str.str();
1552                     return false;
1553                 }
1554             }
1555             break;
1556         }
1557         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1558         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
1559             for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1560                 auto buffer_view = update->pTexelBufferView[di];
1561                 auto bv_state = GetBufferViewState(device_data_, buffer_view);
1562                 if (!bv_state) {
1563                     *error_code = VALIDATION_ERROR_15c00286;
1564                     std::stringstream error_str;
1565                     error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: " << buffer_view;
1566                     *error_msg = error_str.str();
1567                     return false;
1568                 }
1569                 auto buffer = bv_state->create_info.buffer;
1570                 auto buffer_state = GetBufferState(device_data_, buffer);
1571                 // Verify that buffer underlying the view hasn't been destroyed prematurely
1572                 if (!buffer_state) {
1573                     *error_code = VALIDATION_ERROR_15c00286;
1574                     std::stringstream error_str;
1575                     error_str << "Attempted write update to texel buffer descriptor failed because underlying buffer (" << buffer
1576                               << ") has been destroyed: " << error_msg->c_str();
1577                     *error_msg = error_str.str();
1578                     return false;
1579                 } else if (!ValidateBufferUsage(buffer_state, update->descriptorType, error_code, error_msg)) {
1580                     std::stringstream error_str;
1581                     error_str << "Attempted write update to texel buffer descriptor failed due to: " << error_msg->c_str();
1582                     *error_msg = error_str.str();
1583                     return false;
1584                 }
1585             }
1586             break;
1587         }
1588         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1589         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1590         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1591         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
1592             for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1593                 if (!ValidateBufferUpdate(update->pBufferInfo + di, update->descriptorType, error_code, error_msg)) {
1594                     std::stringstream error_str;
1595                     error_str << "Attempted write update to buffer descriptor failed due to: " << error_msg->c_str();
1596                     *error_msg = error_str.str();
1597                     return false;
1598                 }
1599             }
1600             break;
1601         }
1602         default:
1603             assert(0);  // We've already verified update type so should never get here
1604             break;
1605     }
1606     // All checks passed so update contents are good
1607     return true;
1608 }
1609 // Verify that the contents of the update are ok, but don't perform actual update
1610 bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescriptorSet *update, const DescriptorSet *src_set,
1611                                                               VkDescriptorType type, uint32_t index,
1612                                                               UNIQUE_VALIDATION_ERROR_CODE *error_code,
1613                                                               std::string *error_msg) const {
1614     // Note : Repurposing some Write update error codes here as specific details aren't called out for copy updates like they are
1615     // for write updates
1616     switch (src_set->descriptors_[index]->descriptor_class) {
1617         case PlainSampler: {
1618             for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1619                 const auto src_desc = src_set->descriptors_[index + di].get();
1620                 if (!src_desc->updated) continue;
1621                 if (!src_desc->IsImmutableSampler()) {
1622                     auto update_sampler = static_cast<SamplerDescriptor *>(src_desc)->GetSampler();
1623                     if (!ValidateSampler(update_sampler, device_data_)) {
1624                         *error_code = VALIDATION_ERROR_15c0028a;
1625                         std::stringstream error_str;
1626                         error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << ".";
1627                         *error_msg = error_str.str();
1628                         return false;
1629                     }
1630                 } else {
1631                     // TODO : Warn here
1632                 }
1633             }
1634             break;
1635         }
1636         case ImageSampler: {
1637             for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1638                 const auto src_desc = src_set->descriptors_[index + di].get();
1639                 if (!src_desc->updated) continue;
1640                 auto img_samp_desc = static_cast<const ImageSamplerDescriptor *>(src_desc);
1641                 // First validate sampler
1642                 if (!img_samp_desc->IsImmutableSampler()) {
1643                     auto update_sampler = img_samp_desc->GetSampler();
1644                     if (!ValidateSampler(update_sampler, device_data_)) {
1645                         *error_code = VALIDATION_ERROR_15c0028a;
1646                         std::stringstream error_str;
1647                         error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << ".";
1648                         *error_msg = error_str.str();
1649                         return false;
1650                     }
1651                 } else {
1652                     // TODO : Warn here
1653                 }
1654                 // Validate image
1655                 auto image_view = img_samp_desc->GetImageView();
1656                 auto image_layout = img_samp_desc->GetImageLayout();
1657                 if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, error_code, error_msg)) {
1658                     std::stringstream error_str;
1659                     error_str << "Attempted copy update to combined image sampler descriptor failed due to: " << error_msg->c_str();
1660                     *error_msg = error_str.str();
1661                     return false;
1662                 }
1663             }
1664             break;
1665         }
1666         case Image: {
1667             for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1668                 const auto src_desc = src_set->descriptors_[index + di].get();
1669                 if (!src_desc->updated) continue;
1670                 auto img_desc = static_cast<const ImageDescriptor *>(src_desc);
1671                 auto image_view = img_desc->GetImageView();
1672                 auto image_layout = img_desc->GetImageLayout();
1673                 if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, error_code, error_msg)) {
1674                     std::stringstream error_str;
1675                     error_str << "Attempted copy update to image descriptor failed due to: " << error_msg->c_str();
1676                     *error_msg = error_str.str();
1677                     return false;
1678                 }
1679             }
1680             break;
1681         }
1682         case TexelBuffer: {
1683             for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1684                 const auto src_desc = src_set->descriptors_[index + di].get();
1685                 if (!src_desc->updated) continue;
1686                 auto buffer_view = static_cast<TexelDescriptor *>(src_desc)->GetBufferView();
1687                 auto bv_state = GetBufferViewState(device_data_, buffer_view);
1688                 if (!bv_state) {
1689                     *error_code = VALIDATION_ERROR_15c00286;
1690                     std::stringstream error_str;
1691                     error_str << "Attempted copy update to texel buffer descriptor with invalid buffer view: " << buffer_view;
1692                     *error_msg = error_str.str();
1693                     return false;
1694                 }
1695                 auto buffer = bv_state->create_info.buffer;
1696                 if (!ValidateBufferUsage(GetBufferState(device_data_, buffer), type, error_code, error_msg)) {
1697                     std::stringstream error_str;
1698                     error_str << "Attempted copy update to texel buffer descriptor failed due to: " << error_msg->c_str();
1699                     *error_msg = error_str.str();
1700                     return false;
1701                 }
1702             }
1703             break;
1704         }
1705         case GeneralBuffer: {
1706             for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1707                 const auto src_desc = src_set->descriptors_[index + di].get();
1708                 if (!src_desc->updated) continue;
1709                 auto buffer = static_cast<BufferDescriptor *>(src_desc)->GetBuffer();
1710                 if (!ValidateBufferUsage(GetBufferState(device_data_, buffer), type, error_code, error_msg)) {
1711                     std::stringstream error_str;
1712                     error_str << "Attempted copy update to buffer descriptor failed due to: " << error_msg->c_str();
1713                     *error_msg = error_str.str();
1714                     return false;
1715                 }
1716             }
1717             break;
1718         }
1719         default:
1720             assert(0);  // We've already verified update type so should never get here
1721             break;
1722     }
1723     // All checks passed so update contents are good
1724     return true;
1725 }
1726 // Update the common AllocateDescriptorSetsData
1727 void cvdescriptorset::UpdateAllocateDescriptorSetsData(const layer_data *dev_data, const VkDescriptorSetAllocateInfo *p_alloc_info,
1728                                                        AllocateDescriptorSetsData *ds_data) {
1729     for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
1730         auto layout = GetDescriptorSetLayout(dev_data, p_alloc_info->pSetLayouts[i]);
1731         if (layout) {
1732             ds_data->layout_nodes[i] = layout;
1733             // Count total descriptors required per type
1734             for (uint32_t j = 0; j < layout->GetBindingCount(); ++j) {
1735                 const auto &binding_layout = layout->GetDescriptorSetLayoutBindingPtrFromIndex(j);
1736                 uint32_t typeIndex = static_cast<uint32_t>(binding_layout->descriptorType);
1737                 ds_data->required_descriptors_by_type[typeIndex] += binding_layout->descriptorCount;
1738             }
1739         }
1740         // Any unknown layouts will be flagged as errors during ValidateAllocateDescriptorSets() call
1741     }
1742 }
1743 // Verify that the state at allocate time is correct, but don't actually allocate the sets yet
1744 bool cvdescriptorset::ValidateAllocateDescriptorSets(const core_validation::layer_data *dev_data,
1745                                                      const VkDescriptorSetAllocateInfo *p_alloc_info,
1746                                                      const AllocateDescriptorSetsData *ds_data) {
1747     bool skip = false;
1748     auto report_data = core_validation::GetReportData(dev_data);
1749
1750     for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
1751         auto layout = GetDescriptorSetLayout(dev_data, p_alloc_info->pSetLayouts[i]);
1752         if (!layout) {
1753             skip |=
1754                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
1755                         HandleToUint64(p_alloc_info->pSetLayouts[i]), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
1756                         "Unable to find set layout node for layout 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call",
1757                         HandleToUint64(p_alloc_info->pSetLayouts[i]));
1758         }
1759     }
1760     if (!GetDeviceExtensions(dev_data)->vk_khr_maintenance1) {
1761         auto pool_state = GetDescriptorPoolState(dev_data, p_alloc_info->descriptorPool);
1762         // Track number of descriptorSets allowable in this pool
1763         if (pool_state->availableSets < p_alloc_info->descriptorSetCount) {
1764             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
1765                             HandleToUint64(pool_state->pool), __LINE__, VALIDATION_ERROR_04c00264, "DS",
1766                             "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64
1767                             ". This pool only has %d descriptorSets remaining. %s",
1768                             p_alloc_info->descriptorSetCount, HandleToUint64(pool_state->pool), pool_state->availableSets,
1769                             validation_error_map[VALIDATION_ERROR_04c00264]);
1770         }
1771         // Determine whether descriptor counts are satisfiable
1772         for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) {
1773             if (ds_data->required_descriptors_by_type[i] > pool_state->availableDescriptorTypeCount[i]) {
1774                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
1775                                 HandleToUint64(pool_state->pool), __LINE__, VALIDATION_ERROR_04c00266, "DS",
1776                                 "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64
1777                                 ". This pool only has %d descriptors of this type remaining. %s",
1778                                 ds_data->required_descriptors_by_type[i], string_VkDescriptorType(VkDescriptorType(i)),
1779                                 HandleToUint64(pool_state->pool), pool_state->availableDescriptorTypeCount[i],
1780                                 validation_error_map[VALIDATION_ERROR_04c00266]);
1781             }
1782         }
1783     }
1784
1785     return skip;
1786 }
1787 // Decrement allocated sets from the pool and insert new sets into set_map
1788 void cvdescriptorset::PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *p_alloc_info,
1789                                                     const VkDescriptorSet *descriptor_sets,
1790                                                     const AllocateDescriptorSetsData *ds_data,
1791                                                     std::unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_STATE *> *pool_map,
1792                                                     std::unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> *set_map,
1793                                                     layer_data *dev_data) {
1794     auto pool_state = (*pool_map)[p_alloc_info->descriptorPool];
1795     // Account for sets and individual descriptors allocated from pool
1796     pool_state->availableSets -= p_alloc_info->descriptorSetCount;
1797     for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) {
1798         pool_state->availableDescriptorTypeCount[i] -= ds_data->required_descriptors_by_type[i];
1799     }
1800     // Create tracking object for each descriptor set; insert into global map and the pool's set.
1801     for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
1802         auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], p_alloc_info->descriptorPool, ds_data->layout_nodes[i],
1803                                                          dev_data);
1804
1805         pool_state->sets.insert(new_ds);
1806         new_ds->in_use.store(0);
1807         (*set_map)[descriptor_sets[i]] = new_ds;
1808     }
1809 }
1810
1811 cvdescriptorset::PrefilterBindRequestMap::PrefilterBindRequestMap(cvdescriptorset::DescriptorSet &ds, const BindingReqMap &in_map,
1812                                                                   GLOBAL_CB_NODE *cb_state)
1813     : filtered_map_(), orig_map_(in_map) {
1814     if (ds.GetTotalDescriptorCount() > kManyDescriptors_) {
1815         filtered_map_.reset(new std::map<uint32_t, descriptor_req>());
1816         ds.FilterAndTrackBindingReqs(cb_state, orig_map_, filtered_map_.get());
1817     }
1818 }
1819 cvdescriptorset::PrefilterBindRequestMap::PrefilterBindRequestMap(cvdescriptorset::DescriptorSet &ds, const BindingReqMap &in_map,
1820                                                                   GLOBAL_CB_NODE *cb_state, PIPELINE_STATE *pipeline)
1821     : filtered_map_(), orig_map_(in_map) {
1822     if (ds.GetTotalDescriptorCount() > kManyDescriptors_) {
1823         filtered_map_.reset(new std::map<uint32_t, descriptor_req>());
1824         ds.FilterAndTrackBindingReqs(cb_state, pipeline, orig_map_, filtered_map_.get());
1825     }
1826 }