1 /* Copyright (c) 2015-2019 The Khronos Group Inc. 2 * Copyright (c) 2015-2019 Valve Corporation 3 * Copyright (c) 2015-2019 LunarG, Inc. 4 * Copyright (C) 2015-2019 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 (at) google.com> 19 * John Zulauf <jzulauf (at) lunarg.com> 20 */ 21 22 // Allow use of STL min and max functions in Windows 23 #define NOMINMAX 24 25 #include "chassis.h" 26 #include "core_validation_error_enums.h" 27 #include "core_validation.h" 28 #include "descriptor_sets.h" 29 #include "hash_vk_types.h" 30 #include "vk_enum_string_helper.h" 31 #include "vk_safe_struct.h" 32 #include "vk_typemap_helper.h" 33 #include "buffer_validation.h" 34 #include <sstream> 35 #include <algorithm> 36 #include <array> 37 #include <memory> 38 39 // ExtendedBinding collects a VkDescriptorSetLayoutBinding and any extended 40 // state that comes from a different array/structure so they can stay together 41 // while being sorted by binding number. 42 struct ExtendedBinding { 43 ExtendedBinding(const VkDescriptorSetLayoutBinding *l, VkDescriptorBindingFlagsEXT f) : layout_binding(l), binding_flags(f) {} 44 45 const VkDescriptorSetLayoutBinding *layout_binding; 46 VkDescriptorBindingFlagsEXT binding_flags; 47 }; 48 49 struct BindingNumCmp { 50 bool operator()(const ExtendedBinding &a, const ExtendedBinding &b) const { 51 return a.layout_binding->binding < b.layout_binding->binding; 52 } 53 }; 54 55 using DescriptorSetLayoutDef = cvdescriptorset::DescriptorSetLayoutDef; 56 using DescriptorSetLayoutId = cvdescriptorset::DescriptorSetLayoutId; 57 58 // Canonical dictionary of DescriptorSetLayoutDef (without any handle/device specific information) 59 cvdescriptorset::DescriptorSetLayoutDict descriptor_set_layout_dict; 60 61 DescriptorSetLayoutId GetCanonicalId(const VkDescriptorSetLayoutCreateInfo *p_create_info) { 62 return descriptor_set_layout_dict.look_up(DescriptorSetLayoutDef(p_create_info)); 63 } 64 65 // Construct DescriptorSetLayout instance from given create info 66 // Proactively reserve and resize as possible, as the reallocation was visible in profiling 67 cvdescriptorset::DescriptorSetLayoutDef::DescriptorSetLayoutDef(const VkDescriptorSetLayoutCreateInfo *p_create_info) 68 : flags_(p_create_info->flags), binding_count_(0), descriptor_count_(0), dynamic_descriptor_count_(0) { 69 const auto *flags_create_info = lvl_find_in_chain<VkDescriptorSetLayoutBindingFlagsCreateInfoEXT>(p_create_info->pNext); 70 71 binding_type_stats_ = {0, 0, 0}; 72 std::set<ExtendedBinding, BindingNumCmp> sorted_bindings; 73 const uint32_t input_bindings_count = p_create_info->bindingCount; 74 // Sort the input bindings in binding number order, eliminating duplicates 75 for (uint32_t i = 0; i < input_bindings_count; i++) { 76 VkDescriptorBindingFlagsEXT flags = 0; 77 if (flags_create_info && flags_create_info->bindingCount == p_create_info->bindingCount) { 78 flags = flags_create_info->pBindingFlags[i]; 79 } 80 sorted_bindings.insert(ExtendedBinding(p_create_info->pBindings + i, flags)); 81 } 82 83 // Store the create info in the sorted order from above 84 std::map<uint32_t, uint32_t> binding_to_dyn_count; 85 uint32_t index = 0; 86 binding_count_ = static_cast<uint32_t>(sorted_bindings.size()); 87 bindings_.reserve(binding_count_); 88 binding_flags_.reserve(binding_count_); 89 binding_to_index_map_.reserve(binding_count_); 90 for (auto input_binding : sorted_bindings) { 91 // Add to binding and map, s.t. it is robust to invalid duplication of binding_num 92 const auto binding_num = input_binding.layout_binding->binding; 93 binding_to_index_map_[binding_num] = index++; 94 bindings_.emplace_back(input_binding.layout_binding); 95 auto &binding_info = bindings_.back(); 96 binding_flags_.emplace_back(input_binding.binding_flags); 97 98 descriptor_count_ += binding_info.descriptorCount; 99 if (binding_info.descriptorCount > 0) { 100 non_empty_bindings_.insert(binding_num); 101 } 102 103 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || 104 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) { 105 binding_to_dyn_count[binding_num] = binding_info.descriptorCount; 106 dynamic_descriptor_count_ += binding_info.descriptorCount; 107 binding_type_stats_.dynamic_buffer_count++; 108 } else if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) || 109 (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)) { 110 binding_type_stats_.non_dynamic_buffer_count++; 111 } else { 112 binding_type_stats_.image_sampler_count++; 113 } 114 } 115 assert(bindings_.size() == binding_count_); 116 assert(binding_flags_.size() == binding_count_); 117 uint32_t global_index = 0; 118 binding_to_global_index_range_map_.reserve(binding_count_); 119 // Vector order is finalized so create maps of bindings to descriptors and descriptors to indices 120 for (uint32_t i = 0; i < binding_count_; ++i) { 121 auto binding_num = bindings_[i].binding; 122 auto final_index = global_index + bindings_[i].descriptorCount; 123 binding_to_global_index_range_map_[binding_num] = IndexRange(global_index, final_index); 124 if (final_index != global_index) { 125 global_start_to_index_map_[global_index] = i; 126 } 127 global_index = final_index; 128 } 129 130 // Now create dyn offset array mapping for any dynamic descriptors 131 uint32_t dyn_array_idx = 0; 132 binding_to_dynamic_array_idx_map_.reserve(binding_to_dyn_count.size()); 133 for (const auto &bc_pair : binding_to_dyn_count) { 134 binding_to_dynamic_array_idx_map_[bc_pair.first] = dyn_array_idx; 135 dyn_array_idx += bc_pair.second; 136 } 137 } 138 139 size_t cvdescriptorset::DescriptorSetLayoutDef::hash() const { 140 hash_util::HashCombiner hc; 141 hc << flags_; 142 hc.Combine(bindings_); 143 hc.Combine(binding_flags_); 144 return hc.Value(); 145 } 146 // 147 148 // Return valid index or "end" i.e. binding_count_; 149 // The asserts in "Get" are reduced to the set where no valid answer(like null or 0) could be given 150 // Common code for all binding lookups. 151 uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetIndexFromBinding(uint32_t binding) const { 152 const auto &bi_itr = binding_to_index_map_.find(binding); 153 if (bi_itr != binding_to_index_map_.cend()) return bi_itr->second; 154 return GetBindingCount(); 155 } 156 VkDescriptorSetLayoutBinding const *cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorSetLayoutBindingPtrFromIndex( 157 const uint32_t index) const { 158 if (index >= bindings_.size()) return nullptr; 159 return bindings_[index].ptr(); 160 } 161 // Return descriptorCount for given index, 0 if index is unavailable 162 uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorCountFromIndex(const uint32_t index) const { 163 if (index >= bindings_.size()) return 0; 164 return bindings_[index].descriptorCount; 165 } 166 // For the given index, return descriptorType 167 VkDescriptorType cvdescriptorset::DescriptorSetLayoutDef::GetTypeFromIndex(const uint32_t index) const { 168 assert(index < bindings_.size()); 169 if (index < bindings_.size()) return bindings_[index].descriptorType; 170 return VK_DESCRIPTOR_TYPE_MAX_ENUM; 171 } 172 // For the given index, return stageFlags 173 VkShaderStageFlags cvdescriptorset::DescriptorSetLayoutDef::GetStageFlagsFromIndex(const uint32_t index) const { 174 assert(index < bindings_.size()); 175 if (index < bindings_.size()) return bindings_[index].stageFlags; 176 return VkShaderStageFlags(0); 177 } 178 // Return binding flags for given index, 0 if index is unavailable 179 VkDescriptorBindingFlagsEXT cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorBindingFlagsFromIndex( 180 const uint32_t index) const { 181 if (index >= binding_flags_.size()) return 0; 182 return binding_flags_[index]; 183 } 184 185 // For the given global index, return index 186 uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetIndexFromGlobalIndex(const uint32_t global_index) const { 187 auto start_it = global_start_to_index_map_.upper_bound(global_index); 188 uint32_t index = binding_count_; 189 assert(start_it != global_start_to_index_map_.cbegin()); 190 if (start_it != global_start_to_index_map_.cbegin()) { 191 --start_it; 192 index = start_it->second; 193 #ifndef NDEBUG 194 const auto &range = GetGlobalIndexRangeFromBinding(bindings_[index].binding); 195 assert(range.start <= global_index && global_index < range.end); 196 #endif 197 } 198 return index; 199 } 200 201 // For the given binding, return the global index range 202 // As start and end are often needed in pairs, get both with a single hash lookup. 203 const cvdescriptorset::IndexRange &cvdescriptorset::DescriptorSetLayoutDef::GetGlobalIndexRangeFromBinding( 204 const uint32_t binding) const { 205 assert(binding_to_global_index_range_map_.count(binding)); 206 // In error case max uint32_t so index is out of bounds to break ASAP 207 const static IndexRange kInvalidRange = {0xFFFFFFFF, 0xFFFFFFFF}; 208 const auto &range_it = binding_to_global_index_range_map_.find(binding); 209 if (range_it != binding_to_global_index_range_map_.end()) { 210 return range_it->second; 211 } 212 return kInvalidRange; 213 } 214 215 // For given binding, return ptr to ImmutableSampler array 216 VkSampler const *cvdescriptorset::DescriptorSetLayoutDef::GetImmutableSamplerPtrFromBinding(const uint32_t binding) const { 217 const auto &bi_itr = binding_to_index_map_.find(binding); 218 if (bi_itr != binding_to_index_map_.end()) { 219 return bindings_[bi_itr->second].pImmutableSamplers; 220 } 221 return nullptr; 222 } 223 // Move to next valid binding having a non-zero binding count 224 uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetNextValidBinding(const uint32_t binding) const { 225 auto it = non_empty_bindings_.upper_bound(binding); 226 assert(it != non_empty_bindings_.cend()); 227 if (it != non_empty_bindings_.cend()) return *it; 228 return GetMaxBinding() + 1; 229 } 230 // For given index, return ptr to ImmutableSampler array 231 VkSampler const *cvdescriptorset::DescriptorSetLayoutDef::GetImmutableSamplerPtrFromIndex(const uint32_t index) const { 232 if (index < bindings_.size()) { 233 return bindings_[index].pImmutableSamplers; 234 } 235 return nullptr; 236 } 237 // If our layout is compatible with rh_ds_layout, return true, 238 // else return false and fill in error_msg will description of what causes incompatibility 239 bool cvdescriptorset::DescriptorSetLayout::IsCompatible(DescriptorSetLayout const *const rh_ds_layout, 240 std::string *error_msg) const { 241 // Trivial case 242 if (layout_ == rh_ds_layout->GetDescriptorSetLayout()) return true; 243 if (GetLayoutDef() == rh_ds_layout->GetLayoutDef()) return true; 244 bool detailed_compat_check = 245 GetLayoutDef()->IsCompatible(layout_, rh_ds_layout->GetDescriptorSetLayout(), rh_ds_layout->GetLayoutDef(), error_msg); 246 // The detailed check should never tell us mismatching DSL are compatible 247 assert(!detailed_compat_check); 248 return detailed_compat_check; 249 } 250 251 // Do a detailed compatibility check of this def (referenced by ds_layout), vs. the rhs (layout and def) 252 // Should only be called if trivial accept has failed, and in that context should return false. 253 bool cvdescriptorset::DescriptorSetLayoutDef::IsCompatible(VkDescriptorSetLayout ds_layout, VkDescriptorSetLayout rh_ds_layout, 254 DescriptorSetLayoutDef const *const rh_ds_layout_def, 255 std::string *error_msg) const { 256 if (descriptor_count_ != rh_ds_layout_def->descriptor_count_) { 257 std::stringstream error_str; 258 error_str << "DescriptorSetLayout " << ds_layout << " has " << descriptor_count_ << " descriptors, but DescriptorSetLayout " 259 << rh_ds_layout << ", which comes from pipelineLayout, has " << rh_ds_layout_def->descriptor_count_ 260 << " descriptors."; 261 *error_msg = error_str.str(); 262 return false; // trivial fail case 263 } 264 265 // Descriptor counts match so need to go through bindings one-by-one 266 // and verify that type and stageFlags match 267 for (auto binding : bindings_) { 268 // TODO : Do we also need to check immutable samplers? 269 // VkDescriptorSetLayoutBinding *rh_binding; 270 if (binding.descriptorCount != rh_ds_layout_def->GetDescriptorCountFromBinding(binding.binding)) { 271 std::stringstream error_str; 272 error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << ds_layout << " has a descriptorCount of " 273 << binding.descriptorCount << " but binding " << binding.binding << " for DescriptorSetLayout " 274 << rh_ds_layout << ", which comes from pipelineLayout, has a descriptorCount of " 275 << rh_ds_layout_def->GetDescriptorCountFromBinding(binding.binding); 276 *error_msg = error_str.str(); 277 return false; 278 } else if (binding.descriptorType != rh_ds_layout_def->GetTypeFromBinding(binding.binding)) { 279 std::stringstream error_str; 280 error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << ds_layout << " is type '" 281 << string_VkDescriptorType(binding.descriptorType) << "' but binding " << binding.binding 282 << " for DescriptorSetLayout " << rh_ds_layout << ", which comes from pipelineLayout, is type '" 283 << string_VkDescriptorType(rh_ds_layout_def->GetTypeFromBinding(binding.binding)) << "'"; 284 *error_msg = error_str.str(); 285 return false; 286 } else if (binding.stageFlags != rh_ds_layout_def->GetStageFlagsFromBinding(binding.binding)) { 287 std::stringstream error_str; 288 error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << ds_layout << " has stageFlags " 289 << binding.stageFlags << " but binding " << binding.binding << " for DescriptorSetLayout " << rh_ds_layout 290 << ", which comes from pipelineLayout, has stageFlags " 291 << rh_ds_layout_def->GetStageFlagsFromBinding(binding.binding); 292 *error_msg = error_str.str(); 293 return false; 294 } 295 } 296 return true; 297 } 298 299 bool cvdescriptorset::DescriptorSetLayoutDef::IsNextBindingConsistent(const uint32_t binding) const { 300 if (!binding_to_index_map_.count(binding + 1)) return false; 301 auto const &bi_itr = binding_to_index_map_.find(binding); 302 if (bi_itr != binding_to_index_map_.end()) { 303 const auto &next_bi_itr = binding_to_index_map_.find(binding + 1); 304 if (next_bi_itr != binding_to_index_map_.end()) { 305 auto type = bindings_[bi_itr->second].descriptorType; 306 auto stage_flags = bindings_[bi_itr->second].stageFlags; 307 auto immut_samp = bindings_[bi_itr->second].pImmutableSamplers ? true : false; 308 auto flags = binding_flags_[bi_itr->second]; 309 if ((type != bindings_[next_bi_itr->second].descriptorType) || 310 (stage_flags != bindings_[next_bi_itr->second].stageFlags) || 311 (immut_samp != (bindings_[next_bi_itr->second].pImmutableSamplers ? true : false)) || 312 (flags != binding_flags_[next_bi_itr->second])) { 313 return false; 314 } 315 return true; 316 } 317 } 318 return false; 319 } 320 // Starting at offset descriptor of given binding, parse over update_count 321 // descriptor updates and verify that for any binding boundaries that are crossed, the next binding(s) are all consistent 322 // Consistency means that their type, stage flags, and whether or not they use immutable samplers matches 323 // If so, return true. If not, fill in error_msg and return false 324 bool cvdescriptorset::DescriptorSetLayoutDef::VerifyUpdateConsistency(uint32_t current_binding, uint32_t offset, 325 uint32_t update_count, const char *type, 326 const VkDescriptorSet set, std::string *error_msg) const { 327 // Verify consecutive bindings match (if needed) 328 auto orig_binding = current_binding; 329 // Track count of descriptors in the current_bindings that are remaining to be updated 330 auto binding_remaining = GetDescriptorCountFromBinding(current_binding); 331 // First, it's legal to offset beyond your own binding so handle that case 332 // Really this is just searching for the binding in which the update begins and adjusting offset accordingly 333 while (offset >= binding_remaining) { 334 // Advance to next binding, decrement offset by binding size 335 offset -= binding_remaining; 336 binding_remaining = GetDescriptorCountFromBinding(++current_binding); 337 } 338 binding_remaining -= offset; 339 while (update_count > binding_remaining) { // While our updates overstep current binding 340 // Verify next consecutive binding matches type, stage flags & immutable sampler use 341 if (!IsNextBindingConsistent(current_binding++)) { 342 std::stringstream error_str; 343 error_str << "Attempting " << type; 344 if (IsPushDescriptor()) { 345 error_str << " push descriptors"; 346 } else { 347 error_str << " descriptor set " << set; 348 } 349 error_str << " binding #" << orig_binding << " with #" << update_count 350 << " descriptors being updated but this update oversteps the bounds of this binding and the next binding is " 351 "not consistent with current binding so this update is invalid."; 352 *error_msg = error_str.str(); 353 return false; 354 } 355 // For sake of this check consider the bindings updated and grab count for next binding 356 update_count -= binding_remaining; 357 binding_remaining = GetDescriptorCountFromBinding(current_binding); 358 } 359 return true; 360 } 361 362 // The DescriptorSetLayout stores the per handle data for a descriptor set layout, and references the common defintion for the 363 // handle invariant portion 364 cvdescriptorset::DescriptorSetLayout::DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info, 365 const VkDescriptorSetLayout layout) 366 : layout_(layout), layout_destroyed_(false), layout_id_(GetCanonicalId(p_create_info)) {} 367 368 // Validate descriptor set layout create info 369 bool cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo( 370 const debug_report_data *report_data, const VkDescriptorSetLayoutCreateInfo *create_info, const bool push_descriptor_ext, 371 const uint32_t max_push_descriptors, const bool descriptor_indexing_ext, 372 const VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing_features, 373 const VkPhysicalDeviceInlineUniformBlockFeaturesEXT *inline_uniform_block_features, 374 const VkPhysicalDeviceInlineUniformBlockPropertiesEXT *inline_uniform_block_props) { 375 bool skip = false; 376 std::unordered_set<uint32_t> bindings; 377 uint64_t total_descriptors = 0; 378 379 const auto *flags_create_info = lvl_find_in_chain<VkDescriptorSetLayoutBindingFlagsCreateInfoEXT>(create_info->pNext); 380 381 const bool push_descriptor_set = !!(create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR); 382 if (push_descriptor_set && !push_descriptor_ext) { 383 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 384 kVUID_Core_DrawState_ExtensionNotEnabled, 385 "Attempted to use %s in %s but its required extension %s has not been enabled.\n", 386 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR", "VkDescriptorSetLayoutCreateInfo::flags", 387 VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); 388 } 389 390 const bool update_after_bind_set = !!(create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT); 391 if (update_after_bind_set && !descriptor_indexing_ext) { 392 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 393 kVUID_Core_DrawState_ExtensionNotEnabled, 394 "Attemped to use %s in %s but its required extension %s has not been enabled.\n", 395 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT", "VkDescriptorSetLayoutCreateInfo::flags", 396 VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); 397 } 398 399 auto valid_type = [push_descriptor_set](const VkDescriptorType type) { 400 return !push_descriptor_set || 401 ((type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) && (type != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) && 402 (type != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)); 403 }; 404 405 uint32_t max_binding = 0; 406 407 for (uint32_t i = 0; i < create_info->bindingCount; ++i) { 408 const auto &binding_info = create_info->pBindings[i]; 409 max_binding = std::max(max_binding, binding_info.binding); 410 411 if (!bindings.insert(binding_info.binding).second) { 412 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 413 "VUID-VkDescriptorSetLayoutCreateInfo-binding-00279", 414 "duplicated binding number in VkDescriptorSetLayoutBinding."); 415 } 416 if (!valid_type(binding_info.descriptorType)) { 417 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 418 (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) 419 ? "VUID-VkDescriptorSetLayoutCreateInfo-flags-02208" 420 : "VUID-VkDescriptorSetLayoutCreateInfo-flags-00280", 421 "invalid type %s ,for push descriptors in VkDescriptorSetLayoutBinding entry %" PRIu32 ".", 422 string_VkDescriptorType(binding_info.descriptorType), i); 423 } 424 425 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) { 426 if ((binding_info.descriptorCount % 4) != 0) { 427 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 428 "VUID-VkDescriptorSetLayoutBinding-descriptorType-02209", 429 "descriptorCount =(%" PRIu32 ") must be a multiple of 4", binding_info.descriptorCount); 430 } 431 if (binding_info.descriptorCount > inline_uniform_block_props->maxInlineUniformBlockSize) { 432 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 433 "VUID-VkDescriptorSetLayoutBinding-descriptorType-02210", 434 "descriptorCount =(%" PRIu32 ") must be less than or equal to maxInlineUniformBlockSize", 435 binding_info.descriptorCount); 436 } 437 } 438 439 total_descriptors += binding_info.descriptorCount; 440 } 441 442 if (flags_create_info) { 443 if (flags_create_info->bindingCount != 0 && flags_create_info->bindingCount != create_info->bindingCount) { 444 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 445 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-bindingCount-03002", 446 "VkDescriptorSetLayoutCreateInfo::bindingCount (%d) != " 447 "VkDescriptorSetLayoutBindingFlagsCreateInfoEXT::bindingCount (%d)", 448 create_info->bindingCount, flags_create_info->bindingCount); 449 } 450 451 if (flags_create_info->bindingCount == create_info->bindingCount) { 452 for (uint32_t i = 0; i < create_info->bindingCount; ++i) { 453 const auto &binding_info = create_info->pBindings[i]; 454 455 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT) { 456 if (!update_after_bind_set) { 457 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 458 "VUID-VkDescriptorSetLayoutCreateInfo-flags-03000", 459 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 460 } 461 462 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER && 463 !descriptor_indexing_features->descriptorBindingUniformBufferUpdateAfterBind) { 464 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 465 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-" 466 "descriptorBindingUniformBufferUpdateAfterBind-03005", 467 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 468 } 469 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || 470 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || 471 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) && 472 !descriptor_indexing_features->descriptorBindingSampledImageUpdateAfterBind) { 473 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 474 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-" 475 "descriptorBindingSampledImageUpdateAfterBind-03006", 476 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 477 } 478 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE && 479 !descriptor_indexing_features->descriptorBindingStorageImageUpdateAfterBind) { 480 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 481 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-" 482 "descriptorBindingStorageImageUpdateAfterBind-03007", 483 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 484 } 485 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER && 486 !descriptor_indexing_features->descriptorBindingStorageBufferUpdateAfterBind) { 487 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 488 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-" 489 "descriptorBindingStorageBufferUpdateAfterBind-03008", 490 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 491 } 492 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER && 493 !descriptor_indexing_features->descriptorBindingUniformTexelBufferUpdateAfterBind) { 494 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 495 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-" 496 "descriptorBindingUniformTexelBufferUpdateAfterBind-03009", 497 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 498 } 499 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER && 500 !descriptor_indexing_features->descriptorBindingStorageTexelBufferUpdateAfterBind) { 501 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 502 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-" 503 "descriptorBindingStorageTexelBufferUpdateAfterBind-03010", 504 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 505 } 506 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT || 507 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || 508 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) { 509 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 510 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-None-03011", 511 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 512 } 513 514 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT && 515 !inline_uniform_block_features->descriptorBindingInlineUniformBlockUpdateAfterBind) { 516 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 517 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-" 518 "descriptorBindingInlineUniformBlockUpdateAfterBind-02211", 519 "Invalid flags (VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT) for " 520 "VkDescriptorSetLayoutBinding entry %" PRIu32 521 " with descriptorBindingInlineUniformBlockUpdateAfterBind not enabled", 522 i); 523 } 524 } 525 526 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT) { 527 if (!descriptor_indexing_features->descriptorBindingUpdateUnusedWhilePending) { 528 skip |= log_msg( 529 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 530 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUpdateUnusedWhilePending-03012", 531 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 532 } 533 } 534 535 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT) { 536 if (!descriptor_indexing_features->descriptorBindingPartiallyBound) { 537 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 538 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingPartiallyBound-03013", 539 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 540 } 541 } 542 543 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT) { 544 if (binding_info.binding != max_binding) { 545 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 546 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-03004", 547 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 548 } 549 550 if (!descriptor_indexing_features->descriptorBindingVariableDescriptorCount) { 551 skip |= log_msg( 552 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 553 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingVariableDescriptorCount-03014", 554 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 555 } 556 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || 557 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) { 558 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 559 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-03015", 560 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 561 } 562 } 563 564 if (push_descriptor_set && 565 (flags_create_info->pBindingFlags[i] & 566 (VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | 567 VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT))) { 568 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 569 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-flags-03003", 570 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i); 571 } 572 } 573 } 574 } 575 576 if ((push_descriptor_set) && (total_descriptors > max_push_descriptors)) { 577 const char *undefined = push_descriptor_ext ? "" : " -- undefined"; 578 skip |= 579 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 580 "VUID-VkDescriptorSetLayoutCreateInfo-flags-00281", 581 "for push descriptor, total descriptor count in layout (%" PRIu64 582 ") must not be greater than VkPhysicalDevicePushDescriptorPropertiesKHR::maxPushDescriptors (%" PRIu32 "%s).", 583 total_descriptors, max_push_descriptors, undefined); 584 } 585 586 return skip; 587 } 588 589 cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t count) 590 : required_descriptors_by_type{}, layout_nodes(count, nullptr) {} 591 592 cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const VkDescriptorPool pool, 593 const std::shared_ptr<DescriptorSetLayout const> &layout, uint32_t variable_count, 594 layer_data *dev_data) 595 : some_update_(false), 596 set_(set), 597 pool_state_(nullptr), 598 p_layout_(layout), 599 device_data_(dev_data), 600 limits_(dev_data->phys_dev_props.limits), 601 variable_count_(variable_count) { 602 pool_state_ = dev_data->GetDescriptorPoolState(pool); 603 // Foreach binding, create default descriptors of given type 604 descriptors_.reserve(p_layout_->GetTotalDescriptorCount()); 605 for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) { 606 auto type = p_layout_->GetTypeFromIndex(i); 607 switch (type) { 608 case VK_DESCRIPTOR_TYPE_SAMPLER: { 609 auto immut_sampler = p_layout_->GetImmutableSamplerPtrFromIndex(i); 610 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) { 611 if (immut_sampler) { 612 descriptors_.emplace_back(new SamplerDescriptor(immut_sampler + di)); 613 some_update_ = true; // Immutable samplers are updated at creation 614 } else 615 descriptors_.emplace_back(new SamplerDescriptor(nullptr)); 616 } 617 break; 618 } 619 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { 620 auto immut = p_layout_->GetImmutableSamplerPtrFromIndex(i); 621 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) { 622 if (immut) { 623 descriptors_.emplace_back(new ImageSamplerDescriptor(immut + di)); 624 some_update_ = true; // Immutable samplers are updated at creation 625 } else 626 descriptors_.emplace_back(new ImageSamplerDescriptor(nullptr)); 627 } 628 break; 629 } 630 // ImageDescriptors 631 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 632 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 633 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 634 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) 635 descriptors_.emplace_back(new ImageDescriptor(type)); 636 break; 637 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 638 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 639 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) 640 descriptors_.emplace_back(new TexelDescriptor(type)); 641 break; 642 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 643 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 644 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 645 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 646 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) 647 descriptors_.emplace_back(new BufferDescriptor(type)); 648 break; 649 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: 650 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) 651 descriptors_.emplace_back(new InlineUniformDescriptor(type)); 652 break; 653 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: 654 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) 655 descriptors_.emplace_back(new AccelerationStructureDescriptor(type)); 656 break; 657 default: 658 assert(0); // Bad descriptor type specified 659 break; 660 } 661 } 662 } 663 664 cvdescriptorset::DescriptorSet::~DescriptorSet() { InvalidateBoundCmdBuffers(); } 665 666 static std::string StringDescriptorReqViewType(descriptor_req req) { 667 std::string result(""); 668 for (unsigned i = 0; i <= VK_IMAGE_VIEW_TYPE_END_RANGE; i++) { 669 if (req & (1 << i)) { 670 if (result.size()) result += ", "; 671 result += string_VkImageViewType(VkImageViewType(i)); 672 } 673 } 674 675 if (!result.size()) result = "(none)"; 676 677 return result; 678 } 679 680 static char const *StringDescriptorReqComponentType(descriptor_req req) { 681 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_SINT) return "SINT"; 682 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_UINT) return "UINT"; 683 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT) return "FLOAT"; 684 return "(none)"; 685 } 686 687 // Is this sets underlying layout compatible with passed in layout according to "Pipeline Layout Compatibility" in spec? 688 bool cvdescriptorset::DescriptorSet::IsCompatible(DescriptorSetLayout const *const layout, std::string *error) const { 689 return layout->IsCompatible(p_layout_.get(), error); 690 } 691 692 static unsigned DescriptorRequirementsBitsFromFormat(VkFormat fmt) { 693 if (FormatIsSInt(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_SINT; 694 if (FormatIsUInt(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_UINT; 695 if (FormatIsDepthAndStencil(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT | DESCRIPTOR_REQ_COMPONENT_TYPE_UINT; 696 if (fmt == VK_FORMAT_UNDEFINED) return 0; 697 // everything else -- UNORM/SNORM/FLOAT/USCALED/SSCALED is all float in the shader. 698 return DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT; 699 } 700 701 // Validate that the state of this set is appropriate for the given bindings and dynamic_offsets at Draw time 702 // This includes validating that all descriptors in the given bindings are updated, 703 // that any update buffers are valid, and that any dynamic offsets are within the bounds of their buffers. 704 // Return true if state is acceptable, or false and write an error message into error string 705 bool cvdescriptorset::DescriptorSet::ValidateDrawState(const std::map<uint32_t, descriptor_req> &bindings, 706 const std::vector<uint32_t> &dynamic_offsets, GLOBAL_CB_NODE *cb_node, 707 const char *caller, std::string *error) const { 708 for (auto binding_pair : bindings) { 709 auto binding = binding_pair.first; 710 if (!p_layout_->HasBinding(binding)) { 711 std::stringstream error_str; 712 error_str << "Attempting to validate DrawState for binding #" << binding 713 << " which is an invalid binding for this descriptor set."; 714 *error = error_str.str(); 715 return false; 716 } 717 IndexRange index_range = p_layout_->GetGlobalIndexRangeFromBinding(binding); 718 auto array_idx = 0; // Track array idx if we're dealing with array descriptors 719 720 if (IsVariableDescriptorCount(binding)) { 721 // Only validate the first N descriptors if it uses variable_count 722 index_range.end = index_range.start + GetVariableDescriptorCount(); 723 } 724 725 for (uint32_t i = index_range.start; i < index_range.end; ++i, ++array_idx) { 726 if ((p_layout_->GetDescriptorBindingFlagsFromBinding(binding) & 727 (VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT)) || 728 descriptors_[i]->GetClass() == InlineUniform) { 729 // Can't validate the descriptor because it may not have been updated, 730 // or the view could have been destroyed 731 continue; 732 } else if (!descriptors_[i]->updated) { 733 std::stringstream error_str; 734 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i 735 << " is being used in draw but has not been updated."; 736 *error = error_str.str(); 737 return false; 738 } else { 739 auto descriptor_class = descriptors_[i]->GetClass(); 740 if (descriptor_class == GeneralBuffer) { 741 // Verify that buffers are valid 742 auto buffer = static_cast<BufferDescriptor *>(descriptors_[i].get())->GetBuffer(); 743 auto buffer_node = device_data_->GetBufferState(buffer); 744 if (!buffer_node) { 745 std::stringstream error_str; 746 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i 747 << " references invalid buffer " << buffer << "."; 748 *error = error_str.str(); 749 return false; 750 } else if (!buffer_node->sparse) { 751 for (auto mem_binding : buffer_node->GetBoundMemory()) { 752 if (!device_data_->GetMemObjInfo(mem_binding)) { 753 std::stringstream error_str; 754 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i 755 << " uses buffer " << buffer << " that references invalid memory " << mem_binding << "."; 756 *error = error_str.str(); 757 return false; 758 } 759 } 760 } 761 if (descriptors_[i]->IsDynamic()) { 762 // Validate that dynamic offsets are within the buffer 763 auto buffer_size = buffer_node->createInfo.size; 764 auto range = static_cast<BufferDescriptor *>(descriptors_[i].get())->GetRange(); 765 auto desc_offset = static_cast<BufferDescriptor *>(descriptors_[i].get())->GetOffset(); 766 auto dyn_offset = dynamic_offsets[GetDynamicOffsetIndexFromBinding(binding) + array_idx]; 767 if (VK_WHOLE_SIZE == range) { 768 if ((dyn_offset + desc_offset) > buffer_size) { 769 std::stringstream error_str; 770 error_str << "Dynamic descriptor in binding #" << binding << " at global descriptor index " << i 771 << " uses buffer " << buffer << " with update range of VK_WHOLE_SIZE has dynamic offset " 772 << dyn_offset << " combined with offset " << desc_offset 773 << " that oversteps the buffer size of " << buffer_size << "."; 774 *error = error_str.str(); 775 return false; 776 } 777 } else { 778 if ((dyn_offset + desc_offset + range) > buffer_size) { 779 std::stringstream error_str; 780 error_str << "Dynamic descriptor in binding #" << binding << " at global descriptor index " << i 781 << " uses buffer " << buffer << " with dynamic offset " << dyn_offset 782 << " combined with offset " << desc_offset << " and range " << range 783 << " that oversteps the buffer size of " << buffer_size << "."; 784 *error = error_str.str(); 785 return false; 786 } 787 } 788 } 789 } else if (descriptor_class == ImageSampler || descriptor_class == Image) { 790 VkImageView image_view; 791 VkImageLayout image_layout; 792 if (descriptor_class == ImageSampler) { 793 image_view = static_cast<ImageSamplerDescriptor *>(descriptors_[i].get())->GetImageView(); 794 image_layout = static_cast<ImageSamplerDescriptor *>(descriptors_[i].get())->GetImageLayout(); 795 } else { 796 image_view = static_cast<ImageDescriptor *>(descriptors_[i].get())->GetImageView(); 797 image_layout = static_cast<ImageDescriptor *>(descriptors_[i].get())->GetImageLayout(); 798 } 799 auto reqs = binding_pair.second; 800 801 auto image_view_state = device_data_->GetImageViewState(image_view); 802 if (nullptr == image_view_state) { 803 // Image view must have been destroyed since initial update. Could potentially flag the descriptor 804 // as "invalid" (updated = false) at DestroyImageView() time and detect this error at bind time 805 std::stringstream error_str; 806 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i 807 << " is using imageView " << image_view << " that has been destroyed."; 808 *error = error_str.str(); 809 return false; 810 } 811 auto image_view_ci = image_view_state->create_info; 812 813 if ((reqs & DESCRIPTOR_REQ_ALL_VIEW_TYPE_BITS) && (~reqs & (1 << image_view_ci.viewType))) { 814 // bad view type 815 std::stringstream error_str; 816 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i 817 << " requires an image view of type " << StringDescriptorReqViewType(reqs) << " but got " 818 << string_VkImageViewType(image_view_ci.viewType) << "."; 819 *error = error_str.str(); 820 return false; 821 } 822 823 auto format_bits = DescriptorRequirementsBitsFromFormat(image_view_ci.format); 824 if (!(reqs & format_bits)) { 825 // bad component type 826 std::stringstream error_str; 827 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i << " requires " 828 << StringDescriptorReqComponentType(reqs) << " component type, but bound descriptor format is " 829 << string_VkFormat(image_view_ci.format) << "."; 830 *error = error_str.str(); 831 return false; 832 } 833 834 auto image_node = device_data_->GetImageState(image_view_ci.image); 835 assert(image_node); 836 // Verify Image Layout 837 // Copy first mip level into sub_layers and loop over each mip level to verify layout 838 VkImageSubresourceLayers sub_layers; 839 sub_layers.aspectMask = image_view_ci.subresourceRange.aspectMask; 840 sub_layers.baseArrayLayer = image_view_ci.subresourceRange.baseArrayLayer; 841 sub_layers.layerCount = image_view_ci.subresourceRange.layerCount; 842 bool hit_error = false; 843 for (auto cur_level = image_view_ci.subresourceRange.baseMipLevel; 844 cur_level < image_view_ci.subresourceRange.levelCount; ++cur_level) { 845 sub_layers.mipLevel = cur_level; 846 // No "invalid layout" VUID required for this call, since the optimal_layout parameter is UNDEFINED. 847 device_data_->VerifyImageLayout(device_data_, cb_node, image_node, sub_layers, image_layout, 848 VK_IMAGE_LAYOUT_UNDEFINED, caller, kVUIDUndefined, 849 "VUID-VkDescriptorImageInfo-imageLayout-00344", &hit_error); 850 if (hit_error) { 851 *error = 852 "Image layout specified at vkUpdateDescriptorSet* or vkCmdPushDescriptorSet* time " 853 "doesn't match actual image layout at time descriptor is used. See previous error callback for " 854 "specific details."; 855 return false; 856 } 857 } 858 // Verify Sample counts 859 if ((reqs & DESCRIPTOR_REQ_SINGLE_SAMPLE) && image_node->createInfo.samples != VK_SAMPLE_COUNT_1_BIT) { 860 std::stringstream error_str; 861 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i 862 << " requires bound image to have VK_SAMPLE_COUNT_1_BIT but got " 863 << string_VkSampleCountFlagBits(image_node->createInfo.samples) << "."; 864 *error = error_str.str(); 865 return false; 866 } 867 if ((reqs & DESCRIPTOR_REQ_MULTI_SAMPLE) && image_node->createInfo.samples == VK_SAMPLE_COUNT_1_BIT) { 868 std::stringstream error_str; 869 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i 870 << " requires bound image to have multiple samples, but got VK_SAMPLE_COUNT_1_BIT."; 871 *error = error_str.str(); 872 return false; 873 } 874 } else if (descriptor_class == TexelBuffer) { 875 auto texel_buffer = static_cast<TexelDescriptor *>(descriptors_[i].get()); 876 auto buffer_view = device_data_->GetBufferViewState(texel_buffer->GetBufferView()); 877 878 auto reqs = binding_pair.second; 879 auto format_bits = DescriptorRequirementsBitsFromFormat(buffer_view->create_info.format); 880 881 if (!(reqs & format_bits)) { 882 // bad component type 883 std::stringstream error_str; 884 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i << " requires " 885 << StringDescriptorReqComponentType(reqs) << " component type, but bound descriptor format is " 886 << string_VkFormat(buffer_view->create_info.format) << "."; 887 *error = error_str.str(); 888 return false; 889 } 890 } 891 if (descriptor_class == ImageSampler || descriptor_class == PlainSampler) { 892 // Verify Sampler still valid 893 VkSampler sampler; 894 if (descriptor_class == ImageSampler) { 895 sampler = static_cast<ImageSamplerDescriptor *>(descriptors_[i].get())->GetSampler(); 896 } else { 897 sampler = static_cast<SamplerDescriptor *>(descriptors_[i].get())->GetSampler(); 898 } 899 if (!ValidateSampler(sampler, device_data_)) { 900 std::stringstream error_str; 901 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i 902 << " is using sampler " << sampler << " that has been destroyed."; 903 *error = error_str.str(); 904 return false; 905 } 906 } 907 } 908 } 909 } 910 return true; 911 } 912 913 // For given bindings, place any update buffers or images into the passed-in unordered_sets 914 uint32_t cvdescriptorset::DescriptorSet::GetStorageUpdates(const std::map<uint32_t, descriptor_req> &bindings, 915 std::unordered_set<VkBuffer> *buffer_set, 916 std::unordered_set<VkImageView> *image_set) const { 917 auto num_updates = 0; 918 for (auto binding_pair : bindings) { 919 auto binding = binding_pair.first; 920 // If a binding doesn't exist, skip it 921 if (!p_layout_->HasBinding(binding)) { 922 continue; 923 } 924 uint32_t start_idx = p_layout_->GetGlobalIndexRangeFromBinding(binding).start; 925 if (descriptors_[start_idx]->IsStorage()) { 926 if (Image == descriptors_[start_idx]->descriptor_class) { 927 for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) { 928 if (descriptors_[start_idx + i]->updated) { 929 image_set->insert(static_cast<ImageDescriptor *>(descriptors_[start_idx + i].get())->GetImageView()); 930 num_updates++; 931 } 932 } 933 } else if (TexelBuffer == descriptors_[start_idx]->descriptor_class) { 934 for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) { 935 if (descriptors_[start_idx + i]->updated) { 936 auto bufferview = static_cast<TexelDescriptor *>(descriptors_[start_idx + i].get())->GetBufferView(); 937 auto bv_state = device_data_->GetBufferViewState(bufferview); 938 if (bv_state) { 939 buffer_set->insert(bv_state->create_info.buffer); 940 num_updates++; 941 } 942 } 943 } 944 } else if (GeneralBuffer == descriptors_[start_idx]->descriptor_class) { 945 for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) { 946 if (descriptors_[start_idx + i]->updated) { 947 buffer_set->insert(static_cast<BufferDescriptor *>(descriptors_[start_idx + i].get())->GetBuffer()); 948 num_updates++; 949 } 950 } 951 } 952 } 953 } 954 return num_updates; 955 } 956 // Set is being deleted or updates so invalidate all bound cmd buffers 957 void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers() { 958 device_data_->InvalidateCommandBuffers(device_data_, cb_bindings, {HandleToUint64(set_), kVulkanObjectTypeDescriptorSet}); 959 } 960 961 // Loop through the write updates to do for a push descriptor set, ignoring dstSet 962 void cvdescriptorset::DescriptorSet::PerformPushDescriptorsUpdate(uint32_t write_count, const VkWriteDescriptorSet *p_wds) { 963 assert(IsPushDescriptor()); 964 for (uint32_t i = 0; i < write_count; i++) { 965 PerformWriteUpdate(&p_wds[i]); 966 } 967 } 968 969 // Perform write update in given update struct 970 void cvdescriptorset::DescriptorSet::PerformWriteUpdate(const VkWriteDescriptorSet *update) { 971 // Perform update on a per-binding basis as consecutive updates roll over to next binding 972 auto descriptors_remaining = update->descriptorCount; 973 auto binding_being_updated = update->dstBinding; 974 auto offset = update->dstArrayElement; 975 uint32_t update_index = 0; 976 while (descriptors_remaining) { 977 uint32_t update_count = std::min(descriptors_remaining, GetDescriptorCountFromBinding(binding_being_updated)); 978 auto global_idx = p_layout_->GetGlobalIndexRangeFromBinding(binding_being_updated).start + offset; 979 // Loop over the updates for a single binding at a time 980 for (uint32_t di = 0; di < update_count; ++di, ++update_index) { 981 descriptors_[global_idx + di]->WriteUpdate(update, update_index); 982 } 983 // Roll over to next binding in case of consecutive update 984 descriptors_remaining -= update_count; 985 offset = 0; 986 binding_being_updated++; 987 } 988 if (update->descriptorCount) some_update_ = true; 989 990 if (!(p_layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) & 991 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) { 992 InvalidateBoundCmdBuffers(); 993 } 994 } 995 // Validate Copy update 996 bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data *report_data, const VkCopyDescriptorSet *update, 997 const DescriptorSet *src_set, const char *func_name, 998 std::string *error_code, std::string *error_msg) { 999 // Verify dst layout still valid 1000 if (p_layout_->IsDestroyed()) { 1001 *error_code = "VUID-VkCopyDescriptorSet-dstSet-parameter"; 1002 string_sprintf(error_msg, 1003 "Cannot call %s to perform copy update on descriptor set dstSet %s" 1004 " created with destroyed VkDescriptorSetLayout %s.", 1005 func_name, report_data->FormatHandle(set_).c_str(), 1006 report_data->FormatHandle(p_layout_->GetDescriptorSetLayout()).c_str()); 1007 return false; 1008 } 1009 1010 // Verify src layout still valid 1011 if (src_set->p_layout_->IsDestroyed()) { 1012 *error_code = "VUID-VkCopyDescriptorSet-srcSet-parameter"; 1013 string_sprintf(error_msg, 1014 "Cannot call %s to perform copy update of dstSet %s" 1015 " from descriptor set srcSet %s" 1016 " created with destroyed VkDescriptorSetLayout %s.", 1017 func_name, report_data->FormatHandle(set_).c_str(), report_data->FormatHandle(src_set->set_).c_str(), 1018 report_data->FormatHandle(src_set->p_layout_->GetDescriptorSetLayout()).c_str()); 1019 return false; 1020 } 1021 1022 if (!p_layout_->HasBinding(update->dstBinding)) { 1023 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-00347"; 1024 std::stringstream error_str; 1025 error_str << "DescriptorSet " << set_ << " does not have copy update dest binding of " << update->dstBinding; 1026 *error_msg = error_str.str(); 1027 return false; 1028 } 1029 if (!src_set->HasBinding(update->srcBinding)) { 1030 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-00345"; 1031 std::stringstream error_str; 1032 error_str << "DescriptorSet " << set_ << " does not have copy update src binding of " << update->srcBinding; 1033 *error_msg = error_str.str(); 1034 return false; 1035 } 1036 // Verify idle ds 1037 if (in_use.load() && 1038 !(p_layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) & 1039 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) { 1040 // TODO : Re-using Free Idle error code, need copy update idle error code 1041 *error_code = "VUID-vkFreeDescriptorSets-pDescriptorSets-00309"; 1042 std::stringstream error_str; 1043 error_str << "Cannot call " << func_name << " to perform copy update on descriptor set " << set_ 1044 << " that is in use by a command buffer"; 1045 *error_msg = error_str.str(); 1046 return false; 1047 } 1048 // src & dst set bindings are valid 1049 // Check bounds of src & dst 1050 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement; 1051 if ((src_start_idx + update->descriptorCount) > src_set->GetTotalDescriptorCount()) { 1052 // SRC update out of bounds 1053 *error_code = "VUID-VkCopyDescriptorSet-srcArrayElement-00346"; 1054 std::stringstream error_str; 1055 error_str << "Attempting copy update from descriptorSet " << update->srcSet << " binding#" << update->srcBinding 1056 << " with offset index of " << src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start 1057 << " plus update array offset of " << update->srcArrayElement << " and update of " << update->descriptorCount 1058 << " descriptors oversteps total number of descriptors in set: " << src_set->GetTotalDescriptorCount(); 1059 *error_msg = error_str.str(); 1060 return false; 1061 } 1062 auto dst_start_idx = p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement; 1063 if ((dst_start_idx + update->descriptorCount) > p_layout_->GetTotalDescriptorCount()) { 1064 // DST update out of bounds 1065 *error_code = "VUID-VkCopyDescriptorSet-dstArrayElement-00348"; 1066 std::stringstream error_str; 1067 error_str << "Attempting copy update to descriptorSet " << set_ << " binding#" << update->dstBinding 1068 << " with offset index of " << p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start 1069 << " plus update array offset of " << update->dstArrayElement << " and update of " << update->descriptorCount 1070 << " descriptors oversteps total number of descriptors in set: " << p_layout_->GetTotalDescriptorCount(); 1071 *error_msg = error_str.str(); 1072 return false; 1073 } 1074 // Check that types match 1075 // TODO : Base default error case going from here is "VUID-VkAcquireNextImageInfoKHR-semaphore-parameter"2ba which covers all 1076 // consistency issues, need more fine-grained error codes 1077 *error_code = "VUID-VkCopyDescriptorSet-srcSet-00349"; 1078 auto src_type = src_set->GetTypeFromBinding(update->srcBinding); 1079 auto dst_type = p_layout_->GetTypeFromBinding(update->dstBinding); 1080 if (src_type != dst_type) { 1081 std::stringstream error_str; 1082 error_str << "Attempting copy update to descriptorSet " << set_ << " binding #" << update->dstBinding << " with type " 1083 << string_VkDescriptorType(dst_type) << " from descriptorSet " << src_set->GetSet() << " binding #" 1084 << update->srcBinding << " with type " << string_VkDescriptorType(src_type) << ". Types do not match"; 1085 *error_msg = error_str.str(); 1086 return false; 1087 } 1088 // Verify consistency of src & dst bindings if update crosses binding boundaries 1089 if ((!src_set->GetLayout()->VerifyUpdateConsistency(update->srcBinding, update->srcArrayElement, update->descriptorCount, 1090 "copy update from", src_set->GetSet(), error_msg)) || 1091 (!p_layout_->VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, "copy update to", 1092 set_, error_msg))) { 1093 return false; 1094 } 1095 1096 if ((src_set->GetLayout()->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT) && 1097 !(GetLayout()->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT)) { 1098 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01918"; 1099 std::stringstream error_str; 1100 error_str << "If pname:srcSet's (" << update->srcSet 1101 << ") layout was created with the " 1102 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag " 1103 "set, then pname:dstSet's (" 1104 << update->dstSet 1105 << ") layout must: also have been created with the " 1106 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set"; 1107 *error_msg = error_str.str(); 1108 return false; 1109 } 1110 1111 if (!(src_set->GetLayout()->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT) && 1112 (GetLayout()->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT)) { 1113 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01919"; 1114 std::stringstream error_str; 1115 error_str << "If pname:srcSet's (" << update->srcSet 1116 << ") layout was created without the " 1117 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag " 1118 "set, then pname:dstSet's (" 1119 << update->dstSet 1120 << ") layout must: also have been created without the " 1121 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set"; 1122 *error_msg = error_str.str(); 1123 return false; 1124 } 1125 1126 if ((src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT) && 1127 !(GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)) { 1128 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01920"; 1129 std::stringstream error_str; 1130 error_str << "If the descriptor pool from which pname:srcSet (" << update->srcSet 1131 << ") was allocated was created " 1132 "with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag " 1133 "set, then the descriptor pool from which pname:dstSet (" 1134 << update->dstSet 1135 << ") was allocated must: " 1136 "also have been created with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set"; 1137 *error_msg = error_str.str(); 1138 return false; 1139 } 1140 1141 if (!(src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT) && 1142 (GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)) { 1143 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01921"; 1144 std::stringstream error_str; 1145 error_str << "If the descriptor pool from which pname:srcSet (" << update->srcSet 1146 << ") was allocated was created " 1147 "without the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag " 1148 "set, then the descriptor pool from which pname:dstSet (" 1149 << update->dstSet 1150 << ") was allocated must: " 1151 "also have been created without the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set"; 1152 *error_msg = error_str.str(); 1153 return false; 1154 } 1155 1156 if (src_type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) { 1157 if ((update->srcArrayElement % 4) != 0) { 1158 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-02223"; 1159 std::stringstream error_str; 1160 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with " 1161 << "srcArrayElement " << update->srcArrayElement << " not a multiple of 4"; 1162 *error_msg = error_str.str(); 1163 return false; 1164 } 1165 if ((update->dstArrayElement % 4) != 0) { 1166 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02224"; 1167 std::stringstream error_str; 1168 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with " 1169 << "dstArrayElement " << update->dstArrayElement << " not a multiple of 4"; 1170 *error_msg = error_str.str(); 1171 return false; 1172 } 1173 if ((update->descriptorCount % 4) != 0) { 1174 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-02225"; 1175 std::stringstream error_str; 1176 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with " 1177 << "descriptorCount " << update->descriptorCount << " not a multiple of 4"; 1178 *error_msg = error_str.str(); 1179 return false; 1180 } 1181 } 1182 1183 // Update parameters all look good and descriptor updated so verify update contents 1184 if (!VerifyCopyUpdateContents(update, src_set, src_type, src_start_idx, func_name, error_code, error_msg)) return false; 1185 1186 // All checks passed so update is good 1187 return true; 1188 } 1189 // Perform Copy update 1190 void cvdescriptorset::DescriptorSet::PerformCopyUpdate(const VkCopyDescriptorSet *update, const DescriptorSet *src_set) { 1191 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement; 1192 auto dst_start_idx = p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement; 1193 // Update parameters all look good so perform update 1194 for (uint32_t di = 0; di < update->descriptorCount; ++di) { 1195 auto src = src_set->descriptors_[src_start_idx + di].get(); 1196 auto dst = descriptors_[dst_start_idx + di].get(); 1197 if (src->updated) { 1198 dst->CopyUpdate(src); 1199 some_update_ = true; 1200 } else { 1201 dst->updated = false; 1202 } 1203 } 1204 1205 if (!(p_layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) & 1206 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) { 1207 InvalidateBoundCmdBuffers(); 1208 } 1209 } 1210 1211 // Update the drawing state for the affected descriptors. 1212 // Set cb_node to this set and this set to cb_node. 1213 // Add the bindings of the descriptor 1214 // Set the layout based on the current descriptor layout (will mask subsequent layer mismatch errors) 1215 // TODO: Modify the UpdateDrawState virtural functions to *only* set initial layout and not change layouts 1216 // Prereq: This should be called for a set that has been confirmed to be active for the given cb_node, meaning it's going 1217 // to be used in a draw by the given cb_node 1218 void cvdescriptorset::DescriptorSet::UpdateDrawState(GLOBAL_CB_NODE *cb_node, 1219 const std::map<uint32_t, descriptor_req> &binding_req_map) { 1220 // bind cb to this descriptor set 1221 cb_bindings.insert(cb_node); 1222 // Add bindings for descriptor set, the set's pool, and individual objects in the set 1223 cb_node->object_bindings.insert({HandleToUint64(set_), kVulkanObjectTypeDescriptorSet}); 1224 pool_state_->cb_bindings.insert(cb_node); 1225 cb_node->object_bindings.insert({HandleToUint64(pool_state_->pool), kVulkanObjectTypeDescriptorPool}); 1226 // For the active slots, use set# to look up descriptorSet from boundDescriptorSets, and bind all of that descriptor set's 1227 // resources 1228 for (auto binding_req_pair : binding_req_map) { 1229 auto binding = binding_req_pair.first; 1230 // We aren't validating descriptors created with PARTIALLY_BOUND or UPDATE_AFTER_BIND, so don't record state 1231 if (p_layout_->GetDescriptorBindingFlagsFromBinding(binding) & 1232 (VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT)) { 1233 continue; 1234 } 1235 auto range = p_layout_->GetGlobalIndexRangeFromBinding(binding); 1236 for (uint32_t i = range.start; i < range.end; ++i) { 1237 descriptors_[i]->UpdateDrawState(device_data_, cb_node); 1238 } 1239 } 1240 } 1241 1242 void cvdescriptorset::DescriptorSet::FilterAndTrackOneBindingReq(const BindingReqMap::value_type &binding_req_pair, 1243 const BindingReqMap &in_req, BindingReqMap *out_req, 1244 TrackedBindings *bindings) { 1245 assert(out_req); 1246 assert(bindings); 1247 const auto binding = binding_req_pair.first; 1248 // Use insert and look at the boolean ("was inserted") in the returned pair to see if this is a new set member. 1249 // Saves one hash lookup vs. find ... compare w/ end ... insert. 1250 const auto it_bool_pair = bindings->insert(binding); 1251 if (it_bool_pair.second) { 1252 out_req->emplace(binding_req_pair); 1253 } 1254 } 1255 1256 void cvdescriptorset::DescriptorSet::FilterAndTrackOneBindingReq(const BindingReqMap::value_type &binding_req_pair, 1257 const BindingReqMap &in_req, BindingReqMap *out_req, 1258 TrackedBindings *bindings, uint32_t limit) { 1259 if (bindings->size() < limit) FilterAndTrackOneBindingReq(binding_req_pair, in_req, out_req, bindings); 1260 } 1261 1262 void cvdescriptorset::DescriptorSet::FilterAndTrackBindingReqs(GLOBAL_CB_NODE *cb_state, const BindingReqMap &in_req, 1263 BindingReqMap *out_req) { 1264 TrackedBindings &bound = cached_validation_[cb_state].command_binding_and_usage; 1265 if (bound.size() == GetBindingCount()) { 1266 return; // All bindings are bound, out req is empty 1267 } 1268 for (const auto &binding_req_pair : in_req) { 1269 const auto binding = binding_req_pair.first; 1270 // If a binding doesn't exist, or has already been bound, skip it 1271 if (p_layout_->HasBinding(binding)) { 1272 FilterAndTrackOneBindingReq(binding_req_pair, in_req, out_req, &bound); 1273 } 1274 } 1275 } 1276 1277 void cvdescriptorset::DescriptorSet::FilterAndTrackBindingReqs(GLOBAL_CB_NODE *cb_state, PIPELINE_STATE *pipeline, 1278 const BindingReqMap &in_req, BindingReqMap *out_req) { 1279 auto &validated = cached_validation_[cb_state]; 1280 auto &image_sample_val = validated.image_samplers[pipeline]; 1281 auto *const dynamic_buffers = &validated.dynamic_buffers; 1282 auto *const non_dynamic_buffers = &validated.non_dynamic_buffers; 1283 const auto &stats = p_layout_->GetBindingTypeStats(); 1284 for (const auto &binding_req_pair : in_req) { 1285 auto binding = binding_req_pair.first; 1286 VkDescriptorSetLayoutBinding const *layout_binding = p_layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding); 1287 if (!layout_binding) { 1288 continue; 1289 } 1290 // Caching criteria differs per type. 1291 // If image_layout have changed , the image descriptors need to be validated against them. 1292 if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) || 1293 (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) { 1294 FilterAndTrackOneBindingReq(binding_req_pair, in_req, out_req, dynamic_buffers, stats.dynamic_buffer_count); 1295 } else if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) || 1296 (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)) { 1297 FilterAndTrackOneBindingReq(binding_req_pair, in_req, out_req, non_dynamic_buffers, stats.non_dynamic_buffer_count); 1298 } else { 1299 // This is rather crude, as the changed layouts may not impact the bound descriptors, 1300 // but the simple "versioning" is a simple "dirt" test. 1301 auto &version = image_sample_val[binding]; // Take advantage of default construtor zero initialzing new entries 1302 if (version != cb_state->image_layout_change_count) { 1303 version = cb_state->image_layout_change_count; 1304 out_req->emplace(binding_req_pair); 1305 } 1306 } 1307 } 1308 } 1309 1310 cvdescriptorset::SamplerDescriptor::SamplerDescriptor(const VkSampler *immut) : sampler_(VK_NULL_HANDLE), immutable_(false) { 1311 updated = false; 1312 descriptor_class = PlainSampler; 1313 if (immut) { 1314 sampler_ = *immut; 1315 immutable_ = true; 1316 updated = true; 1317 } 1318 } 1319 // Validate given sampler. Currently this only checks to make sure it exists in the samplerMap 1320 bool cvdescriptorset::ValidateSampler(const VkSampler sampler, layer_data *dev_data) { 1321 return (dev_data->GetSamplerState(sampler) != nullptr); 1322 } 1323 1324 bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type, 1325 layer_data *dev_data, const char *func_name, std::string *error_code, 1326 std::string *error_msg) { 1327 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00326"; 1328 auto iv_state = dev_data->GetImageViewState(image_view); 1329 if (!iv_state) { 1330 std::stringstream error_str; 1331 error_str << "Invalid VkImageView: " << image_view; 1332 *error_msg = error_str.str(); 1333 return false; 1334 } 1335 // Note that when an imageview is created, we validated that memory is bound so no need to re-check here 1336 // Validate that imageLayout is compatible with aspect_mask and image format 1337 // and validate that image usage bits are correct for given usage 1338 VkImageAspectFlags aspect_mask = iv_state->create_info.subresourceRange.aspectMask; 1339 VkImage image = iv_state->create_info.image; 1340 VkFormat format = VK_FORMAT_MAX_ENUM; 1341 VkImageUsageFlags usage = 0; 1342 auto image_node = dev_data->GetImageState(image); 1343 if (image_node) { 1344 format = image_node->createInfo.format; 1345 usage = image_node->createInfo.usage; 1346 // Validate that memory is bound to image 1347 // TODO: This should have its own valid usage id apart from 2524 which is from CreateImageView case. The only 1348 // the error here occurs is if memory bound to a created imageView has been freed. 1349 if (dev_data->ValidateMemoryIsBoundToImage(dev_data, image_node, func_name, "VUID-VkImageViewCreateInfo-image-01020")) { 1350 *error_code = "VUID-VkImageViewCreateInfo-image-01020"; 1351 *error_msg = "No memory bound to image."; 1352 return false; 1353 } 1354 1355 // KHR_maintenance1 allows rendering into 2D or 2DArray views which slice a 3D image, 1356 // but not binding them to descriptor sets. 1357 if (image_node->createInfo.imageType == VK_IMAGE_TYPE_3D && 1358 (iv_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_2D || 1359 iv_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)) { 1360 *error_code = "VUID-VkDescriptorImageInfo-imageView-00343"; 1361 *error_msg = "ImageView must not be a 2D or 2DArray view of a 3D image"; 1362 return false; 1363 } 1364 } 1365 // First validate that format and layout are compatible 1366 if (format == VK_FORMAT_MAX_ENUM) { 1367 std::stringstream error_str; 1368 error_str << "Invalid image (" << image << ") in imageView (" << image_view << ")."; 1369 *error_msg = error_str.str(); 1370 return false; 1371 } 1372 // TODO : The various image aspect and format checks here are based on general spec language in 11.5 Image Views section under 1373 // vkCreateImageView(). What's the best way to create unique id for these cases? 1374 bool ds = FormatIsDepthOrStencil(format); 1375 switch (image_layout) { 1376 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: 1377 // Only Color bit must be set 1378 if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) { 1379 std::stringstream error_str; 1380 error_str 1381 << "ImageView (" << image_view 1382 << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but does not have VK_IMAGE_ASPECT_COLOR_BIT set."; 1383 *error_msg = error_str.str(); 1384 return false; 1385 } 1386 // format must NOT be DS 1387 if (ds) { 1388 std::stringstream error_str; 1389 error_str << "ImageView (" << image_view 1390 << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but the image format is " 1391 << string_VkFormat(format) << " which is not a color format."; 1392 *error_msg = error_str.str(); 1393 return false; 1394 } 1395 break; 1396 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: 1397 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: 1398 // Depth or stencil bit must be set, but both must NOT be set 1399 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) { 1400 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) { 1401 // both must NOT be set 1402 std::stringstream error_str; 1403 error_str << "ImageView (" << image_view << ") has both STENCIL and DEPTH aspects set"; 1404 *error_msg = error_str.str(); 1405 return false; 1406 } 1407 } else if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) { 1408 // Neither were set 1409 std::stringstream error_str; 1410 error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout) 1411 << " but does not have STENCIL or DEPTH aspects set"; 1412 *error_msg = error_str.str(); 1413 return false; 1414 } 1415 // format must be DS 1416 if (!ds) { 1417 std::stringstream error_str; 1418 error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout) 1419 << " but the image format is " << string_VkFormat(format) << " which is not a depth/stencil format."; 1420 *error_msg = error_str.str(); 1421 return false; 1422 } 1423 break; 1424 default: 1425 // For other layouts if the source is depth/stencil image, both aspect bits must not be set 1426 if (ds) { 1427 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) { 1428 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) { 1429 // both must NOT be set 1430 std::stringstream error_str; 1431 error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout) 1432 << " and is using depth/stencil image of format " << string_VkFormat(format) 1433 << " but it has both STENCIL and DEPTH aspects set, which is illegal. When using a depth/stencil " 1434 "image in a descriptor set, please only set either VK_IMAGE_ASPECT_DEPTH_BIT or " 1435 "VK_IMAGE_ASPECT_STENCIL_BIT depending on whether it will be used for depth reads or stencil " 1436 "reads respectively."; 1437 *error_msg = error_str.str(); 1438 return false; 1439 } 1440 } 1441 } 1442 break; 1443 } 1444 // Now validate that usage flags are correctly set for given type of update 1445 // As we're switching per-type, if any type has specific layout requirements, check those here as well 1446 // TODO : The various image usage bit requirements are in general spec language for VkImageUsageFlags bit block in 11.3 Images 1447 // under vkCreateImage() 1448 // TODO : Need to also validate case "VUID-VkWriteDescriptorSet-descriptorType-00336" where STORAGE_IMAGE & INPUT_ATTACH types 1449 // must have been created with identify swizzle 1450 const char *error_usage_bit = nullptr; 1451 switch (type) { 1452 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 1453 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { 1454 if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) { 1455 error_usage_bit = "VK_IMAGE_USAGE_SAMPLED_BIT"; 1456 } 1457 break; 1458 } 1459 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: { 1460 if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT)) { 1461 error_usage_bit = "VK_IMAGE_USAGE_STORAGE_BIT"; 1462 } else if (VK_IMAGE_LAYOUT_GENERAL != image_layout) { 1463 std::stringstream error_str; 1464 // TODO : Need to create custom enum error codes for these cases 1465 if (image_node->shared_presentable) { 1466 if (VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR != image_layout) { 1467 error_str << "ImageView (" << image_view 1468 << ") of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE type with a front-buffered image is being updated with " 1469 "layout " 1470 << string_VkImageLayout(image_layout) 1471 << " but according to spec section 13.1 Descriptor Types, 'Front-buffered images that report " 1472 "support for VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT must be in the " 1473 "VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR layout.'"; 1474 *error_msg = error_str.str(); 1475 return false; 1476 } 1477 } else if (VK_IMAGE_LAYOUT_GENERAL != image_layout) { 1478 error_str << "ImageView (" << image_view 1479 << ") of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE type is being updated with layout " 1480 << string_VkImageLayout(image_layout) 1481 << " but according to spec section 13.1 Descriptor Types, 'Load and store operations on storage " 1482 "images can only be done on images in VK_IMAGE_LAYOUT_GENERAL layout.'"; 1483 *error_msg = error_str.str(); 1484 return false; 1485 } 1486 } 1487 break; 1488 } 1489 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: { 1490 if (!(usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) { 1491 error_usage_bit = "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT"; 1492 } 1493 break; 1494 } 1495 default: 1496 break; 1497 } 1498 if (error_usage_bit) { 1499 std::stringstream error_str; 1500 error_str << "ImageView (" << image_view << ") with usage mask 0x" << usage 1501 << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have " 1502 << error_usage_bit << " set."; 1503 *error_msg = error_str.str(); 1504 return false; 1505 } 1506 1507 if ((type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) || (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)) { 1508 // Test that the layout is compatible with the descriptorType for the two sampled image types 1509 const static std::array<VkImageLayout, 3> valid_layouts = { 1510 {VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL}}; 1511 1512 struct ExtensionLayout { 1513 VkImageLayout layout; 1514 bool DeviceExtensions::*extension; 1515 }; 1516 1517 const static std::array<ExtensionLayout, 3> extended_layouts{ 1518 {// Note double brace req'd for aggregate initialization 1519 {VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR, &DeviceExtensions::vk_khr_shared_presentable_image}, 1520 {VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, &DeviceExtensions::vk_khr_maintenance2}, 1521 {VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, &DeviceExtensions::vk_khr_maintenance2}}}; 1522 auto is_layout = [image_layout, dev_data](const ExtensionLayout &ext_layout) { 1523 return dev_data->device_extensions.*(ext_layout.extension) && (ext_layout.layout == image_layout); 1524 }; 1525 1526 bool valid_layout = (std::find(valid_layouts.cbegin(), valid_layouts.cend(), image_layout) != valid_layouts.cend()) || 1527 std::any_of(extended_layouts.cbegin(), extended_layouts.cend(), is_layout); 1528 1529 if (!valid_layout) { 1530 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-01403"; 1531 std::stringstream error_str; 1532 error_str << "Descriptor update with descriptorType " << string_VkDescriptorType(type) 1533 << " is being updated with invalid imageLayout " << string_VkImageLayout(image_layout) 1534 << ". Allowed layouts are: VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, " 1535 << "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL"; 1536 for (auto &ext_layout : extended_layouts) { 1537 if (dev_data->device_extensions.*(ext_layout.extension)) { 1538 error_str << ", " << string_VkImageLayout(ext_layout.layout); 1539 } 1540 } 1541 *error_msg = error_str.str(); 1542 return false; 1543 } 1544 } 1545 1546 return true; 1547 } 1548 1549 void cvdescriptorset::SamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { 1550 if (!immutable_) { 1551 sampler_ = update->pImageInfo[index].sampler; 1552 } 1553 updated = true; 1554 } 1555 1556 void cvdescriptorset::SamplerDescriptor::CopyUpdate(const Descriptor *src) { 1557 if (!immutable_) { 1558 auto update_sampler = static_cast<const SamplerDescriptor *>(src)->sampler_; 1559 sampler_ = update_sampler; 1560 } 1561 updated = true; 1562 } 1563 1564 void cvdescriptorset::SamplerDescriptor::UpdateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 1565 if (!immutable_) { 1566 auto sampler_state = dev_data->GetSamplerState(sampler_); 1567 if (sampler_state) dev_data->AddCommandBufferBindingSampler(cb_node, sampler_state); 1568 } 1569 } 1570 1571 cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(const VkSampler *immut) 1572 : sampler_(VK_NULL_HANDLE), immutable_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) { 1573 updated = false; 1574 descriptor_class = ImageSampler; 1575 if (immut) { 1576 sampler_ = *immut; 1577 immutable_ = true; 1578 } 1579 } 1580 1581 void cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { 1582 updated = true; 1583 const auto &image_info = update->pImageInfo[index]; 1584 if (!immutable_) { 1585 sampler_ = image_info.sampler; 1586 } 1587 image_view_ = image_info.imageView; 1588 image_layout_ = image_info.imageLayout; 1589 } 1590 1591 void cvdescriptorset::ImageSamplerDescriptor::CopyUpdate(const Descriptor *src) { 1592 if (!immutable_) { 1593 auto update_sampler = static_cast<const ImageSamplerDescriptor *>(src)->sampler_; 1594 sampler_ = update_sampler; 1595 } 1596 auto image_view = static_cast<const ImageSamplerDescriptor *>(src)->image_view_; 1597 auto image_layout = static_cast<const ImageSamplerDescriptor *>(src)->image_layout_; 1598 updated = true; 1599 image_view_ = image_view; 1600 image_layout_ = image_layout; 1601 } 1602 1603 void cvdescriptorset::ImageSamplerDescriptor::UpdateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 1604 // First add binding for any non-immutable sampler 1605 if (!immutable_) { 1606 auto sampler_state = dev_data->GetSamplerState(sampler_); 1607 if (sampler_state) dev_data->AddCommandBufferBindingSampler(cb_node, sampler_state); 1608 } 1609 // Add binding for image 1610 auto iv_state = dev_data->GetImageViewState(image_view_); 1611 if (iv_state) { 1612 dev_data->AddCommandBufferBindingImageView(dev_data, cb_node, iv_state); 1613 } 1614 if (image_view_) { 1615 dev_data->SetImageViewLayout(dev_data, cb_node, image_view_, image_layout_); 1616 } 1617 } 1618 1619 cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type) 1620 : storage_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) { 1621 updated = false; 1622 descriptor_class = Image; 1623 if (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE == type) storage_ = true; 1624 } 1625 1626 void cvdescriptorset::ImageDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { 1627 updated = true; 1628 const auto &image_info = update->pImageInfo[index]; 1629 image_view_ = image_info.imageView; 1630 image_layout_ = image_info.imageLayout; 1631 } 1632 1633 void cvdescriptorset::ImageDescriptor::CopyUpdate(const Descriptor *src) { 1634 auto image_view = static_cast<const ImageDescriptor *>(src)->image_view_; 1635 auto image_layout = static_cast<const ImageDescriptor *>(src)->image_layout_; 1636 updated = true; 1637 image_view_ = image_view; 1638 image_layout_ = image_layout; 1639 } 1640 1641 void cvdescriptorset::ImageDescriptor::UpdateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 1642 // Add binding for image 1643 auto iv_state = dev_data->GetImageViewState(image_view_); 1644 if (iv_state) { 1645 dev_data->AddCommandBufferBindingImageView(dev_data, cb_node, iv_state); 1646 } 1647 if (image_view_) { 1648 dev_data->SetImageViewLayout(dev_data, cb_node, image_view_, image_layout_); 1649 } 1650 } 1651 1652 cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type) 1653 : storage_(false), dynamic_(false), buffer_(VK_NULL_HANDLE), offset_(0), range_(0) { 1654 updated = false; 1655 descriptor_class = GeneralBuffer; 1656 if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) { 1657 dynamic_ = true; 1658 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type) { 1659 storage_ = true; 1660 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) { 1661 dynamic_ = true; 1662 storage_ = true; 1663 } 1664 } 1665 void cvdescriptorset::BufferDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { 1666 updated = true; 1667 const auto &buffer_info = update->pBufferInfo[index]; 1668 buffer_ = buffer_info.buffer; 1669 offset_ = buffer_info.offset; 1670 range_ = buffer_info.range; 1671 } 1672 1673 void cvdescriptorset::BufferDescriptor::CopyUpdate(const Descriptor *src) { 1674 auto buff_desc = static_cast<const BufferDescriptor *>(src); 1675 updated = true; 1676 buffer_ = buff_desc->buffer_; 1677 offset_ = buff_desc->offset_; 1678 range_ = buff_desc->range_; 1679 } 1680 1681 void cvdescriptorset::BufferDescriptor::UpdateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 1682 auto buffer_node = dev_data->GetBufferState(buffer_); 1683 if (buffer_node) dev_data->AddCommandBufferBindingBuffer(dev_data, cb_node, buffer_node); 1684 } 1685 1686 cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type) : buffer_view_(VK_NULL_HANDLE), storage_(false) { 1687 updated = false; 1688 descriptor_class = TexelBuffer; 1689 if (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER == type) storage_ = true; 1690 } 1691 1692 void cvdescriptorset::TexelDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { 1693 updated = true; 1694 buffer_view_ = update->pTexelBufferView[index]; 1695 } 1696 1697 void cvdescriptorset::TexelDescriptor::CopyUpdate(const Descriptor *src) { 1698 updated = true; 1699 buffer_view_ = static_cast<const TexelDescriptor *>(src)->buffer_view_; 1700 } 1701 1702 void cvdescriptorset::TexelDescriptor::UpdateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 1703 auto bv_state = dev_data->GetBufferViewState(buffer_view_); 1704 if (bv_state) { 1705 dev_data->AddCommandBufferBindingBufferView(dev_data, cb_node, bv_state); 1706 } 1707 } 1708 1709 // This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated 1710 // sets, and then calls their respective Validate[Write|Copy]Update functions. 1711 // If the update hits an issue for which the callback returns "true", meaning that the call down the chain should 1712 // be skipped, then true is returned. 1713 // If there is no issue with the update, then false is returned. 1714 bool CoreChecks::ValidateUpdateDescriptorSets(const debug_report_data *report_data, const layer_data *dev_data, 1715 uint32_t write_count, const VkWriteDescriptorSet *p_wds, uint32_t copy_count, 1716 const VkCopyDescriptorSet *p_cds, const char *func_name) { 1717 bool skip = false; 1718 // Validate Write updates 1719 for (uint32_t i = 0; i < write_count; i++) { 1720 auto dest_set = p_wds[i].dstSet; 1721 auto set_node = GetSetNode(dest_set); 1722 if (!set_node) { 1723 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 1724 HandleToUint64(dest_set), kVUID_Core_DrawState_InvalidDescriptorSet, 1725 "Cannot call %s on descriptor set %s that has not been allocated.", func_name, 1726 report_data->FormatHandle(dest_set).c_str()); 1727 } else { 1728 std::string error_code; 1729 std::string error_str; 1730 if (!set_node->ValidateWriteUpdate(report_data, &p_wds[i], func_name, &error_code, &error_str)) { 1731 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 1732 HandleToUint64(dest_set), error_code, 1733 "%s failed write update validation for Descriptor Set %s with error: %s.", func_name, 1734 report_data->FormatHandle(dest_set).c_str(), error_str.c_str()); 1735 } 1736 } 1737 } 1738 // Now validate copy updates 1739 for (uint32_t i = 0; i < copy_count; ++i) { 1740 auto dst_set = p_cds[i].dstSet; 1741 auto src_set = p_cds[i].srcSet; 1742 auto src_node = GetSetNode(src_set); 1743 auto dst_node = GetSetNode(dst_set); 1744 // Object_tracker verifies that src & dest descriptor set are valid 1745 assert(src_node); 1746 assert(dst_node); 1747 std::string error_code; 1748 std::string error_str; 1749 if (!dst_node->ValidateCopyUpdate(report_data, &p_cds[i], src_node, func_name, &error_code, &error_str)) { 1750 skip |= log_msg( 1751 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(dst_set), 1752 error_code, "%s failed copy update from Descriptor Set %s to Descriptor Set %s with error: %s.", func_name, 1753 report_data->FormatHandle(src_set).c_str(), report_data->FormatHandle(dst_set).c_str(), error_str.c_str()); 1754 } 1755 } 1756 return skip; 1757 } 1758 // This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated 1759 // sets, and then calls their respective Perform[Write|Copy]Update functions. 1760 // Prerequisite : ValidateUpdateDescriptorSets() should be called and return "false" prior to calling PerformUpdateDescriptorSets() 1761 // with the same set of updates. 1762 // This is split from the validate code to allow validation prior to calling down the chain, and then update after 1763 // calling down the chain. 1764 void cvdescriptorset::PerformUpdateDescriptorSets(layer_data *dev_data, uint32_t write_count, const VkWriteDescriptorSet *p_wds, 1765 uint32_t copy_count, const VkCopyDescriptorSet *p_cds) { 1766 // Write updates first 1767 uint32_t i = 0; 1768 for (i = 0; i < write_count; ++i) { 1769 auto dest_set = p_wds[i].dstSet; 1770 auto set_node = dev_data->GetSetNode(dest_set); 1771 if (set_node) { 1772 set_node->PerformWriteUpdate(&p_wds[i]); 1773 } 1774 } 1775 // Now copy updates 1776 for (i = 0; i < copy_count; ++i) { 1777 auto dst_set = p_cds[i].dstSet; 1778 auto src_set = p_cds[i].srcSet; 1779 auto src_node = dev_data->GetSetNode(src_set); 1780 auto dst_node = dev_data->GetSetNode(dst_set); 1781 if (src_node && dst_node) { 1782 dst_node->PerformCopyUpdate(&p_cds[i], src_node); 1783 } 1784 } 1785 } 1786 1787 cvdescriptorset::DecodedTemplateUpdate::DecodedTemplateUpdate(layer_data *device_data, VkDescriptorSet descriptorSet, 1788 const TEMPLATE_STATE *template_state, const void *pData, 1789 VkDescriptorSetLayout push_layout) { 1790 auto const &create_info = template_state->create_info; 1791 inline_infos.resize(create_info.descriptorUpdateEntryCount); // Make sure we have one if we need it 1792 desc_writes.reserve(create_info.descriptorUpdateEntryCount); // emplaced, so reserved without initialization 1793 VkDescriptorSetLayout effective_dsl = create_info.templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET 1794 ? create_info.descriptorSetLayout 1795 : push_layout; 1796 auto layout_obj = GetDescriptorSetLayout(device_data, effective_dsl); 1797 1798 // Create a WriteDescriptorSet struct for each template update entry 1799 for (uint32_t i = 0; i < create_info.descriptorUpdateEntryCount; i++) { 1800 auto binding_count = layout_obj->GetDescriptorCountFromBinding(create_info.pDescriptorUpdateEntries[i].dstBinding); 1801 auto binding_being_updated = create_info.pDescriptorUpdateEntries[i].dstBinding; 1802 auto dst_array_element = create_info.pDescriptorUpdateEntries[i].dstArrayElement; 1803 1804 desc_writes.reserve(desc_writes.size() + create_info.pDescriptorUpdateEntries[i].descriptorCount); 1805 for (uint32_t j = 0; j < create_info.pDescriptorUpdateEntries[i].descriptorCount; j++) { 1806 desc_writes.emplace_back(); 1807 auto &write_entry = desc_writes.back(); 1808 1809 size_t offset = create_info.pDescriptorUpdateEntries[i].offset + j * create_info.pDescriptorUpdateEntries[i].stride; 1810 char *update_entry = (char *)(pData) + offset; 1811 1812 if (dst_array_element >= binding_count) { 1813 dst_array_element = 0; 1814 binding_being_updated = layout_obj->GetNextValidBinding(binding_being_updated); 1815 } 1816 1817 write_entry.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 1818 write_entry.pNext = NULL; 1819 write_entry.dstSet = descriptorSet; 1820 write_entry.dstBinding = binding_being_updated; 1821 write_entry.dstArrayElement = dst_array_element; 1822 write_entry.descriptorCount = 1; 1823 write_entry.descriptorType = create_info.pDescriptorUpdateEntries[i].descriptorType; 1824 1825 switch (create_info.pDescriptorUpdateEntries[i].descriptorType) { 1826 case VK_DESCRIPTOR_TYPE_SAMPLER: 1827 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 1828 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 1829 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 1830 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 1831 write_entry.pImageInfo = reinterpret_cast<VkDescriptorImageInfo *>(update_entry); 1832 break; 1833 1834 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 1835 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 1836 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 1837 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 1838 write_entry.pBufferInfo = reinterpret_cast<VkDescriptorBufferInfo *>(update_entry); 1839 break; 1840 1841 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 1842 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 1843 write_entry.pTexelBufferView = reinterpret_cast<VkBufferView *>(update_entry); 1844 break; 1845 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: { 1846 VkWriteDescriptorSetInlineUniformBlockEXT *inline_info = &inline_infos[i]; 1847 inline_info->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT; 1848 inline_info->pNext = nullptr; 1849 inline_info->dataSize = create_info.pDescriptorUpdateEntries[i].descriptorCount; 1850 inline_info->pData = update_entry; 1851 write_entry.pNext = inline_info; 1852 // skip the rest of the array, they just represent bytes in the update 1853 j = create_info.pDescriptorUpdateEntries[i].descriptorCount; 1854 break; 1855 } 1856 default: 1857 assert(0); 1858 break; 1859 } 1860 dst_array_element++; 1861 } 1862 } 1863 } 1864 // These helper functions carry out the validate and record descriptor updates peformed via update templates. They decode 1865 // the templatized data and leverage the non-template UpdateDescriptor helper functions. 1866 bool CoreChecks::ValidateUpdateDescriptorSetsWithTemplateKHR(layer_data *device_data, VkDescriptorSet descriptorSet, 1867 const TEMPLATE_STATE *template_state, const void *pData) { 1868 // Translate the templated update into a normal update for validation... 1869 cvdescriptorset::DecodedTemplateUpdate decoded_update(device_data, descriptorSet, template_state, pData); 1870 return ValidateUpdateDescriptorSets(GetReportData(), device_data, static_cast<uint32_t>(decoded_update.desc_writes.size()), 1871 decoded_update.desc_writes.data(), 0, NULL, "vkUpdateDescriptorSetWithTemplate()"); 1872 } 1873 1874 void CoreChecks::PerformUpdateDescriptorSetsWithTemplateKHR(layer_data *device_data, VkDescriptorSet descriptorSet, 1875 const TEMPLATE_STATE *template_state, const void *pData) { 1876 // Translate the templated update into a normal update for validation... 1877 cvdescriptorset::DecodedTemplateUpdate decoded_update(device_data, descriptorSet, template_state, pData); 1878 cvdescriptorset::PerformUpdateDescriptorSets(device_data, static_cast<uint32_t>(decoded_update.desc_writes.size()), 1879 decoded_update.desc_writes.data(), 0, NULL); 1880 } 1881 1882 std::string cvdescriptorset::DescriptorSet::StringifySetAndLayout() const { 1883 std::string out; 1884 uint64_t layout_handle = HandleToUint64(p_layout_->GetDescriptorSetLayout()); 1885 if (IsPushDescriptor()) { 1886 string_sprintf(&out, "Push Descriptors defined with VkDescriptorSetLayout 0x%" PRIxLEAST64, layout_handle); 1887 } else { 1888 string_sprintf(&out, "VkDescriptorSet 0x%" PRIxLEAST64 "allocated with VkDescriptorSetLayout 0x%" PRIxLEAST64, 1889 HandleToUint64(set_), layout_handle); 1890 } 1891 return out; 1892 }; 1893 1894 // Loop through the write updates to validate for a push descriptor set, ignoring dstSet 1895 bool cvdescriptorset::DescriptorSet::ValidatePushDescriptorsUpdate(const debug_report_data *report_data, uint32_t write_count, 1896 const VkWriteDescriptorSet *p_wds, const char *func_name) { 1897 assert(IsPushDescriptor()); 1898 bool skip = false; 1899 for (uint32_t i = 0; i < write_count; i++) { 1900 std::string error_code; 1901 std::string error_str; 1902 if (!ValidateWriteUpdate(report_data, &p_wds[i], func_name, &error_code, &error_str)) { 1903 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, 1904 HandleToUint64(p_layout_->GetDescriptorSetLayout()), error_code, "%s failed update validation: %s.", 1905 func_name, error_str.c_str()); 1906 } 1907 } 1908 return skip; 1909 } 1910 1911 // Validate the state for a given write update but don't actually perform the update 1912 // If an error would occur for this update, return false and fill in details in error_msg string 1913 bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data *report_data, const VkWriteDescriptorSet *update, 1914 const char *func_name, std::string *error_code, std::string *error_msg) { 1915 // Verify dst layout still valid 1916 if (p_layout_->IsDestroyed()) { 1917 *error_code = "VUID-VkWriteDescriptorSet-dstSet-00320"; 1918 string_sprintf(error_msg, "Cannot call %s to perform write update on %s which has been destroyed", func_name, 1919 StringifySetAndLayout().c_str()); 1920 return false; 1921 } 1922 // Verify dst binding exists 1923 if (!p_layout_->HasBinding(update->dstBinding)) { 1924 *error_code = "VUID-VkWriteDescriptorSet-dstBinding-00315"; 1925 std::stringstream error_str; 1926 error_str << StringifySetAndLayout() << " does not have binding " << update->dstBinding; 1927 *error_msg = error_str.str(); 1928 return false; 1929 } else { 1930 // Make sure binding isn't empty 1931 if (0 == p_layout_->GetDescriptorCountFromBinding(update->dstBinding)) { 1932 *error_code = "VUID-VkWriteDescriptorSet-dstBinding-00316"; 1933 std::stringstream error_str; 1934 error_str << StringifySetAndLayout() << " cannot updated binding " << update->dstBinding << " that has 0 descriptors"; 1935 *error_msg = error_str.str(); 1936 return false; 1937 } 1938 } 1939 // Verify idle ds 1940 if (in_use.load() && 1941 !(p_layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) & 1942 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) { 1943 // TODO : Re-using Free Idle error code, need write update idle error code 1944 *error_code = "VUID-vkFreeDescriptorSets-pDescriptorSets-00309"; 1945 std::stringstream error_str; 1946 error_str << "Cannot call " << func_name << " to perform write update on " << StringifySetAndLayout() 1947 << " that is in use by a command buffer"; 1948 *error_msg = error_str.str(); 1949 return false; 1950 } 1951 // We know that binding is valid, verify update and do update on each descriptor 1952 auto start_idx = p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement; 1953 auto type = p_layout_->GetTypeFromBinding(update->dstBinding); 1954 if (type != update->descriptorType) { 1955 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00319"; 1956 std::stringstream error_str; 1957 error_str << "Attempting write update to " << StringifySetAndLayout() << " binding #" << update->dstBinding << " with type " 1958 << string_VkDescriptorType(type) << " but update type is " << string_VkDescriptorType(update->descriptorType); 1959 *error_msg = error_str.str(); 1960 return false; 1961 } 1962 if (update->descriptorCount > (descriptors_.size() - start_idx)) { 1963 *error_code = "VUID-VkWriteDescriptorSet-dstArrayElement-00321"; 1964 std::stringstream error_str; 1965 error_str << "Attempting write update to " << StringifySetAndLayout() << " binding #" << update->dstBinding << " with " 1966 << descriptors_.size() - start_idx 1967 << " descriptors in that binding and all successive bindings of the set, but update of " 1968 << update->descriptorCount << " descriptors combined with update array element offset of " 1969 << update->dstArrayElement << " oversteps the available number of consecutive descriptors"; 1970 *error_msg = error_str.str(); 1971 return false; 1972 } 1973 if (type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) { 1974 if ((update->dstArrayElement % 4) != 0) { 1975 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02219"; 1976 std::stringstream error_str; 1977 error_str << "Attempting write update to " << StringifySetAndLayout() << " binding #" << update->dstBinding << " with " 1978 << "dstArrayElement " << update->dstArrayElement << " not a multiple of 4"; 1979 *error_msg = error_str.str(); 1980 return false; 1981 } 1982 if ((update->descriptorCount % 4) != 0) { 1983 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02220"; 1984 std::stringstream error_str; 1985 error_str << "Attempting write update to " << StringifySetAndLayout() << " binding #" << update->dstBinding << " with " 1986 << "descriptorCount " << update->descriptorCount << " not a multiple of 4"; 1987 *error_msg = error_str.str(); 1988 return false; 1989 } 1990 const auto *write_inline_info = lvl_find_in_chain<VkWriteDescriptorSetInlineUniformBlockEXT>(update->pNext); 1991 if (!write_inline_info || write_inline_info->dataSize != update->descriptorCount) { 1992 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02221"; 1993 std::stringstream error_str; 1994 if (!write_inline_info) { 1995 error_str << "Attempting write update to " << StringifySetAndLayout() << " binding #" << update->dstBinding 1996 << " with " 1997 << "VkWriteDescriptorSetInlineUniformBlockEXT missing"; 1998 } else { 1999 error_str << "Attempting write update to " << StringifySetAndLayout() << " binding #" << update->dstBinding 2000 << " with " 2001 << "VkWriteDescriptorSetInlineUniformBlockEXT dataSize " << write_inline_info->dataSize 2002 << " not equal to " 2003 << "VkWriteDescriptorSet descriptorCount " << update->descriptorCount; 2004 } 2005 *error_msg = error_str.str(); 2006 return false; 2007 } 2008 // This error is probably unreachable due to the previous two errors 2009 if (write_inline_info && (write_inline_info->dataSize % 4) != 0) { 2010 *error_code = "VUID-VkWriteDescriptorSetInlineUniformBlockEXT-dataSize-02222"; 2011 std::stringstream error_str; 2012 error_str << "Attempting write update to " << StringifySetAndLayout() << " binding #" << update->dstBinding << " with " 2013 << "VkWriteDescriptorSetInlineUniformBlockEXT dataSize " << write_inline_info->dataSize 2014 << " not a multiple of 4"; 2015 *error_msg = error_str.str(); 2016 return false; 2017 } 2018 } 2019 // Verify consecutive bindings match (if needed) 2020 if (!p_layout_->VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, "write update to", 2021 set_, error_msg)) { 2022 // TODO : Should break out "consecutive binding updates" language into valid usage statements 2023 *error_code = "VUID-VkWriteDescriptorSet-dstArrayElement-00321"; 2024 return false; 2025 } 2026 // Update is within bounds and consistent so last step is to validate update contents 2027 if (!VerifyWriteUpdateContents(update, start_idx, func_name, error_code, error_msg)) { 2028 std::stringstream error_str; 2029 error_str << "Write update to " << StringifySetAndLayout() << " binding #" << update->dstBinding 2030 << " failed with error message: " << error_msg->c_str(); 2031 *error_msg = error_str.str(); 2032 return false; 2033 } 2034 // All checks passed, update is clean 2035 return true; 2036 } 2037 // For the given buffer, verify that its creation parameters are appropriate for the given type 2038 // If there's an error, update the error_msg string with details and return false, else return true 2039 bool cvdescriptorset::DescriptorSet::ValidateBufferUsage(BUFFER_STATE const *buffer_node, VkDescriptorType type, 2040 std::string *error_code, std::string *error_msg) const { 2041 // Verify that usage bits set correctly for given type 2042 auto usage = buffer_node->createInfo.usage; 2043 const char *error_usage_bit = nullptr; 2044 switch (type) { 2045 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 2046 if (!(usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) { 2047 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00334"; 2048 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT"; 2049 } 2050 break; 2051 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 2052 if (!(usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) { 2053 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00335"; 2054 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT"; 2055 } 2056 break; 2057 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 2058 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 2059 if (!(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) { 2060 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00330"; 2061 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT"; 2062 } 2063 break; 2064 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 2065 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 2066 if (!(usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) { 2067 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00331"; 2068 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT"; 2069 } 2070 break; 2071 default: 2072 break; 2073 } 2074 if (error_usage_bit) { 2075 std::stringstream error_str; 2076 error_str << "Buffer (" << buffer_node->buffer << ") with usage mask 0x" << usage 2077 << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have " 2078 << error_usage_bit << " set."; 2079 *error_msg = error_str.str(); 2080 return false; 2081 } 2082 return true; 2083 } 2084 // For buffer descriptor updates, verify the buffer usage and VkDescriptorBufferInfo struct which includes: 2085 // 1. buffer is valid 2086 // 2. buffer was created with correct usage flags 2087 // 3. offset is less than buffer size 2088 // 4. range is either VK_WHOLE_SIZE or falls in (0, (buffer size - offset)] 2089 // 5. range and offset are within the device's limits 2090 // If there's an error, update the error_msg string with details and return false, else return true 2091 bool cvdescriptorset::DescriptorSet::ValidateBufferUpdate(VkDescriptorBufferInfo const *buffer_info, VkDescriptorType type, 2092 const char *func_name, std::string *error_code, 2093 std::string *error_msg) const { 2094 // First make sure that buffer is valid 2095 auto buffer_node = device_data_->GetBufferState(buffer_info->buffer); 2096 // Any invalid buffer should already be caught by object_tracker 2097 assert(buffer_node); 2098 if (device_data_->ValidateMemoryIsBoundToBuffer(device_data_, buffer_node, func_name, 2099 "VUID-VkWriteDescriptorSet-descriptorType-00329")) { 2100 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00329"; 2101 *error_msg = "No memory bound to buffer."; 2102 return false; 2103 } 2104 // Verify usage bits 2105 if (!ValidateBufferUsage(buffer_node, type, error_code, error_msg)) { 2106 // error_msg will have been updated by ValidateBufferUsage() 2107 return false; 2108 } 2109 // offset must be less than buffer size 2110 if (buffer_info->offset >= buffer_node->createInfo.size) { 2111 *error_code = "VUID-VkDescriptorBufferInfo-offset-00340"; 2112 std::stringstream error_str; 2113 error_str << "VkDescriptorBufferInfo offset of " << buffer_info->offset << " is greater than or equal to buffer " 2114 << buffer_node->buffer << " size of " << buffer_node->createInfo.size; 2115 *error_msg = error_str.str(); 2116 return false; 2117 } 2118 if (buffer_info->range != VK_WHOLE_SIZE) { 2119 // Range must be VK_WHOLE_SIZE or > 0 2120 if (!buffer_info->range) { 2121 *error_code = "VUID-VkDescriptorBufferInfo-range-00341"; 2122 std::stringstream error_str; 2123 error_str << "VkDescriptorBufferInfo range is not VK_WHOLE_SIZE and is zero, which is not allowed."; 2124 *error_msg = error_str.str(); 2125 return false; 2126 } 2127 // Range must be VK_WHOLE_SIZE or <= (buffer size - offset) 2128 if (buffer_info->range > (buffer_node->createInfo.size - buffer_info->offset)) { 2129 *error_code = "VUID-VkDescriptorBufferInfo-range-00342"; 2130 std::stringstream error_str; 2131 error_str << "VkDescriptorBufferInfo range is " << buffer_info->range << " which is greater than buffer size (" 2132 << buffer_node->createInfo.size << ") minus requested offset of " << buffer_info->offset; 2133 *error_msg = error_str.str(); 2134 return false; 2135 } 2136 } 2137 // Check buffer update sizes against device limits 2138 if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == type || VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) { 2139 auto max_ub_range = limits_.maxUniformBufferRange; 2140 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_ub_range) { 2141 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00332"; 2142 std::stringstream error_str; 2143 error_str << "VkDescriptorBufferInfo range is " << buffer_info->range 2144 << " which is greater than this device's maxUniformBufferRange (" << max_ub_range << ")"; 2145 *error_msg = error_str.str(); 2146 return false; 2147 } else if (buffer_info->range == VK_WHOLE_SIZE && (buffer_node->createInfo.size - buffer_info->offset) > max_ub_range) { 2148 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00332"; 2149 std::stringstream error_str; 2150 error_str << "VkDescriptorBufferInfo range is VK_WHOLE_SIZE but effective range " 2151 << "(" << (buffer_node->createInfo.size - buffer_info->offset) << ") is greater than this device's " 2152 << "maxUniformBufferRange (" << max_ub_range << ")"; 2153 *error_msg = error_str.str(); 2154 return false; 2155 } 2156 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type || VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) { 2157 auto max_sb_range = limits_.maxStorageBufferRange; 2158 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_sb_range) { 2159 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00333"; 2160 std::stringstream error_str; 2161 error_str << "VkDescriptorBufferInfo range is " << buffer_info->range 2162 << " which is greater than this device's maxStorageBufferRange (" << max_sb_range << ")"; 2163 *error_msg = error_str.str(); 2164 return false; 2165 } else if (buffer_info->range == VK_WHOLE_SIZE && (buffer_node->createInfo.size - buffer_info->offset) > max_sb_range) { 2166 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00333"; 2167 std::stringstream error_str; 2168 error_str << "VkDescriptorBufferInfo range is VK_WHOLE_SIZE but effective range " 2169 << "(" << (buffer_node->createInfo.size - buffer_info->offset) << ") is greater than this device's " 2170 << "maxStorageBufferRange (" << max_sb_range << ")"; 2171 *error_msg = error_str.str(); 2172 return false; 2173 } 2174 } 2175 return true; 2176 } 2177 2178 // Verify that the contents of the update are ok, but don't perform actual update 2179 bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDescriptorSet *update, const uint32_t index, 2180 const char *func_name, std::string *error_code, 2181 std::string *error_msg) const { 2182 switch (update->descriptorType) { 2183 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { 2184 for (uint32_t di = 0; di < update->descriptorCount; ++di) { 2185 // Validate image 2186 auto image_view = update->pImageInfo[di].imageView; 2187 auto image_layout = update->pImageInfo[di].imageLayout; 2188 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, func_name, error_code, 2189 error_msg)) { 2190 std::stringstream error_str; 2191 error_str << "Attempted write update to combined image sampler descriptor failed due to: " 2192 << error_msg->c_str(); 2193 *error_msg = error_str.str(); 2194 return false; 2195 } 2196 if (device_data_->GetDeviceExtensions()->vk_khr_sampler_ycbcr_conversion) { 2197 ImageSamplerDescriptor *desc = (ImageSamplerDescriptor *)descriptors_[index].get(); 2198 if (desc->IsImmutableSampler()) { 2199 auto sampler_state = device_data_->GetSamplerState(desc->GetSampler()); 2200 auto iv_state = device_data_->GetImageViewState(image_view); 2201 if (iv_state && sampler_state) { 2202 if (iv_state->samplerConversion != sampler_state->samplerConversion) { 2203 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-01948"; 2204 std::stringstream error_str; 2205 error_str << "Attempted write update to combined image sampler and image view and sampler ycbcr " 2206 "conversions are not identical, sampler: " 2207 << desc->GetSampler() << " image view: " << iv_state->image_view << "."; 2208 *error_msg = error_str.str(); 2209 return false; 2210 } 2211 } 2212 } 2213 } 2214 } 2215 } 2216 // fall through 2217 case VK_DESCRIPTOR_TYPE_SAMPLER: { 2218 for (uint32_t di = 0; di < update->descriptorCount; ++di) { 2219 if (!descriptors_[index + di].get()->IsImmutableSampler()) { 2220 if (!ValidateSampler(update->pImageInfo[di].sampler, device_data_)) { 2221 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325"; 2222 std::stringstream error_str; 2223 error_str << "Attempted write update to sampler descriptor with invalid sampler: " 2224 << update->pImageInfo[di].sampler << "."; 2225 *error_msg = error_str.str(); 2226 return false; 2227 } 2228 } else { 2229 // TODO : Warn here 2230 } 2231 } 2232 break; 2233 } 2234 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 2235 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 2236 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: { 2237 for (uint32_t di = 0; di < update->descriptorCount; ++di) { 2238 auto image_view = update->pImageInfo[di].imageView; 2239 auto image_layout = update->pImageInfo[di].imageLayout; 2240 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, func_name, error_code, 2241 error_msg)) { 2242 std::stringstream error_str; 2243 error_str << "Attempted write update to image descriptor failed due to: " << error_msg->c_str(); 2244 *error_msg = error_str.str(); 2245 return false; 2246 } 2247 } 2248 break; 2249 } 2250 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 2251 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: { 2252 for (uint32_t di = 0; di < update->descriptorCount; ++di) { 2253 auto buffer_view = update->pTexelBufferView[di]; 2254 auto bv_state = device_data_->GetBufferViewState(buffer_view); 2255 if (!bv_state) { 2256 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00323"; 2257 std::stringstream error_str; 2258 error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: " << buffer_view; 2259 *error_msg = error_str.str(); 2260 return false; 2261 } 2262 auto buffer = bv_state->create_info.buffer; 2263 auto buffer_state = device_data_->GetBufferState(buffer); 2264 // Verify that buffer underlying the view hasn't been destroyed prematurely 2265 if (!buffer_state) { 2266 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00323"; 2267 std::stringstream error_str; 2268 error_str << "Attempted write update to texel buffer descriptor failed because underlying buffer (" << buffer 2269 << ") has been destroyed: " << error_msg->c_str(); 2270 *error_msg = error_str.str(); 2271 return false; 2272 } else if (!ValidateBufferUsage(buffer_state, update->descriptorType, error_code, error_msg)) { 2273 std::stringstream error_str; 2274 error_str << "Attempted write update to texel buffer descriptor failed due to: " << error_msg->c_str(); 2275 *error_msg = error_str.str(); 2276 return false; 2277 } 2278 } 2279 break; 2280 } 2281 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 2282 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 2283 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 2284 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: { 2285 for (uint32_t di = 0; di < update->descriptorCount; ++di) { 2286 if (!ValidateBufferUpdate(update->pBufferInfo + di, update->descriptorType, func_name, error_code, error_msg)) { 2287 std::stringstream error_str; 2288 error_str << "Attempted write update to buffer descriptor failed due to: " << error_msg->c_str(); 2289 *error_msg = error_str.str(); 2290 return false; 2291 } 2292 } 2293 break; 2294 } 2295 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: 2296 break; 2297 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: 2298 // XXX TODO 2299 break; 2300 default: 2301 assert(0); // We've already verified update type so should never get here 2302 break; 2303 } 2304 // All checks passed so update contents are good 2305 return true; 2306 } 2307 // Verify that the contents of the update are ok, but don't perform actual update 2308 bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescriptorSet *update, const DescriptorSet *src_set, 2309 VkDescriptorType type, uint32_t index, const char *func_name, 2310 std::string *error_code, std::string *error_msg) const { 2311 // Note : Repurposing some Write update error codes here as specific details aren't called out for copy updates like they are 2312 // for write updates 2313 switch (src_set->descriptors_[index]->descriptor_class) { 2314 case PlainSampler: { 2315 for (uint32_t di = 0; di < update->descriptorCount; ++di) { 2316 const auto src_desc = src_set->descriptors_[index + di].get(); 2317 if (!src_desc->updated) continue; 2318 if (!src_desc->IsImmutableSampler()) { 2319 auto update_sampler = static_cast<SamplerDescriptor *>(src_desc)->GetSampler(); 2320 if (!ValidateSampler(update_sampler, device_data_)) { 2321 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325"; 2322 std::stringstream error_str; 2323 error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << "."; 2324 *error_msg = error_str.str(); 2325 return false; 2326 } 2327 } else { 2328 // TODO : Warn here 2329 } 2330 } 2331 break; 2332 } 2333 case ImageSampler: { 2334 for (uint32_t di = 0; di < update->descriptorCount; ++di) { 2335 const auto src_desc = src_set->descriptors_[index + di].get(); 2336 if (!src_desc->updated) continue; 2337 auto img_samp_desc = static_cast<const ImageSamplerDescriptor *>(src_desc); 2338 // First validate sampler 2339 if (!img_samp_desc->IsImmutableSampler()) { 2340 auto update_sampler = img_samp_desc->GetSampler(); 2341 if (!ValidateSampler(update_sampler, device_data_)) { 2342 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325"; 2343 std::stringstream error_str; 2344 error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << "."; 2345 *error_msg = error_str.str(); 2346 return false; 2347 } 2348 } else { 2349 // TODO : Warn here 2350 } 2351 // Validate image 2352 auto image_view = img_samp_desc->GetImageView(); 2353 auto image_layout = img_samp_desc->GetImageLayout(); 2354 if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, func_name, error_code, error_msg)) { 2355 std::stringstream error_str; 2356 error_str << "Attempted copy update to combined image sampler descriptor failed due to: " << error_msg->c_str(); 2357 *error_msg = error_str.str(); 2358 return false; 2359 } 2360 } 2361 break; 2362 } 2363 case Image: { 2364 for (uint32_t di = 0; di < update->descriptorCount; ++di) { 2365 const auto src_desc = src_set->descriptors_[index + di].get(); 2366 if (!src_desc->updated) continue; 2367 auto img_desc = static_cast<const ImageDescriptor *>(src_desc); 2368 auto image_view = img_desc->GetImageView(); 2369 auto image_layout = img_desc->GetImageLayout(); 2370 if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, func_name, error_code, error_msg)) { 2371 std::stringstream error_str; 2372 error_str << "Attempted copy update to image descriptor failed due to: " << error_msg->c_str(); 2373 *error_msg = error_str.str(); 2374 return false; 2375 } 2376 } 2377 break; 2378 } 2379 case TexelBuffer: { 2380 for (uint32_t di = 0; di < update->descriptorCount; ++di) { 2381 const auto src_desc = src_set->descriptors_[index + di].get(); 2382 if (!src_desc->updated) continue; 2383 auto buffer_view = static_cast<TexelDescriptor *>(src_desc)->GetBufferView(); 2384 auto bv_state = device_data_->GetBufferViewState(buffer_view); 2385 if (!bv_state) { 2386 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00323"; 2387 std::stringstream error_str; 2388 error_str << "Attempted copy update to texel buffer descriptor with invalid buffer view: " << buffer_view; 2389 *error_msg = error_str.str(); 2390 return false; 2391 } 2392 auto buffer = bv_state->create_info.buffer; 2393 if (!ValidateBufferUsage(device_data_->GetBufferState(buffer), type, error_code, error_msg)) { 2394 std::stringstream error_str; 2395 error_str << "Attempted copy update to texel buffer descriptor failed due to: " << error_msg->c_str(); 2396 *error_msg = error_str.str(); 2397 return false; 2398 } 2399 } 2400 break; 2401 } 2402 case GeneralBuffer: { 2403 for (uint32_t di = 0; di < update->descriptorCount; ++di) { 2404 const auto src_desc = src_set->descriptors_[index + di].get(); 2405 if (!src_desc->updated) continue; 2406 auto buffer = static_cast<BufferDescriptor *>(src_desc)->GetBuffer(); 2407 if (!ValidateBufferUsage(device_data_->GetBufferState(buffer), type, error_code, error_msg)) { 2408 std::stringstream error_str; 2409 error_str << "Attempted copy update to buffer descriptor failed due to: " << error_msg->c_str(); 2410 *error_msg = error_str.str(); 2411 return false; 2412 } 2413 } 2414 break; 2415 } 2416 case InlineUniform: 2417 case AccelerationStructure: 2418 break; 2419 default: 2420 assert(0); // We've already verified update type so should never get here 2421 break; 2422 } 2423 // All checks passed so update contents are good 2424 return true; 2425 } 2426 // Update the common AllocateDescriptorSetsData 2427 void CoreChecks::UpdateAllocateDescriptorSetsData(const layer_data *dev_data, const VkDescriptorSetAllocateInfo *p_alloc_info, 2428 cvdescriptorset::AllocateDescriptorSetsData *ds_data) { 2429 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { 2430 auto layout = GetDescriptorSetLayout(dev_data, p_alloc_info->pSetLayouts[i]); 2431 if (layout) { 2432 ds_data->layout_nodes[i] = layout; 2433 // Count total descriptors required per type 2434 for (uint32_t j = 0; j < layout->GetBindingCount(); ++j) { 2435 const auto &binding_layout = layout->GetDescriptorSetLayoutBindingPtrFromIndex(j); 2436 uint32_t typeIndex = static_cast<uint32_t>(binding_layout->descriptorType); 2437 ds_data->required_descriptors_by_type[typeIndex] += binding_layout->descriptorCount; 2438 } 2439 } 2440 // Any unknown layouts will be flagged as errors during ValidateAllocateDescriptorSets() call 2441 } 2442 } 2443 // Verify that the state at allocate time is correct, but don't actually allocate the sets yet 2444 bool CoreChecks::ValidateAllocateDescriptorSets(const layer_data *dev_data, const VkDescriptorSetAllocateInfo *p_alloc_info, 2445 const cvdescriptorset::AllocateDescriptorSetsData *ds_data) { 2446 bool skip = false; 2447 auto pool_state = GetDescriptorPoolState(p_alloc_info->descriptorPool); 2448 2449 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { 2450 auto layout = GetDescriptorSetLayout(dev_data, p_alloc_info->pSetLayouts[i]); 2451 if (layout) { // nullptr layout indicates no valid layout handle for this device, validated/logged in object_tracker 2452 if (layout->IsPushDescriptor()) { 2453 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, 2454 HandleToUint64(p_alloc_info->pSetLayouts[i]), "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-00308", 2455 "Layout %s specified at pSetLayouts[%" PRIu32 2456 "] in vkAllocateDescriptorSets() was created with invalid flag %s set.", 2457 report_data->FormatHandle(p_alloc_info->pSetLayouts[i]).c_str(), i, 2458 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR"); 2459 } 2460 if (layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT && 2461 !(pool_state->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)) { 2462 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, 2463 0, "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-03044", 2464 "Descriptor set layout create flags and pool create flags mismatch for index (%d)", i); 2465 } 2466 } 2467 } 2468 if (!GetDeviceExtensions()->vk_khr_maintenance1) { 2469 // Track number of descriptorSets allowable in this pool 2470 if (pool_state->availableSets < p_alloc_info->descriptorSetCount) { 2471 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 2472 HandleToUint64(pool_state->pool), "VUID-VkDescriptorSetAllocateInfo-descriptorSetCount-00306", 2473 "Unable to allocate %u descriptorSets from pool %s" 2474 ". This pool only has %d descriptorSets remaining.", 2475 p_alloc_info->descriptorSetCount, report_data->FormatHandle(pool_state->pool).c_str(), 2476 pool_state->availableSets); 2477 } 2478 // Determine whether descriptor counts are satisfiable 2479 for (auto it = ds_data->required_descriptors_by_type.begin(); it != ds_data->required_descriptors_by_type.end(); ++it) { 2480 if (ds_data->required_descriptors_by_type.at(it->first) > pool_state->availableDescriptorTypeCount[it->first]) { 2481 skip |= log_msg( 2482 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 2483 HandleToUint64(pool_state->pool), "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307", 2484 "Unable to allocate %u descriptors of type %s from pool %s" 2485 ". This pool only has %d descriptors of this type remaining.", 2486 ds_data->required_descriptors_by_type.at(it->first), string_VkDescriptorType(VkDescriptorType(it->first)), 2487 report_data->FormatHandle(pool_state->pool).c_str(), pool_state->availableDescriptorTypeCount[it->first]); 2488 } 2489 } 2490 } 2491 2492 const auto *count_allocate_info = lvl_find_in_chain<VkDescriptorSetVariableDescriptorCountAllocateInfoEXT>(p_alloc_info->pNext); 2493 2494 if (count_allocate_info) { 2495 if (count_allocate_info->descriptorSetCount != 0 && 2496 count_allocate_info->descriptorSetCount != p_alloc_info->descriptorSetCount) { 2497 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, 0, 2498 "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-descriptorSetCount-03045", 2499 "VkDescriptorSetAllocateInfo::descriptorSetCount (%d) != " 2500 "VkDescriptorSetVariableDescriptorCountAllocateInfoEXT::descriptorSetCount (%d)", 2501 p_alloc_info->descriptorSetCount, count_allocate_info->descriptorSetCount); 2502 } 2503 if (count_allocate_info->descriptorSetCount == p_alloc_info->descriptorSetCount) { 2504 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { 2505 auto layout = GetDescriptorSetLayout(dev_data, p_alloc_info->pSetLayouts[i]); 2506 if (count_allocate_info->pDescriptorCounts[i] > layout->GetDescriptorCountFromBinding(layout->GetMaxBinding())) { 2507 skip |= log_msg( 2508 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, 0, 2509 "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-pSetLayouts-03046", 2510 "pDescriptorCounts[%d] = (%d), binding's descriptorCount = (%d)", i, 2511 count_allocate_info->pDescriptorCounts[i], layout->GetDescriptorCountFromBinding(layout->GetMaxBinding())); 2512 } 2513 } 2514 } 2515 } 2516 2517 return skip; 2518 } 2519 // Decrement allocated sets from the pool and insert new sets into set_map 2520 void CoreChecks::PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *p_alloc_info, 2521 const VkDescriptorSet *descriptor_sets, 2522 const cvdescriptorset::AllocateDescriptorSetsData *ds_data, 2523 std::unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_STATE *> *pool_map, 2524 std::unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> *set_map, 2525 layer_data *dev_data) { 2526 auto pool_state = (*pool_map)[p_alloc_info->descriptorPool]; 2527 // Account for sets and individual descriptors allocated from pool 2528 pool_state->availableSets -= p_alloc_info->descriptorSetCount; 2529 for (auto it = ds_data->required_descriptors_by_type.begin(); it != ds_data->required_descriptors_by_type.end(); ++it) { 2530 pool_state->availableDescriptorTypeCount[it->first] -= ds_data->required_descriptors_by_type.at(it->first); 2531 } 2532 2533 const auto *variable_count_info = lvl_find_in_chain<VkDescriptorSetVariableDescriptorCountAllocateInfoEXT>(p_alloc_info->pNext); 2534 bool variable_count_valid = variable_count_info && variable_count_info->descriptorSetCount == p_alloc_info->descriptorSetCount; 2535 2536 // Create tracking object for each descriptor set; insert into global map and the pool's set. 2537 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { 2538 uint32_t variable_count = variable_count_valid ? variable_count_info->pDescriptorCounts[i] : 0; 2539 2540 auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], p_alloc_info->descriptorPool, ds_data->layout_nodes[i], 2541 variable_count, this); 2542 2543 pool_state->sets.insert(new_ds); 2544 new_ds->in_use.store(0); 2545 (*set_map)[descriptor_sets[i]] = new_ds; 2546 } 2547 } 2548 2549 cvdescriptorset::PrefilterBindRequestMap::PrefilterBindRequestMap(cvdescriptorset::DescriptorSet &ds, const BindingReqMap &in_map, 2550 GLOBAL_CB_NODE *cb_state) 2551 : filtered_map_(), orig_map_(in_map) { 2552 if (ds.GetTotalDescriptorCount() > kManyDescriptors_) { 2553 filtered_map_.reset(new std::map<uint32_t, descriptor_req>()); 2554 ds.FilterAndTrackBindingReqs(cb_state, orig_map_, filtered_map_.get()); 2555 } 2556 } 2557 cvdescriptorset::PrefilterBindRequestMap::PrefilterBindRequestMap(cvdescriptorset::DescriptorSet &ds, const BindingReqMap &in_map, 2558 GLOBAL_CB_NODE *cb_state, PIPELINE_STATE *pipeline) 2559 : filtered_map_(), orig_map_(in_map) { 2560 if (ds.GetTotalDescriptorCount() > kManyDescriptors_) { 2561 filtered_map_.reset(new std::map<uint32_t, descriptor_req>()); 2562 ds.FilterAndTrackBindingReqs(cb_state, pipeline, orig_map_, filtered_map_.get()); 2563 } 2564 } 2565