blob: 22c18504084bbee7b888d43ded103ee2ec59d72b [file] [log] [blame]
sfricke-samsung691299b2021-01-01 20:48:48 -08001/* Copyright (c) 2015-2021 The Khronos Group Inc.
2 * Copyright (c) 2015-2021 Valve Corporation
3 * Copyright (c) 2015-2021 LunarG, Inc.
4 * Copyright (C) 2015-2021 Google Inc.
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06005 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Tobin Ehlis <tobine@google.com>
John Zulaufc483f442017-12-15 14:02:06 -070019 * John Zulauf <jzulauf@lunarg.com>
Jeremy Kniagere6827432020-04-01 09:05:56 -060020 * Jeremy Kniager <jeremyk@lunarg.com>
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060021 */
22
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -070023#include "chassis.h"
Mark Lobodzinski76d76662019-02-14 14:38:21 -070024#include "core_validation_error_enums.h"
25#include "core_validation.h"
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060026#include "descriptor_sets.h"
John Zulaufd47d0612018-02-16 13:00:34 -070027#include "hash_vk_types.h"
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060028#include "vk_enum_string_helper.h"
29#include "vk_safe_struct.h"
Jeff Bolzfdf96072018-04-10 14:32:18 -050030#include "vk_typemap_helper.h"
Tobin Ehlisc8266452017-04-07 12:20:30 -060031#include "buffer_validation.h"
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060032#include <sstream>
Mark Lobodzinski2eee5d82016-12-02 15:33:18 -070033#include <algorithm>
John Zulauff4c07882019-01-24 14:03:36 -070034#include <array>
John Zulauf1f8174b2018-02-16 12:58:37 -070035#include <memory>
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060036
Jeremy Gebben1fbebb82021-10-27 10:27:27 -060037static DESCRIPTOR_POOL_STATE::TypeCountMap GetMaxTypeCounts(const VkDescriptorPoolCreateInfo *create_info) {
38 DESCRIPTOR_POOL_STATE::TypeCountMap counts;
39 // Collect maximums per descriptor type.
40 for (uint32_t i = 0; i < create_info->poolSizeCount; ++i) {
41 const auto &pool_size = create_info->pPoolSizes[i];
42 uint32_t type = static_cast<uint32_t>(pool_size.type);
43 // Same descriptor types can appear several times
44 counts[type] += pool_size.descriptorCount;
45 }
46 return counts;
47}
48
49DESCRIPTOR_POOL_STATE::DESCRIPTOR_POOL_STATE(ValidationStateTracker *dev, const VkDescriptorPool pool,
50 const VkDescriptorPoolCreateInfo *pCreateInfo)
51 : BASE_NODE(pool, kVulkanObjectTypeDescriptorPool),
52 dev_data(dev),
53 maxSets(pCreateInfo->maxSets),
54 availableSets(pCreateInfo->maxSets),
55 createInfo(pCreateInfo),
56 maxDescriptorTypeCount(GetMaxTypeCounts(pCreateInfo)),
57 availableDescriptorTypeCount(maxDescriptorTypeCount) {}
58
59void DESCRIPTOR_POOL_STATE::Allocate(const VkDescriptorSetAllocateInfo *alloc_info, const VkDescriptorSet *descriptor_sets,
60 const cvdescriptorset::AllocateDescriptorSetsData *ds_data) {
61 // Account for sets and individual descriptors allocated from pool
62 availableSets -= alloc_info->descriptorSetCount;
63 for (auto it = ds_data->required_descriptors_by_type.begin(); it != ds_data->required_descriptors_by_type.end(); ++it) {
64 availableDescriptorTypeCount[it->first] -= ds_data->required_descriptors_by_type.at(it->first);
65 }
66
67 const auto *variable_count_info = LvlFindInChain<VkDescriptorSetVariableDescriptorCountAllocateInfo>(alloc_info->pNext);
68 bool variable_count_valid = variable_count_info && variable_count_info->descriptorSetCount == alloc_info->descriptorSetCount;
69
70 // Create tracking object for each descriptor set; insert into global map and the pool's set.
71 for (uint32_t i = 0; i < alloc_info->descriptorSetCount; i++) {
72 uint32_t variable_count = variable_count_valid ? variable_count_info->pDescriptorCounts[i] : 0;
73
74 auto new_ds = std::make_shared<cvdescriptorset::DescriptorSet>(descriptor_sets[i], this, ds_data->layout_nodes[i],
75 variable_count, dev_data);
76 sets.emplace(descriptor_sets[i], new_ds.get());
Jeremy Gebben082a9832021-10-28 13:40:11 -060077 dev_data->Add(std::move(new_ds));
Jeremy Gebben1fbebb82021-10-27 10:27:27 -060078 }
79}
80
81void DESCRIPTOR_POOL_STATE::Free(uint32_t count, const VkDescriptorSet *descriptor_sets) {
82 // Update available descriptor sets in pool
83 availableSets += count;
84
Jeremy Gebben082a9832021-10-28 13:40:11 -060085 // For each freed descriptor add its resources back into the pool as available and remove from pool and device data
Jeremy Gebben1fbebb82021-10-27 10:27:27 -060086 for (uint32_t i = 0; i < count; ++i) {
87 if (descriptor_sets[i] != VK_NULL_HANDLE) {
88 auto iter = sets.find(descriptor_sets[i]);
89 assert(iter != sets.end());
90 auto *set_state = iter->second;
91 uint32_t type_index = 0, descriptor_count = 0;
92 for (uint32_t j = 0; j < set_state->GetBindingCount(); ++j) {
93 type_index = static_cast<uint32_t>(set_state->GetTypeFromIndex(j));
94 descriptor_count = set_state->GetDescriptorCountFromIndex(j);
95 availableDescriptorTypeCount[type_index] += descriptor_count;
96 }
Jeremy Gebben082a9832021-10-28 13:40:11 -060097 dev_data->Destroy<cvdescriptorset::DescriptorSet>(iter->first);
Jeremy Gebben1fbebb82021-10-27 10:27:27 -060098 sets.erase(iter);
99 }
100 }
101}
102
103void DESCRIPTOR_POOL_STATE::Reset() {
104 // For every set off of this pool, clear it, remove from setMap, and free cvdescriptorset::DescriptorSet
105 for (auto entry : sets) {
Jeremy Gebben082a9832021-10-28 13:40:11 -0600106 dev_data->Destroy<cvdescriptorset::DescriptorSet>(entry.first);
Jeremy Gebben1fbebb82021-10-27 10:27:27 -0600107 }
108 sets.clear();
109 // Reset available count for each type and available sets for this pool
110 availableDescriptorTypeCount = maxDescriptorTypeCount;
111 availableSets = maxSets;
112}
113
114void DESCRIPTOR_POOL_STATE::Destroy() {
115 Reset();
116 BASE_NODE::Destroy();
117}
118
Jeff Bolzfdf96072018-04-10 14:32:18 -0500119// ExtendedBinding collects a VkDescriptorSetLayoutBinding and any extended
120// state that comes from a different array/structure so they can stay together
121// while being sorted by binding number.
122struct ExtendedBinding {
Mike Schuchardt2df08912020-12-15 16:28:09 -0800123 ExtendedBinding(const VkDescriptorSetLayoutBinding *l, VkDescriptorBindingFlags f) : layout_binding(l), binding_flags(f) {}
Jeff Bolzfdf96072018-04-10 14:32:18 -0500124
125 const VkDescriptorSetLayoutBinding *layout_binding;
Mike Schuchardt2df08912020-12-15 16:28:09 -0800126 VkDescriptorBindingFlags binding_flags;
Jeff Bolzfdf96072018-04-10 14:32:18 -0500127};
128
John Zulauf508d13a2018-01-05 15:10:34 -0700129struct BindingNumCmp {
Jeff Bolzfdf96072018-04-10 14:32:18 -0500130 bool operator()(const ExtendedBinding &a, const ExtendedBinding &b) const {
131 return a.layout_binding->binding < b.layout_binding->binding;
John Zulauf508d13a2018-01-05 15:10:34 -0700132 }
133};
134
John Zulauf613fd982019-06-04 15:14:41 -0600135using DescriptorSet = cvdescriptorset::DescriptorSet;
John Zulauf4a015c92019-06-04 09:50:05 -0600136using DescriptorSetLayout = cvdescriptorset::DescriptorSetLayout;
John Zulaufd47d0612018-02-16 13:00:34 -0700137using DescriptorSetLayoutDef = cvdescriptorset::DescriptorSetLayoutDef;
138using DescriptorSetLayoutId = cvdescriptorset::DescriptorSetLayoutId;
139
John Zulauf34ebf272018-02-16 13:08:47 -0700140// Canonical dictionary of DescriptorSetLayoutDef (without any handle/device specific information)
141cvdescriptorset::DescriptorSetLayoutDict descriptor_set_layout_dict;
John Zulaufd47d0612018-02-16 13:00:34 -0700142
Shannon McPhersonc06c33d2018-06-28 17:21:12 -0600143DescriptorSetLayoutId GetCanonicalId(const VkDescriptorSetLayoutCreateInfo *p_create_info) {
John Zulauf34ebf272018-02-16 13:08:47 -0700144 return descriptor_set_layout_dict.look_up(DescriptorSetLayoutDef(p_create_info));
John Zulaufd47d0612018-02-16 13:00:34 -0700145}
John Zulauf34ebf272018-02-16 13:08:47 -0700146
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600147// Construct DescriptorSetLayout instance from given create info
John Zulauf48a6a702017-12-22 17:14:54 -0700148// Proactively reserve and resize as possible, as the reallocation was visible in profiling
John Zulauf1f8174b2018-02-16 12:58:37 -0700149cvdescriptorset::DescriptorSetLayoutDef::DescriptorSetLayoutDef(const VkDescriptorSetLayoutCreateInfo *p_create_info)
150 : flags_(p_create_info->flags), binding_count_(0), descriptor_count_(0), dynamic_descriptor_count_(0) {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -0700151 const auto *flags_create_info = LvlFindInChain<VkDescriptorSetLayoutBindingFlagsCreateInfo>(p_create_info->pNext);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500152
sfricke-samsung0d00aed2021-03-08 23:31:17 -0800153 binding_type_stats_ = {0, 0};
Jeff Bolzfdf96072018-04-10 14:32:18 -0500154 std::set<ExtendedBinding, BindingNumCmp> sorted_bindings;
John Zulauf508d13a2018-01-05 15:10:34 -0700155 const uint32_t input_bindings_count = p_create_info->bindingCount;
156 // Sort the input bindings in binding number order, eliminating duplicates
157 for (uint32_t i = 0; i < input_bindings_count; i++) {
Mike Schuchardt2df08912020-12-15 16:28:09 -0800158 VkDescriptorBindingFlags flags = 0;
Jeff Bolzfdf96072018-04-10 14:32:18 -0500159 if (flags_create_info && flags_create_info->bindingCount == p_create_info->bindingCount) {
160 flags = flags_create_info->pBindingFlags[i];
161 }
Jeremy Gebbenfc6f8152021-03-18 16:58:55 -0600162 sorted_bindings.emplace(p_create_info->pBindings + i, flags);
John Zulaufb6d71202017-12-22 16:47:09 -0700163 }
164
ziga-lunargd67b5f52021-10-16 23:52:59 +0200165 const auto *mutable_descriptor_type_create_info = LvlFindInChain<VkMutableDescriptorTypeCreateInfoVALVE>(p_create_info->pNext);
166 if (mutable_descriptor_type_create_info) {
167 mutable_types_.resize(mutable_descriptor_type_create_info->mutableDescriptorTypeListCount);
168 for (uint32_t i = 0; i < mutable_descriptor_type_create_info->mutableDescriptorTypeListCount; ++i) {
169 const auto &list = mutable_descriptor_type_create_info->pMutableDescriptorTypeLists[i];
170 mutable_types_[i].reserve(list.descriptorTypeCount);
171 for (uint32_t j = 0; j < list.descriptorTypeCount; ++j) {
172 mutable_types_[i].push_back(list.pDescriptorTypes[j]);
173 }
ziga-lunarg2ab8c472021-10-27 22:54:02 +0200174 std::sort(mutable_types_[i].begin(), mutable_types_[i].end());
ziga-lunargd67b5f52021-10-16 23:52:59 +0200175 }
176 }
177
John Zulaufb6d71202017-12-22 16:47:09 -0700178 // Store the create info in the sorted order from above
John Zulauf508d13a2018-01-05 15:10:34 -0700179 uint32_t index = 0;
180 binding_count_ = static_cast<uint32_t>(sorted_bindings.size());
181 bindings_.reserve(binding_count_);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500182 binding_flags_.reserve(binding_count_);
John Zulauf508d13a2018-01-05 15:10:34 -0700183 binding_to_index_map_.reserve(binding_count_);
John Zulauf79f06582021-02-27 18:38:39 -0700184 for (const auto &input_binding : sorted_bindings) {
John Zulauf508d13a2018-01-05 15:10:34 -0700185 // Add to binding and map, s.t. it is robust to invalid duplication of binding_num
Jeff Bolzfdf96072018-04-10 14:32:18 -0500186 const auto binding_num = input_binding.layout_binding->binding;
John Zulauf508d13a2018-01-05 15:10:34 -0700187 binding_to_index_map_[binding_num] = index++;
Jeff Bolzfdf96072018-04-10 14:32:18 -0500188 bindings_.emplace_back(input_binding.layout_binding);
John Zulauf508d13a2018-01-05 15:10:34 -0700189 auto &binding_info = bindings_.back();
Jeff Bolzfdf96072018-04-10 14:32:18 -0500190 binding_flags_.emplace_back(input_binding.binding_flags);
John Zulauf508d13a2018-01-05 15:10:34 -0700191
John Zulaufb6d71202017-12-22 16:47:09 -0700192 descriptor_count_ += binding_info.descriptorCount;
193 if (binding_info.descriptorCount > 0) {
194 non_empty_bindings_.insert(binding_num);
Tobin Ehlis9637fb22016-12-12 15:59:34 -0700195 }
John Zulaufb6d71202017-12-22 16:47:09 -0700196
sfricke-samsung60f29ec2021-03-10 20:37:25 -0800197 if (IsDynamicDescriptor(binding_info.descriptorType)) {
sfricke-samsung0d00aed2021-03-08 23:31:17 -0800198 dynamic_descriptor_count_ += binding_info.descriptorCount;
199 }
200
201 // Get stats depending on descriptor type for caching later
sfricke-samsung60f29ec2021-03-10 20:37:25 -0800202 if (IsBufferDescriptor(binding_info.descriptorType)) {
203 if (IsDynamicDescriptor(binding_info.descriptorType)) {
204 binding_type_stats_.dynamic_buffer_count++;
205 } else {
206 binding_type_stats_.non_dynamic_buffer_count++;
207 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600208 }
209 }
Tobin Ehlis9637fb22016-12-12 15:59:34 -0700210 assert(bindings_.size() == binding_count_);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500211 assert(binding_flags_.size() == binding_count_);
Tobin Ehlis9637fb22016-12-12 15:59:34 -0700212 uint32_t global_index = 0;
John Zulauf7705bfc2019-06-10 09:52:04 -0600213 global_index_range_.reserve(binding_count_);
214 // Vector order is finalized so build vectors of descriptors and dynamic offsets by binding index
Tobin Ehlis9637fb22016-12-12 15:59:34 -0700215 for (uint32_t i = 0; i < binding_count_; ++i) {
John Zulaufc483f442017-12-15 14:02:06 -0700216 auto final_index = global_index + bindings_[i].descriptorCount;
John Zulauf7705bfc2019-06-10 09:52:04 -0600217 global_index_range_.emplace_back(global_index, final_index);
John Zulaufc483f442017-12-15 14:02:06 -0700218 global_index = final_index;
Tobin Ehlis9637fb22016-12-12 15:59:34 -0700219 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600220}
Tobin Ehlis154c2692016-10-25 09:36:53 -0600221
John Zulaufd47d0612018-02-16 13:00:34 -0700222size_t cvdescriptorset::DescriptorSetLayoutDef::hash() const {
223 hash_util::HashCombiner hc;
224 hc << flags_;
225 hc.Combine(bindings_);
John Zulauf223b69d2018-11-09 16:00:59 -0700226 hc.Combine(binding_flags_);
John Zulaufd47d0612018-02-16 13:00:34 -0700227 return hc.Value();
228}
229//
230
John Zulauf1f8174b2018-02-16 12:58:37 -0700231// Return valid index or "end" i.e. binding_count_;
232// The asserts in "Get" are reduced to the set where no valid answer(like null or 0) could be given
233// Common code for all binding lookups.
234uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetIndexFromBinding(uint32_t binding) const {
235 const auto &bi_itr = binding_to_index_map_.find(binding);
236 if (bi_itr != binding_to_index_map_.cend()) return bi_itr->second;
237 return GetBindingCount();
238}
239VkDescriptorSetLayoutBinding const *cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorSetLayoutBindingPtrFromIndex(
240 const uint32_t index) const {
241 if (index >= bindings_.size()) return nullptr;
242 return bindings_[index].ptr();
243}
244// Return descriptorCount for given index, 0 if index is unavailable
245uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorCountFromIndex(const uint32_t index) const {
246 if (index >= bindings_.size()) return 0;
247 return bindings_[index].descriptorCount;
248}
249// For the given index, return descriptorType
250VkDescriptorType cvdescriptorset::DescriptorSetLayoutDef::GetTypeFromIndex(const uint32_t index) const {
251 assert(index < bindings_.size());
252 if (index < bindings_.size()) return bindings_[index].descriptorType;
253 return VK_DESCRIPTOR_TYPE_MAX_ENUM;
254}
255// For the given index, return stageFlags
256VkShaderStageFlags cvdescriptorset::DescriptorSetLayoutDef::GetStageFlagsFromIndex(const uint32_t index) const {
257 assert(index < bindings_.size());
258 if (index < bindings_.size()) return bindings_[index].stageFlags;
259 return VkShaderStageFlags(0);
260}
Jeff Bolzfdf96072018-04-10 14:32:18 -0500261// Return binding flags for given index, 0 if index is unavailable
Mike Schuchardt2df08912020-12-15 16:28:09 -0800262VkDescriptorBindingFlags cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorBindingFlagsFromIndex(const uint32_t index) const {
Jeff Bolzfdf96072018-04-10 14:32:18 -0500263 if (index >= binding_flags_.size()) return 0;
264 return binding_flags_[index];
265}
John Zulauf1f8174b2018-02-16 12:58:37 -0700266
John Zulauf7705bfc2019-06-10 09:52:04 -0600267const cvdescriptorset::IndexRange &cvdescriptorset::DescriptorSetLayoutDef::GetGlobalIndexRangeFromIndex(uint32_t index) const {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700268 const static IndexRange k_invalid_range = {0xFFFFFFFF, 0xFFFFFFFF};
269 if (index >= binding_flags_.size()) return k_invalid_range;
John Zulauf7705bfc2019-06-10 09:52:04 -0600270 return global_index_range_[index];
John Zulauf1f8174b2018-02-16 12:58:37 -0700271}
272
John Zulauf7705bfc2019-06-10 09:52:04 -0600273// For the given binding, return the global index range (half open)
274// As start and end are often needed in pairs, get both with a single lookup.
John Zulauf1f8174b2018-02-16 12:58:37 -0700275const cvdescriptorset::IndexRange &cvdescriptorset::DescriptorSetLayoutDef::GetGlobalIndexRangeFromBinding(
276 const uint32_t binding) const {
John Zulauf7705bfc2019-06-10 09:52:04 -0600277 uint32_t index = GetIndexFromBinding(binding);
278 return GetGlobalIndexRangeFromIndex(index);
John Zulauf1f8174b2018-02-16 12:58:37 -0700279}
280
281// For given binding, return ptr to ImmutableSampler array
282VkSampler const *cvdescriptorset::DescriptorSetLayoutDef::GetImmutableSamplerPtrFromBinding(const uint32_t binding) const {
283 const auto &bi_itr = binding_to_index_map_.find(binding);
284 if (bi_itr != binding_to_index_map_.end()) {
285 return bindings_[bi_itr->second].pImmutableSamplers;
286 }
287 return nullptr;
288}
289// Move to next valid binding having a non-zero binding count
290uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetNextValidBinding(const uint32_t binding) const {
291 auto it = non_empty_bindings_.upper_bound(binding);
292 assert(it != non_empty_bindings_.cend());
293 if (it != non_empty_bindings_.cend()) return *it;
294 return GetMaxBinding() + 1;
295}
296// For given index, return ptr to ImmutableSampler array
297VkSampler const *cvdescriptorset::DescriptorSetLayoutDef::GetImmutableSamplerPtrFromIndex(const uint32_t index) const {
298 if (index < bindings_.size()) {
299 return bindings_[index].pImmutableSamplers;
300 }
301 return nullptr;
302}
John Zulauf9ce3b252019-06-06 15:20:22 -0600303
ziga-lunargd67b5f52021-10-16 23:52:59 +0200304bool cvdescriptorset::DescriptorSetLayoutDef::IsTypeMutable(const VkDescriptorType type, uint32_t binding) const {
305 if (binding < mutable_types_.size()) {
306 if (mutable_types_[binding].size() > 0) {
307 for (const auto mutable_type : mutable_types_[binding]) {
308 if (type == mutable_type) {
309 return true;
310 }
311 }
312 return false;
313 }
314 }
315 // If mutableDescriptorTypeListCount is zero or if VkMutableDescriptorTypeCreateInfoVALVE structure is not included in the pNext
316 // chain, the VkMutableDescriptorTypeListVALVE for each element is considered to be zero or NULL for each member.
317 return false;
318}
319
ziga-lunarg2ab8c472021-10-27 22:54:02 +0200320const std::vector<std::vector<VkDescriptorType>>& cvdescriptorset::DescriptorSetLayoutDef::GetMutableTypes() const {
321 return mutable_types_;
322}
323
ziga-lunarge5d28542021-10-24 21:14:25 +0200324const std::vector<VkDescriptorType> &cvdescriptorset::DescriptorSetLayoutDef::GetMutableTypes(uint32_t binding) const {
325 if (binding >= mutable_types_.size()) {
326 static const std::vector<VkDescriptorType> empty = {};
327 return empty;
328 }
329 return mutable_types_[binding];
330}
331
John Zulauf9ce3b252019-06-06 15:20:22 -0600332// If our layout is compatible with rh_ds_layout, return true.
333bool cvdescriptorset::DescriptorSetLayout::IsCompatible(DescriptorSetLayout const *rh_ds_layout) const {
334 bool compatible = (this == rh_ds_layout) || (GetLayoutDef() == rh_ds_layout->GetLayoutDef());
335 return compatible;
336}
John Zulauf1f8174b2018-02-16 12:58:37 -0700337
John Zulauff43695f2019-09-13 17:56:26 -0600338// TODO: Find a way to add smarts to the autogenerated version of this
339static std::string smart_string_VkShaderStageFlags(VkShaderStageFlags stage_flags) {
340 if (stage_flags == VK_SHADER_STAGE_ALL) {
341 return string_VkShaderStageFlagBits(VK_SHADER_STAGE_ALL);
342 }
343
344 return string_VkShaderStageFlags(stage_flags);
345}
346
347// If our layout is compatible with bound_dsl, return true,
348// else return false and fill in error_msg will description of what causes incompatibility
349bool cvdescriptorset::VerifySetLayoutCompatibility(const debug_report_data *report_data, DescriptorSetLayout const *layout_dsl,
350 DescriptorSetLayout const *bound_dsl, std::string *error_msg) {
351 // Short circuit the detailed check.
352 if (layout_dsl->IsCompatible(bound_dsl)) return true;
353
354 // Do a detailed compatibility check of this lhs def (referenced by layout_dsl), vs. the rhs (layout and def)
John Zulauf9ce3b252019-06-06 15:20:22 -0600355 // Should only be run if trivial accept has failed, and in that context should return false.
John Zulauff43695f2019-09-13 17:56:26 -0600356 VkDescriptorSetLayout layout_dsl_handle = layout_dsl->GetDescriptorSetLayout();
357 VkDescriptorSetLayout bound_dsl_handle = bound_dsl->GetDescriptorSetLayout();
358 DescriptorSetLayoutDef const *layout_ds_layout_def = layout_dsl->GetLayoutDef();
359 DescriptorSetLayoutDef const *bound_ds_layout_def = bound_dsl->GetLayoutDef();
John Zulauf9ce3b252019-06-06 15:20:22 -0600360
361 // Check descriptor counts
John Zulauff43695f2019-09-13 17:56:26 -0600362 const auto bound_total_count = bound_ds_layout_def->GetTotalDescriptorCount();
363 if (layout_ds_layout_def->GetTotalDescriptorCount() != bound_ds_layout_def->GetTotalDescriptorCount()) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700364 std::stringstream error_str;
John Zulauff43695f2019-09-13 17:56:26 -0600365 error_str << report_data->FormatHandle(layout_dsl_handle) << " from pipeline layout has "
366 << layout_ds_layout_def->GetTotalDescriptorCount() << " total descriptors, but "
367 << report_data->FormatHandle(bound_dsl_handle) << ", which is bound, has " << bound_total_count
368 << " total descriptors.";
John Zulauf1f8174b2018-02-16 12:58:37 -0700369 *error_msg = error_str.str();
370 return false; // trivial fail case
371 }
John Zulaufd47d0612018-02-16 13:00:34 -0700372
John Zulauf1f8174b2018-02-16 12:58:37 -0700373 // Descriptor counts match so need to go through bindings one-by-one
374 // and verify that type and stageFlags match
John Zulauff43695f2019-09-13 17:56:26 -0600375 for (const auto &layout_binding : layout_ds_layout_def->GetBindings()) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700376 // TODO : Do we also need to check immutable samplers?
John Zulauff43695f2019-09-13 17:56:26 -0600377 const auto bound_binding = bound_ds_layout_def->GetBindingInfoFromBinding(layout_binding.binding);
378 if (layout_binding.descriptorCount != bound_binding->descriptorCount) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700379 std::stringstream error_str;
John Zulauff43695f2019-09-13 17:56:26 -0600380 error_str << "Binding " << layout_binding.binding << " for " << report_data->FormatHandle(layout_dsl_handle)
381 << " from pipeline layout has a descriptorCount of " << layout_binding.descriptorCount << " but binding "
382 << layout_binding.binding << " for " << report_data->FormatHandle(bound_dsl_handle)
383 << ", which is bound, has a descriptorCount of " << bound_binding->descriptorCount;
John Zulauf1f8174b2018-02-16 12:58:37 -0700384 *error_msg = error_str.str();
385 return false;
John Zulauff43695f2019-09-13 17:56:26 -0600386 } else if (layout_binding.descriptorType != bound_binding->descriptorType) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700387 std::stringstream error_str;
John Zulauff43695f2019-09-13 17:56:26 -0600388 error_str << "Binding " << layout_binding.binding << " for " << report_data->FormatHandle(layout_dsl_handle)
389 << " from pipeline layout is type '" << string_VkDescriptorType(layout_binding.descriptorType)
390 << "' but binding " << layout_binding.binding << " for " << report_data->FormatHandle(bound_dsl_handle)
391 << ", which is bound, is type '" << string_VkDescriptorType(bound_binding->descriptorType) << "'";
John Zulauf1f8174b2018-02-16 12:58:37 -0700392 *error_msg = error_str.str();
393 return false;
John Zulauff43695f2019-09-13 17:56:26 -0600394 } else if (layout_binding.stageFlags != bound_binding->stageFlags) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700395 std::stringstream error_str;
John Zulauff43695f2019-09-13 17:56:26 -0600396 error_str << "Binding " << layout_binding.binding << " for " << report_data->FormatHandle(layout_dsl_handle)
397 << " from pipeline layout has stageFlags " << smart_string_VkShaderStageFlags(layout_binding.stageFlags)
398 << " but binding " << layout_binding.binding << " for " << report_data->FormatHandle(bound_dsl_handle)
399 << ", which is bound, has stageFlags " << smart_string_VkShaderStageFlags(bound_binding->stageFlags);
John Zulauf1f8174b2018-02-16 12:58:37 -0700400 *error_msg = error_str.str();
401 return false;
402 }
403 }
Tony-LunarG692b8b42019-09-30 16:07:26 -0600404
405 const auto &ds_layout_flags = layout_ds_layout_def->GetBindingFlags();
406 const auto &bound_layout_flags = bound_ds_layout_def->GetBindingFlags();
407 if (bound_layout_flags != ds_layout_flags) {
408 std::stringstream error_str;
409 assert(ds_layout_flags.size() == bound_layout_flags.size());
410 size_t i;
411 for (i = 0; i < ds_layout_flags.size(); i++) {
412 if (ds_layout_flags[i] != bound_layout_flags[i]) break;
413 }
414 error_str << report_data->FormatHandle(layout_dsl_handle)
415 << " from pipeline layout does not have the same binding flags at binding " << i << " ( "
416 << string_VkDescriptorBindingFlagsEXT(ds_layout_flags[i]) << " ) as "
417 << report_data->FormatHandle(bound_dsl_handle) << " ( "
418 << string_VkDescriptorBindingFlagsEXT(bound_layout_flags[i]) << " ), which is bound";
419 *error_msg = error_str.str();
420 return false;
421 }
422
John Zulauf9ce3b252019-06-06 15:20:22 -0600423 // No detailed check should succeed if the trivial check failed -- or the dictionary has failed somehow.
424 bool compatible = true;
425 assert(!compatible);
426 return compatible;
John Zulauf1f8174b2018-02-16 12:58:37 -0700427}
428
429bool cvdescriptorset::DescriptorSetLayoutDef::IsNextBindingConsistent(const uint32_t binding) const {
430 if (!binding_to_index_map_.count(binding + 1)) return false;
431 auto const &bi_itr = binding_to_index_map_.find(binding);
432 if (bi_itr != binding_to_index_map_.end()) {
433 const auto &next_bi_itr = binding_to_index_map_.find(binding + 1);
434 if (next_bi_itr != binding_to_index_map_.end()) {
435 auto type = bindings_[bi_itr->second].descriptorType;
436 auto stage_flags = bindings_[bi_itr->second].stageFlags;
437 auto immut_samp = bindings_[bi_itr->second].pImmutableSamplers ? true : false;
Jeff Bolzfdf96072018-04-10 14:32:18 -0500438 auto flags = binding_flags_[bi_itr->second];
John Zulauf1f8174b2018-02-16 12:58:37 -0700439 if ((type != bindings_[next_bi_itr->second].descriptorType) ||
440 (stage_flags != bindings_[next_bi_itr->second].stageFlags) ||
Jeff Bolzfdf96072018-04-10 14:32:18 -0500441 (immut_samp != (bindings_[next_bi_itr->second].pImmutableSamplers ? true : false)) ||
442 (flags != binding_flags_[next_bi_itr->second])) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700443 return false;
444 }
445 return true;
446 }
447 }
448 return false;
449}
John Zulauf1f8174b2018-02-16 12:58:37 -0700450
451// The DescriptorSetLayout stores the per handle data for a descriptor set layout, and references the common defintion for the
452// handle invariant portion
453cvdescriptorset::DescriptorSetLayout::DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info,
454 const VkDescriptorSetLayout layout)
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600455 : BASE_NODE(layout, kVulkanObjectTypeDescriptorSetLayout), layout_id_(GetCanonicalId(p_create_info)) {}
John Zulauf1f8174b2018-02-16 12:58:37 -0700456
Tobin Ehlis154c2692016-10-25 09:36:53 -0600457// Validate descriptor set layout create info
John Zulaufd9435c32019-06-05 15:55:36 -0600458bool cvdescriptorset::ValidateDescriptorSetLayoutCreateInfo(
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700459 const ValidationObject *val_obj, const VkDescriptorSetLayoutCreateInfo *create_info, const bool push_descriptor_ext,
Jeff Bolzfdf96072018-04-10 14:32:18 -0500460 const uint32_t max_push_descriptors, const bool descriptor_indexing_ext,
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700461 const VkPhysicalDeviceVulkan12Features *core12_features,
Jeff Bolze54ae892018-09-08 12:16:29 -0500462 const VkPhysicalDeviceInlineUniformBlockFeaturesEXT *inline_uniform_block_features,
ziga-lunarg637356a2021-07-19 12:36:34 +0200463 const VkPhysicalDeviceInlineUniformBlockPropertiesEXT *inline_uniform_block_props,
464 const VkPhysicalDeviceAccelerationStructureFeaturesKHR *acceleration_structure_features,
465 const DeviceExtensions *device_extensions) {
Tobin Ehlis154c2692016-10-25 09:36:53 -0600466 bool skip = false;
Jeremy Gebbencbf22862021-03-03 12:01:22 -0700467 layer_data::unordered_set<uint32_t> bindings;
John Zulauf0fdeab32018-01-23 11:27:35 -0700468 uint64_t total_descriptors = 0;
469
Mark Lobodzinski1f887d32020-12-30 15:31:33 -0700470 const auto *flags_create_info = LvlFindInChain<VkDescriptorSetLayoutBindingFlagsCreateInfo>(create_info->pNext);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500471
472 const bool push_descriptor_set = !!(create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR);
John Zulauf0fdeab32018-01-23 11:27:35 -0700473 if (push_descriptor_set && !push_descriptor_ext) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800474 skip |= val_obj->LogError(
475 val_obj->device, kVUID_Core_DrawState_ExtensionNotEnabled,
476 "vkCreateDescriptorSetLayout(): Attempted to use %s in %s but its required extension %s has not been enabled.\n",
477 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR", "VkDescriptorSetLayoutCreateInfo::flags",
478 VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
John Zulauf0fdeab32018-01-23 11:27:35 -0700479 }
480
Mike Schuchardt2df08912020-12-15 16:28:09 -0800481 const bool update_after_bind_set = !!(create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500482 if (update_after_bind_set && !descriptor_indexing_ext) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800483 skip |= val_obj->LogError(
484 val_obj->device, kVUID_Core_DrawState_ExtensionNotEnabled,
485 "vkCreateDescriptorSetLayout(): Attemped to use %s in %s but its required extension %s has not been enabled.\n",
486 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT", "VkDescriptorSetLayoutCreateInfo::flags",
487 VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500488 }
489
John Zulauf0fdeab32018-01-23 11:27:35 -0700490 auto valid_type = [push_descriptor_set](const VkDescriptorType type) {
491 return !push_descriptor_set ||
Dave Houlton142c4cb2018-10-17 15:04:41 -0600492 ((type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) && (type != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) &&
Jeff Bolze54ae892018-09-08 12:16:29 -0500493 (type != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT));
John Zulauf0fdeab32018-01-23 11:27:35 -0700494 };
495
Jeff Bolzfdf96072018-04-10 14:32:18 -0500496 uint32_t max_binding = 0;
497
ziga-lunarg185ef282021-07-19 13:13:28 +0200498 uint32_t update_after_bind = create_info->bindingCount;
499 uint32_t uniform_buffer_dynamic = create_info->bindingCount;
500 uint32_t storage_buffer_dynamic = create_info->bindingCount;
501
Tobin Ehlis154c2692016-10-25 09:36:53 -0600502 for (uint32_t i = 0; i < create_info->bindingCount; ++i) {
John Zulauf0fdeab32018-01-23 11:27:35 -0700503 const auto &binding_info = create_info->pBindings[i];
Jeff Bolzfdf96072018-04-10 14:32:18 -0500504 max_binding = std::max(max_binding, binding_info.binding);
505
John Zulauf0fdeab32018-01-23 11:27:35 -0700506 if (!bindings.insert(binding_info.binding).second) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700507 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-binding-00279",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800508 "vkCreateDescriptorSetLayout(): pBindings[%u] has duplicated binding number (%u).", i,
509 binding_info.binding);
Tobin Ehlis154c2692016-10-25 09:36:53 -0600510 }
John Zulauf0fdeab32018-01-23 11:27:35 -0700511 if (!valid_type(binding_info.descriptorType)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700512 skip |= val_obj->LogError(val_obj->device,
513 (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
514 ? "VUID-VkDescriptorSetLayoutCreateInfo-flags-02208"
515 : "VUID-VkDescriptorSetLayoutCreateInfo-flags-00280",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800516 "vkCreateDescriptorSetLayout(): pBindings[%u] has invalid type %s , for push descriptors.", i,
517 string_VkDescriptorType(binding_info.descriptorType));
John Zulauf0fdeab32018-01-23 11:27:35 -0700518 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500519
520 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
sfricke-samsungc1e27c32021-01-16 09:32:49 -0800521 if (!inline_uniform_block_features->inlineUniformBlock) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800522 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-04604",
523 "vkCreateDescriptorSetLayout(): pBindings[%u] is creating VkDescriptorSetLayout with "
524 "descriptor type VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT "
Jeremy Gebbenda6b48f2021-05-13 10:46:18 -0600525 "but the inlineUniformBlock feature is not enabled",
526 i);
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600527 } else {
528 if ((binding_info.descriptorCount % 4) != 0) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800529 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-02209",
530 "vkCreateDescriptorSetLayout(): pBindings[%u] has descriptorCount =(%" PRIu32
531 ") but must be a multiple of 4",
532 i, binding_info.descriptorCount);
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600533 }
534 if (binding_info.descriptorCount > inline_uniform_block_props->maxInlineUniformBlockSize) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700535 skip |=
536 val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-02210",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800537 "vkCreateDescriptorSetLayout(): pBindings[%u] has descriptorCount =(%" PRIu32
538 ") but must be less than or equal to maxInlineUniformBlockSize (%u)",
539 i, binding_info.descriptorCount, inline_uniform_block_props->maxInlineUniformBlockSize);
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600540 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500541 }
ziga-lunarg185ef282021-07-19 13:13:28 +0200542 } else if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
543 uniform_buffer_dynamic = i;
544 } else if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
545 storage_buffer_dynamic = i;
Jeff Bolze54ae892018-09-08 12:16:29 -0500546 }
547
Tony-LunarG7337b312020-04-15 16:40:25 -0600548 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
549 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
sfricke-samsung45996a42021-09-16 13:45:27 -0700550 binding_info.pImmutableSamplers && IsExtEnabled(device_extensions->vk_ext_custom_border_color)) {
Tony-LunarG7337b312020-04-15 16:40:25 -0600551 const CoreChecks *core_checks = reinterpret_cast<const CoreChecks *>(val_obj);
552 for (uint32_t j = 0; j < binding_info.descriptorCount; j++) {
Jeremy Gebbenb20a8242021-11-05 15:14:43 -0600553 const auto sampler_state = core_checks->Get<SAMPLER_STATE>(binding_info.pImmutableSamplers[j]);
Tony-LunarG7337b312020-04-15 16:40:25 -0600554 if (sampler_state && (sampler_state->createInfo.borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT ||
555 sampler_state->createInfo.borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT)) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800556 skip |= val_obj->LogError(
557 val_obj->device, "VUID-VkDescriptorSetLayoutBinding-pImmutableSamplers-04009",
Jeremy Gebbenda6b48f2021-05-13 10:46:18 -0600558 "vkCreateDescriptorSetLayout(): pBindings[%u].pImmutableSamplers[%u] has VkSampler %s"
sfricke-samsungbda4a852021-03-06 20:58:01 -0800559 " presented as immutable has a custom border color",
Jeremy Gebbenda6b48f2021-05-13 10:46:18 -0600560 i, j, val_obj->report_data->FormatHandle(binding_info.pImmutableSamplers[j]).c_str());
Tony-LunarG7337b312020-04-15 16:40:25 -0600561 }
562 }
563 }
564
ziga-lunarg6d770792021-07-19 11:27:18 +0200565 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE && binding_info.pImmutableSamplers != nullptr) {
566 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-04605",
567 "vkCreateDescriptorSetLayout(): pBindings[%u] has descriptorType "
568 "VK_DESCRIPTOR_TYPE_MUTABLE_VALVE but pImmutableSamplers is not NULL.",
569 i);
570 }
571
John Zulauf0fdeab32018-01-23 11:27:35 -0700572 total_descriptors += binding_info.descriptorCount;
Tobin Ehlis154c2692016-10-25 09:36:53 -0600573 }
John Zulauf0fdeab32018-01-23 11:27:35 -0700574
Jeff Bolzfdf96072018-04-10 14:32:18 -0500575 if (flags_create_info) {
576 if (flags_create_info->bindingCount != 0 && flags_create_info->bindingCount != create_info->bindingCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700577 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-bindingCount-03002",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800578 "vkCreateDescriptorSetLayout(): VkDescriptorSetLayoutCreateInfo::bindingCount (%d) != "
Mike Schuchardt2df08912020-12-15 16:28:09 -0800579 "VkDescriptorSetLayoutBindingFlagsCreateInfo::bindingCount (%d)",
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700580 create_info->bindingCount, flags_create_info->bindingCount);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500581 }
582
583 if (flags_create_info->bindingCount == create_info->bindingCount) {
584 for (uint32_t i = 0; i < create_info->bindingCount; ++i) {
585 const auto &binding_info = create_info->pBindings[i];
586
Mike Schuchardt2df08912020-12-15 16:28:09 -0800587 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT) {
ziga-lunarg185ef282021-07-19 13:13:28 +0200588 update_after_bind = i;
Jeff Bolzfdf96072018-04-10 14:32:18 -0500589 if (!update_after_bind_set) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700590 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-flags-03000",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800591 "vkCreateDescriptorSetLayout(): pBindings[%u] does not have "
592 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT.",
593 i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500594 }
595
596 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700597 !core12_features->descriptorBindingUniformBufferUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800598 skip |= val_obj->LogError(
599 val_obj->device,
600 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
601 "descriptorBindingUniformBufferUpdateAfterBind-03005",
602 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
603 "for %s since descriptorBindingUniformBufferUpdateAfterBind is not enabled.",
604 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500605 }
606 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
607 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
608 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700609 !core12_features->descriptorBindingSampledImageUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800610 skip |= val_obj->LogError(
611 val_obj->device,
612 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
613 "descriptorBindingSampledImageUpdateAfterBind-03006",
614 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
615 "for %s since descriptorBindingSampledImageUpdateAfterBind is not enabled.",
616 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500617 }
618 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700619 !core12_features->descriptorBindingStorageImageUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800620 skip |= val_obj->LogError(
621 val_obj->device,
622 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
623 "descriptorBindingStorageImageUpdateAfterBind-03007",
624 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
625 "for %s since descriptorBindingStorageImageUpdateAfterBind is not enabled.",
626 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500627 }
628 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700629 !core12_features->descriptorBindingStorageBufferUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800630 skip |= val_obj->LogError(
631 val_obj->device,
632 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
633 "descriptorBindingStorageBufferUpdateAfterBind-03008",
634 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
635 "for %s since descriptorBindingStorageBufferUpdateAfterBind is not enabled.",
636 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500637 }
638 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700639 !core12_features->descriptorBindingUniformTexelBufferUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800640 skip |= val_obj->LogError(
641 val_obj->device,
642 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
643 "descriptorBindingUniformTexelBufferUpdateAfterBind-03009",
644 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
645 "for %s since descriptorBindingUniformTexelBufferUpdateAfterBind is not enabled.",
646 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500647 }
648 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700649 !core12_features->descriptorBindingStorageTexelBufferUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800650 skip |= val_obj->LogError(
651 val_obj->device,
652 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
653 "descriptorBindingStorageTexelBufferUpdateAfterBind-03010",
654 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
655 "for %s since descriptorBindingStorageTexelBufferUpdateAfterBind is not enabled.",
656 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500657 }
658 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ||
659 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
660 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700661 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-None-03011",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800662 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have "
663 "VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT for %s.",
664 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500665 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500666
667 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT &&
668 !inline_uniform_block_features->descriptorBindingInlineUniformBlockUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800669 skip |= val_obj->LogError(
670 val_obj->device,
671 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
672 "descriptorBindingInlineUniformBlockUpdateAfterBind-02211",
673 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
674 "for %s since descriptorBindingInlineUniformBlockUpdateAfterBind is not enabled.",
675 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolze54ae892018-09-08 12:16:29 -0500676 }
ziga-lunarg637356a2021-07-19 12:36:34 +0200677 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR ||
678 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV) &&
679 !acceleration_structure_features->descriptorBindingAccelerationStructureUpdateAfterBind) {
680 skip |= val_obj->LogError(val_obj->device,
681 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
682 "descriptorBindingAccelerationStructureUpdateAfterBind-03570",
683 "vkCreateDescriptorSetLayout(): pBindings[%" PRIu32
684 "] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
685 "for %s if "
686 "VkPhysicalDeviceAccelerationStructureFeaturesKHR::"
687 "descriptorBindingAccelerationStructureUpdateAfterBind is not enabled.",
688 i, string_VkDescriptorType(binding_info.descriptorType));
689 }
Jeff Bolzfdf96072018-04-10 14:32:18 -0500690 }
691
Mike Schuchardt2df08912020-12-15 16:28:09 -0800692 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT) {
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700693 if (!core12_features->descriptorBindingUpdateUnusedWhilePending) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700694 skip |= val_obj->LogError(
695 val_obj->device,
Mike Schuchardt65847d92019-12-20 13:50:47 -0800696 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingUpdateUnusedWhilePending-03012",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800697 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have "
698 "VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT for %s since "
699 "descriptorBindingUpdateUnusedWhilePending is not enabled.",
700 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500701 }
702 }
703
Mike Schuchardt2df08912020-12-15 16:28:09 -0800704 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT) {
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700705 if (!core12_features->descriptorBindingPartiallyBound) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700706 skip |= val_obj->LogError(
707 val_obj->device,
708 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingPartiallyBound-03013",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800709 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT for "
710 "%s since descriptorBindingPartiallyBound is not enabled.",
711 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500712 }
713 }
714
Mike Schuchardt2df08912020-12-15 16:28:09 -0800715 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT) {
Jeff Bolzfdf96072018-04-10 14:32:18 -0500716 if (binding_info.binding != max_binding) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800717 skip |= val_obj->LogError(
718 val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03004",
719 "vkCreateDescriptorSetLayout(): pBindings[%u] has VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT "
720 "but %u is the largest value of all the bindings.",
721 i, binding_info.binding);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500722 }
723
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700724 if (!core12_features->descriptorBindingVariableDescriptorCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700725 skip |= val_obj->LogError(
726 val_obj->device,
Mike Schuchardt65847d92019-12-20 13:50:47 -0800727 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingVariableDescriptorCount-03014",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800728 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have "
729 "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT for %s since "
730 "descriptorBindingVariableDescriptorCount is not enabled.",
731 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500732 }
sfricke-samsung4ba7d6e2021-03-06 20:56:35 -0800733 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
734 (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700735 skip |= val_obj->LogError(val_obj->device,
736 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03015",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800737 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have "
738 "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT for %s.",
739 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500740 }
741 }
742
743 if (push_descriptor_set &&
744 (flags_create_info->pBindingFlags[i] &
Mike Schuchardt2df08912020-12-15 16:28:09 -0800745 (VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT |
746 VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT))) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800747 skip |= val_obj->LogError(
748 val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-flags-03003",
749 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT, "
750 "VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, or "
751 "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT for with "
752 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR.",
753 i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500754 }
755 }
756 }
757 }
758
ziga-lunarg185ef282021-07-19 13:13:28 +0200759 if (update_after_bind < create_info->bindingCount) {
760 if (uniform_buffer_dynamic < create_info->bindingCount) {
761 skip |=
762 val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-descriptorType-03001",
763 "vkCreateDescriptorSetLayout(): binding (%" PRIi32
764 ") has VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
765 "flag, but binding (%" PRIi32 ") has descriptor type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC.",
766 update_after_bind, uniform_buffer_dynamic);
767 }
768 if (storage_buffer_dynamic < create_info->bindingCount) {
769 skip |=
770 val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-descriptorType-03001",
771 "vkCreateDescriptorSetLayout(): binding (%" PRIi32
772 ") has VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
773 "flag, but binding (%" PRIi32 ") has descriptor type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC.",
774 update_after_bind, storage_buffer_dynamic);
775 }
776 }
777
John Zulauf0fdeab32018-01-23 11:27:35 -0700778 if ((push_descriptor_set) && (total_descriptors > max_push_descriptors)) {
779 const char *undefined = push_descriptor_ext ? "" : " -- undefined";
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700780 skip |= val_obj->LogError(
781 val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-flags-00281",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800782 "vkCreateDescriptorSetLayout(): for push descriptor, total descriptor count in layout (%" PRIu64
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700783 ") must not be greater than VkPhysicalDevicePushDescriptorPropertiesKHR::maxPushDescriptors (%" PRIu32 "%s).",
784 total_descriptors, max_push_descriptors, undefined);
John Zulauf0fdeab32018-01-23 11:27:35 -0700785 }
786
Tobin Ehlis154c2692016-10-25 09:36:53 -0600787 return skip;
788}
789
Mark Lobodzinskie12b6e32020-06-29 11:44:15 -0600790void cvdescriptorset::AllocateDescriptorSetsData::Init(uint32_t count) {
791 layout_nodes.resize(count);
Mark Lobodzinskie12b6e32020-06-29 11:44:15 -0600792}
Tobin Ehlis68d0adf2016-06-01 11:33:50 -0600793
Jeff Bolz41a1ced2019-10-11 11:40:49 -0500794cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, DESCRIPTOR_POOL_STATE *pool_state,
Jeff Bolzfdf96072018-04-10 14:32:18 -0500795 const std::shared_ptr<DescriptorSetLayout const> &layout, uint32_t variable_count,
John Zulaufd2c3dae2019-12-12 11:02:17 -0700796 const cvdescriptorset::DescriptorSet::StateTracker *state_data)
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -0600797 : BASE_NODE(set, kVulkanObjectTypeDescriptorSet),
798 some_update_(false),
Jeff Bolz41a1ced2019-10-11 11:40:49 -0500799 pool_state_(pool_state),
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700800 layout_(layout),
John Zulaufd2c3dae2019-12-12 11:02:17 -0700801 state_data_(state_data),
Jeff Bolzdd4cfa12019-08-11 20:57:51 -0500802 variable_count_(variable_count),
803 change_count_(0) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600804 if (pool_state_) {
805 pool_state_->AddParent(this);
806 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600807 // Foreach binding, create default descriptors of given type
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700808 descriptors_.reserve(layout_->GetTotalDescriptorCount());
809 descriptor_store_.resize(layout_->GetTotalDescriptorCount());
John Zulaufe4850d42019-12-30 16:10:55 -0700810 auto free_descriptor = descriptor_store_.data();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700811 for (uint32_t i = 0; i < layout_->GetBindingCount(); ++i) {
812 auto type = layout_->GetTypeFromIndex(i);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600813 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700814 case VK_DESCRIPTOR_TYPE_SAMPLER: {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700815 auto immut_sampler = layout_->GetImmutableSamplerPtrFromIndex(i);
816 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
Tobin Ehlis082c7512017-05-08 11:24:57 -0600817 if (immut_sampler) {
John Zulaufe4850d42019-12-30 16:10:55 -0700818 descriptors_.emplace_back(new ((free_descriptor++)->Sampler())
819 SamplerDescriptor(state_data, immut_sampler + di));
Tobin Ehlis082c7512017-05-08 11:24:57 -0600820 some_update_ = true; // Immutable samplers are updated at creation
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700821 } else {
John Zulaufe4850d42019-12-30 16:10:55 -0700822 descriptors_.emplace_back(new ((free_descriptor++)->Sampler()) SamplerDescriptor(state_data, nullptr));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700823 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600824 descriptors_.back()->AddParent(this);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700825 }
826 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600827 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700828 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700829 auto immut = layout_->GetImmutableSamplerPtrFromIndex(i);
830 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
Tobin Ehlis082c7512017-05-08 11:24:57 -0600831 if (immut) {
John Zulaufe4850d42019-12-30 16:10:55 -0700832 descriptors_.emplace_back(new ((free_descriptor++)->ImageSampler())
833 ImageSamplerDescriptor(state_data, immut + di));
Tobin Ehlis082c7512017-05-08 11:24:57 -0600834 some_update_ = true; // Immutable samplers are updated at creation
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700835 } else {
John Zulaufe4850d42019-12-30 16:10:55 -0700836 descriptors_.emplace_back(new ((free_descriptor++)->ImageSampler())
837 ImageSamplerDescriptor(state_data, nullptr));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700838 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600839 descriptors_.back()->AddParent(this);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700840 }
841 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600842 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700843 // ImageDescriptors
844 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
845 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
846 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700847 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700848 descriptors_.emplace_back(new ((free_descriptor++)->Image()) ImageDescriptor(type));
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600849 descriptors_.back()->AddParent(this);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700850 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700851 break;
852 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
853 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700854 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700855 descriptors_.emplace_back(new ((free_descriptor++)->Texel()) TexelDescriptor(type));
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600856 descriptors_.back()->AddParent(this);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700857 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700858 break;
sfricke-samsung4ca35652021-03-05 02:22:10 -0800859 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
860 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
861 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700862 descriptors_.emplace_back(new ((free_descriptor++)->Buffer()) BufferDescriptor(type));
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600863 descriptors_.back()->AddParent(this);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700864 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700865 break;
Jeff Bolze54ae892018-09-08 12:16:29 -0500866 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700867 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700868 descriptors_.emplace_back(new ((free_descriptor++)->InlineUniform()) InlineUniformDescriptor(type));
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600869 descriptors_.back()->AddParent(this);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700870 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500871 break;
Eric Werness30127fd2018-10-31 21:01:03 -0700872 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
sourav parmarcd5fb182020-07-17 12:58:44 -0700873 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700874 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700875 descriptors_.emplace_back(new ((free_descriptor++)->AccelerationStructure())
876 AccelerationStructureDescriptor(type));
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600877 descriptors_.back()->AddParent(this);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700878 }
Jeff Bolzfbe51582018-09-13 10:01:35 -0500879 break;
Tony-LunarGf563b362021-03-18 16:13:18 -0600880 case VK_DESCRIPTOR_TYPE_MUTABLE_VALVE:
881 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
ziga-lunarge5d28542021-10-24 21:14:25 +0200882 descriptors_.emplace_back(new ((free_descriptor++)->Mutable()) MutableDescriptor());
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600883 descriptors_.back()->AddParent(this);
Tony-LunarGf563b362021-03-18 16:13:18 -0600884 }
885 break;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700886 default:
sfricke-samsung60f29ec2021-03-10 20:37:25 -0800887 if (IsDynamicDescriptor(type) && IsBufferDescriptor(type)) {
888 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
889 dynamic_offset_idx_to_descriptor_list_.push_back(descriptors_.size());
890 descriptors_.emplace_back(new ((free_descriptor++)->Buffer()) BufferDescriptor(type));
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600891 descriptors_.back()->AddParent(this);
sfricke-samsung60f29ec2021-03-10 20:37:25 -0800892 }
893 } else {
894 assert(0); // Bad descriptor type specified
895 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700896 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600897 }
898 }
899}
Tobin Ehlis56a30942016-05-19 08:00:00 -0600900
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600901void cvdescriptorset::DescriptorSet::Destroy() {
902 if (pool_state_) {
903 pool_state_->RemoveParent(this);
904 }
905 for (auto &desc: descriptors_) {
906 desc->RemoveParent(this);
907 }
908 BASE_NODE::Destroy();
909}
Chris Forbes57989132016-07-26 17:06:10 +1200910
Jeremy Gebben90ce4162021-08-25 14:23:07 -0600911static std::string StringDescriptorReqViewType(DescriptorReqFlags req) {
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700912 std::string result("");
Mark Lobodzinski29f451a2020-02-10 16:15:30 -0700913 for (unsigned i = 0; i <= VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; i++) {
Chris Forbes57989132016-07-26 17:06:10 +1200914 if (req & (1 << i)) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700915 if (result.size()) result += ", ";
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700916 result += string_VkImageViewType(VkImageViewType(i));
Chris Forbes57989132016-07-26 17:06:10 +1200917 }
918 }
919
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700920 if (!result.size()) result = "(none)";
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700921
922 return result;
Chris Forbes57989132016-07-26 17:06:10 +1200923}
924
Jeremy Gebben90ce4162021-08-25 14:23:07 -0600925static char const *StringDescriptorReqComponentType(DescriptorReqFlags req) {
Chris Forbesda01e8d2018-08-27 15:36:57 -0700926 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_SINT) return "SINT";
927 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_UINT) return "UINT";
928 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT) return "FLOAT";
929 return "(none)";
930}
931
Jeff Bolz6cede832019-08-09 23:30:39 -0500932unsigned DescriptorRequirementsBitsFromFormat(VkFormat fmt) {
sfricke-samsunge3086292021-11-18 23:02:35 -0800933 if (FormatIsSINT(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_SINT;
934 if (FormatIsUINT(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_UINT;
sfricke-samsunged028b02021-09-06 23:14:51 -0700935 // Formats such as VK_FORMAT_D16_UNORM_S8_UINT are both
Chris Forbesda01e8d2018-08-27 15:36:57 -0700936 if (FormatIsDepthAndStencil(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT | DESCRIPTOR_REQ_COMPONENT_TYPE_UINT;
937 if (fmt == VK_FORMAT_UNDEFINED) return 0;
938 // everything else -- UNORM/SNORM/FLOAT/USCALED/SSCALED is all float in the shader.
939 return DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT;
940}
941
Tobin Ehlis3066db62016-08-22 08:12:23 -0600942// Validate that the state of this set is appropriate for the given bindings and dynamic_offsets at Draw time
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600943// This includes validating that all descriptors in the given bindings are updated,
944// that any update buffers are valid, and that any dynamic offsets are within the bounds of their buffers.
945// Return true if state is acceptable, or false and write an error message into error string
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600946bool CoreChecks::ValidateDrawState(const DescriptorSet *descriptor_set, const BindingReqMap &bindings,
947 const std::vector<uint32_t> &dynamic_offsets, const CMD_BUFFER_STATE *cb_node,
Niels Möller1f945f62021-07-12 15:06:02 +0200948 const std::vector<IMAGE_VIEW_STATE *> *attachments, const std::vector<SUBPASS_INFO> *subpasses,
locke-lunargfc78e932020-11-19 17:06:24 -0700949 const char *caller, const DrawDispatchVuid &vuids) const {
Jeremy Gebben37ed31e2021-04-23 12:12:10 -0600950 layer_data::optional<layer_data::unordered_map<VkImageView, VkImageLayout>> checked_layouts;
Karl Schultz2171f932021-03-19 10:47:01 -0600951 if (descriptor_set->GetTotalDescriptorCount() > cvdescriptorset::PrefilterBindRequestMap::kManyDescriptors_) {
952 checked_layouts.emplace();
953 }
Tony-LunarGace473a2020-05-06 12:48:04 -0600954 bool result = false;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600955 VkFramebuffer framebuffer = cb_node->activeFramebuffer ? cb_node->activeFramebuffer->framebuffer() : VK_NULL_HANDLE;
John Zulauf79f06582021-02-27 18:38:39 -0700956 for (const auto &binding_pair : bindings) {
957 const auto binding = binding_pair.first;
John Zulauf382e1912019-06-10 15:27:44 -0600958 DescriptorSetLayout::ConstBindingIterator binding_it(descriptor_set->GetLayout().get(), binding);
959 if (binding_it.AtEnd()) { // End at construction is the condition for an invalid binding.
Tony-LunarGace473a2020-05-06 12:48:04 -0600960 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600961 result |= LogError(set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -0600962 "%s encountered the following validation error at %s time: Attempting to "
963 "validate DrawState for binding #%u which is an invalid binding for this descriptor set.",
964 report_data->FormatHandle(set).c_str(), caller, binding);
965 return result;
Tobin Ehlis58c59582016-06-21 12:34:33 -0600966 }
Jeff Bolz6cede832019-08-09 23:30:39 -0500967
968 if (binding_it.GetDescriptorBindingFlags() &
Mike Schuchardt2df08912020-12-15 16:28:09 -0800969 (VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT)) {
Jeff Bolz6cede832019-08-09 23:30:39 -0500970 // Can't validate the descriptor because it may not have been updated,
971 // or the view could have been destroyed
972 continue;
973 }
John Zulauf81dd1f12021-01-26 16:49:16 -0700974 // // This is a record time only path
975 const bool record_time_validate = true;
locke-lunargfc78e932020-11-19 17:06:24 -0700976 result |= ValidateDescriptorSetBindingData(cb_node, descriptor_set, dynamic_offsets, binding_pair, framebuffer, attachments,
Karl Schultz2171f932021-03-19 10:47:01 -0600977 subpasses, record_time_validate, caller, vuids, checked_layouts);
unknown3087a642019-09-26 17:21:05 -0600978 }
Tony-LunarGace473a2020-05-06 12:48:04 -0600979 return result;
unknown3087a642019-09-26 17:21:05 -0600980}
Jeff Bolz6cede832019-08-09 23:30:39 -0500981
locke-lunargb8be8222020-10-20 00:34:37 -0600982bool CoreChecks::ValidateDescriptorSetBindingData(const CMD_BUFFER_STATE *cb_node, const DescriptorSet *descriptor_set,
983 const std::vector<uint32_t> &dynamic_offsets,
John Zulauf79f06582021-02-27 18:38:39 -0700984 const std::pair<const uint32_t, DescriptorRequirement> &binding_info,
Mark Lobodzinski85ebd402020-12-03 12:56:07 -0700985 VkFramebuffer framebuffer, const std::vector<IMAGE_VIEW_STATE *> *attachments,
Niels Möller1f945f62021-07-12 15:06:02 +0200986 const std::vector<SUBPASS_INFO> *subpasses, bool record_time_validate,
Karl Schultz2171f932021-03-19 10:47:01 -0600987 const char *caller, const DrawDispatchVuid &vuids,
Jeremy Gebben37ed31e2021-04-23 12:12:10 -0600988 layer_data::optional<layer_data::unordered_map<VkImageView, VkImageLayout>> &checked_layouts) const {
unknown3087a642019-09-26 17:21:05 -0600989 using DescriptorClass = cvdescriptorset::DescriptorClass;
990 using BufferDescriptor = cvdescriptorset::BufferDescriptor;
991 using ImageDescriptor = cvdescriptorset::ImageDescriptor;
992 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
993 using SamplerDescriptor = cvdescriptorset::SamplerDescriptor;
994 using TexelDescriptor = cvdescriptorset::TexelDescriptor;
Jeff Bolz95176d02020-04-01 00:36:16 -0500995 using AccelerationStructureDescriptor = cvdescriptorset::AccelerationStructureDescriptor;
locke-lunarg36045992020-08-20 16:54:37 -0600996 const auto binding = binding_info.first;
Jeremy Gebbene151b6b2021-04-09 18:03:06 -0600997 bool skip = false;
unknown3087a642019-09-26 17:21:05 -0600998 DescriptorSetLayout::ConstBindingIterator binding_it(descriptor_set->GetLayout().get(), binding);
999 {
John Zulauf382e1912019-06-10 15:27:44 -06001000 // Copy the range, the end range is subject to update based on variable length descriptor arrays.
1001 cvdescriptorset::IndexRange index_range = binding_it.GetGlobalIndexRange();
Chris Forbes1f7f3ca2017-05-08 13:54:50 -07001002 auto array_idx = 0; // Track array idx if we're dealing with array descriptors
Jeff Bolzfdf96072018-04-10 14:32:18 -05001003
John Zulauf382e1912019-06-10 15:27:44 -06001004 if (binding_it.IsVariableDescriptorCount()) {
Jeff Bolzfdf96072018-04-10 14:32:18 -05001005 // Only validate the first N descriptors if it uses variable_count
John Zulauf382e1912019-06-10 15:27:44 -06001006 index_range.end = index_range.start + descriptor_set->GetVariableDescriptorCount();
Jeff Bolzfdf96072018-04-10 14:32:18 -05001007 }
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001008 for (uint32_t i = index_range.start; !skip && i < index_range.end; ++i, ++array_idx) {
Lockeb994adf2019-03-29 23:52:31 -06001009 uint32_t index = i - index_range.start;
John Zulauf382e1912019-06-10 15:27:44 -06001010 const auto *descriptor = descriptor_set->GetDescriptorFromGlobalIndex(i);
Jeremy Gebben550ebbd2021-03-11 05:04:52 -07001011 const auto descriptor_class = descriptor->GetClass();
Lockeb994adf2019-03-29 23:52:31 -06001012
Jeremy Gebben550ebbd2021-03-11 05:04:52 -07001013 if (descriptor_class == DescriptorClass::InlineUniform) {
Jeff Bolz6cede832019-08-09 23:30:39 -05001014 // Can't validate the descriptor because it may not have been updated.
Jeff Bolzfdf96072018-04-10 14:32:18 -05001015 continue;
John Zulauf382e1912019-06-10 15:27:44 -06001016 } else if (!descriptor->updated) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001017 auto set = descriptor_set->GetSet();
sfricke-samsungbda4a852021-03-06 20:58:01 -08001018 return LogError(
1019 set, vuids.descriptor_valid,
1020 "Descriptor set %s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
1021 " index %" PRIu32
1022 " is being used in draw but has never been updated via vkUpdateDescriptorSets() or a similar call.",
1023 report_data->FormatHandle(set).c_str(), caller, binding, index);
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001024 }
1025 switch (descriptor_class) {
1026 case DescriptorClass::GeneralBuffer: {
1027 const auto *buffer_desc = static_cast<const BufferDescriptor *>(descriptor);
1028 skip =
1029 ValidateGeneralBufferDescriptor(caller, vuids, cb_node, descriptor_set, *buffer_desc, binding_info, index);
1030 } break;
1031 case DescriptorClass::ImageSampler: {
1032 const auto *image_sampler_desc = static_cast<const ImageSamplerDescriptor *>(descriptor);
1033 skip = ValidateImageDescriptor(caller, vuids, cb_node, descriptor_set, *image_sampler_desc, binding_info, index,
1034 record_time_validate, attachments, subpasses, framebuffer, binding_it.GetType(),
1035 checked_layouts);
1036 if (!skip) {
1037 skip = ValidateSamplerDescriptor(caller, vuids, cb_node, descriptor_set, binding_info, index,
1038 image_sampler_desc->GetSampler(), image_sampler_desc->IsImmutableSampler(),
1039 image_sampler_desc->GetSamplerState());
Karl Schultz76d16a42020-11-11 05:05:33 -07001040 }
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001041 } break;
1042 case DescriptorClass::Image: {
1043 const auto *image_desc = static_cast<const ImageDescriptor *>(descriptor);
1044 skip = ValidateImageDescriptor(caller, vuids, cb_node, descriptor_set, *image_desc, binding_info, index,
1045 record_time_validate, attachments, subpasses, framebuffer, binding_it.GetType(),
1046 checked_layouts);
1047 } break;
1048 case DescriptorClass::PlainSampler: {
1049 const auto *sampler_desc = static_cast<const SamplerDescriptor *>(descriptor);
1050 skip = ValidateSamplerDescriptor(caller, vuids, cb_node, descriptor_set, binding_info, index,
1051 sampler_desc->GetSampler(), sampler_desc->IsImmutableSampler(),
1052 sampler_desc->GetSamplerState());
1053 } break;
1054 case DescriptorClass::TexelBuffer: {
1055 const auto *texel_desc = static_cast<const TexelDescriptor *>(descriptor);
1056 skip = ValidateTexelDescriptor(caller, vuids, cb_node, descriptor_set, *texel_desc, binding_info, index);
1057 } break;
1058 case DescriptorClass::AccelerationStructure: {
1059 const auto *accel_desc = static_cast<const AccelerationStructureDescriptor *>(descriptor);
1060 skip = ValidateAccelerationDescriptor(caller, vuids, cb_node, descriptor_set, *accel_desc, binding_info, index);
1061 } break;
1062 default:
1063 break;
1064 }
1065 }
1066 }
1067 return skip;
1068}
locke-lunarg36045992020-08-20 16:54:37 -06001069
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001070bool CoreChecks::ValidateGeneralBufferDescriptor(const char *caller, const DrawDispatchVuid &vuids, const CMD_BUFFER_STATE *cb_node,
1071 const cvdescriptorset::DescriptorSet *descriptor_set,
1072 const cvdescriptorset::BufferDescriptor &descriptor,
1073 const std::pair<const uint32_t, DescriptorRequirement> &binding_info,
1074 uint32_t index) const {
1075 // Verify that buffers are valid
1076 auto buffer = descriptor.GetBuffer();
1077 auto buffer_node = descriptor.GetBufferState();
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001078 if ((!buffer_node && !enabled_features.robustness2_features.nullDescriptor) || (buffer_node && buffer_node->Destroyed())) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001079 auto set = descriptor_set->GetSet();
1080 return LogError(set, vuids.descriptor_valid,
1081 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1082 "binding #%" PRIu32 " index %" PRIu32 " is using buffer %s that is invalid or has been destroyed.",
1083 report_data->FormatHandle(set).c_str(), caller, binding_info.first, index,
1084 report_data->FormatHandle(buffer).c_str());
1085 }
1086 if (buffer) {
1087 if (buffer_node && !buffer_node->sparse) {
Jeremy Gebben6fbf8242021-06-21 09:14:46 -06001088 for (const auto &item: buffer_node->GetBoundMemory()) {
1089 auto &binding = item.second;
1090 if (binding.mem_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001091 auto set = descriptor_set->GetSet();
1092 return LogError(set, vuids.descriptor_valid,
1093 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1094 "binding #%" PRIu32 " index %" PRIu32 " is uses buffer %s that references invalid memory %s.",
1095 report_data->FormatHandle(set).c_str(), caller, binding_info.first, index,
Jeremy Gebben6fbf8242021-06-21 09:14:46 -06001096 report_data->FormatHandle(buffer).c_str(),
1097 report_data->FormatHandle(binding.mem_state->mem()).c_str());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001098 }
1099 }
1100 }
1101 if (enabled_features.core11.protectedMemory == VK_TRUE) {
1102 if (ValidateProtectedBuffer(cb_node, buffer_node, caller, vuids.unprotected_command_buffer,
1103 "Buffer is in a descriptorSet")) {
1104 return true;
1105 }
1106 if (binding_info.second.is_writable &&
1107 ValidateUnprotectedBuffer(cb_node, buffer_node, caller, vuids.protected_command_buffer,
1108 "Buffer is in a descriptorSet")) {
1109 return true;
1110 }
1111 }
1112 }
1113 return false;
1114}
Chris Forbes1f7f3ca2017-05-08 13:54:50 -07001115
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001116bool CoreChecks::ValidateImageDescriptor(const char *caller, const DrawDispatchVuid &vuids, const CMD_BUFFER_STATE *cb_node,
1117 const cvdescriptorset::DescriptorSet *descriptor_set,
1118 const cvdescriptorset::ImageDescriptor &image_descriptor,
1119 const std::pair<const uint32_t, DescriptorRequirement> &binding_info, uint32_t index,
1120 bool record_time_validate, const std::vector<IMAGE_VIEW_STATE *> *attachments,
Niels Möller1f945f62021-07-12 15:06:02 +02001121 const std::vector<SUBPASS_INFO> *subpasses, VkFramebuffer framebuffer,
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001122 VkDescriptorType descriptor_type,
Jeremy Gebben37ed31e2021-04-23 12:12:10 -06001123 layer_data::optional<layer_data::unordered_map<VkImageView, VkImageLayout>> &checked_layouts) const {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001124 std::vector<const SAMPLER_STATE *> sampler_states;
1125 VkImageView image_view = image_descriptor.GetImageView();
1126 const IMAGE_VIEW_STATE *image_view_state = image_descriptor.GetImageViewState();
1127 VkImageLayout image_layout = image_descriptor.GetImageLayout();
1128 const auto binding = binding_info.first;
1129 const auto reqs = binding_info.second.reqs;
Karl Schultz76d16a42020-11-11 05:05:33 -07001130
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001131 if (image_descriptor.GetClass() == cvdescriptorset::DescriptorClass::ImageSampler) {
1132 sampler_states.emplace_back(
1133 static_cast<const cvdescriptorset::ImageSamplerDescriptor &>(image_descriptor).GetSamplerState());
1134 } else {
1135 if (binding_info.second.samplers_used_by_image.size() > index) {
Jeremy Gebben856b8c62021-12-01 15:20:07 -07001136 for (const auto &desc_index : binding_info.second.samplers_used_by_image[index]) {
1137 const auto *desc = descriptor_set->GetDescriptorFromBinding(desc_index.sampler_slot.binding, desc_index.sampler_index);
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001138 // NOTE: This check _shouldn't_ be necessary due to the checks made in IsSpecificDescriptorType in
1139 // shader_validation.cpp. However, without this check some traces still crash.
Jeremy Gebben856b8c62021-12-01 15:20:07 -07001140 if (desc && (desc->GetClass() == cvdescriptorset::DescriptorClass::PlainSampler)) {
1141 const auto *sampler_state = static_cast<const cvdescriptorset::SamplerDescriptor *>(desc)->GetSamplerState();
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001142 if (sampler_state) sampler_states.emplace_back(sampler_state);
1143 }
1144 }
1145 }
1146 }
locke-lunarg4e1e4632020-10-26 01:52:19 -06001147
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001148 if ((!image_view_state && !enabled_features.robustness2_features.nullDescriptor) ||
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001149 (image_view_state && image_view_state->Destroyed())) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001150 // Image view must have been destroyed since initial update. Could potentially flag the descriptor
1151 // as "invalid" (updated = false) at DestroyImageView() time and detect this error at bind time
Jeff Bolz165818a2020-05-08 11:19:03 -05001152
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001153 auto set = descriptor_set->GetSet();
1154 return LogError(set, vuids.descriptor_valid,
1155 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1156 "binding #%" PRIu32 " index %" PRIu32 " is using imageView %s that is invalid or has been destroyed.",
1157 report_data->FormatHandle(set).c_str(), caller, binding, index,
1158 report_data->FormatHandle(image_view).c_str());
1159 }
1160 if (image_view) {
1161 const auto &image_view_ci = image_view_state->create_info;
1162 const auto *image_state = image_view_state->image_state.get();
Jeff Bolz165818a2020-05-08 11:19:03 -05001163
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001164 if (reqs & DESCRIPTOR_REQ_ALL_VIEW_TYPE_BITS) {
1165 if (~reqs & (1 << image_view_ci.viewType)) {
1166 auto set = descriptor_set->GetSet();
1167 return LogError(set, vuids.descriptor_valid,
1168 "Descriptor set %s encountered the following validation error at %s time: Descriptor "
1169 "in binding #%" PRIu32 " index %" PRIu32 " requires an image view of type %s but got %s.",
sfricke-samsungbda4a852021-03-06 20:58:01 -08001170 report_data->FormatHandle(set).c_str(), caller, binding, index,
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001171 StringDescriptorReqViewType(reqs).c_str(), string_VkImageViewType(image_view_ci.viewType));
1172 }
locke-lunarg25b6c352020-08-06 17:44:18 -06001173
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001174 if (!(reqs & image_view_state->descriptor_format_bits)) {
1175 // bad component type
1176 auto set = descriptor_set->GetSet();
1177 return LogError(set, vuids.descriptor_valid,
1178 "Descriptor set %s encountered the following validation error at %s time: "
1179 "Descriptor in binding "
1180 "#%" PRIu32 " index %" PRIu32 " requires %s component type, but bound descriptor format is %s.",
1181 report_data->FormatHandle(set).c_str(), caller, binding, index,
1182 StringDescriptorReqComponentType(reqs), string_VkFormat(image_view_ci.format));
1183 }
1184 }
locke-lunarg540b2252020-08-03 13:23:36 -06001185
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001186 // NOTE: Submit time validation of UPDATE_AFTER_BIND image layout is not possible with the
1187 // image layout tracking as currently implemented, so only record_time_validation is done
1188 if (!disabled[image_layout_validation] && record_time_validate) {
1189 // Verify Image Layout
1190 // No "invalid layout" VUID required for this call, since the optimal_layout parameter is UNDEFINED.
1191 // The caller provides a checked_layouts map when there are a large number of layouts to check,
1192 // making it worthwhile to keep track of verified layouts and not recheck them.
1193 bool already_validated = false;
1194 if (checked_layouts) {
1195 auto search = checked_layouts->find(image_view);
1196 if (search != checked_layouts->end() && search->second == image_layout) {
1197 already_validated = true;
1198 }
1199 }
1200 if (!already_validated) {
1201 bool hit_error = false;
1202 VerifyImageLayout(cb_node, image_state, image_view_state->normalized_subresource_range,
1203 image_view_ci.subresourceRange.aspectMask, image_layout, VK_IMAGE_LAYOUT_UNDEFINED, caller,
1204 kVUIDUndefined, "VUID-VkDescriptorImageInfo-imageLayout-00344", &hit_error);
1205 if (hit_error) {
1206 auto set = descriptor_set->GetSet();
1207 return LogError(set, vuids.descriptor_valid,
1208 "Descriptor set %s encountered the following validation error at %s time: Image layout "
1209 "specified "
1210 "at vkUpdateDescriptorSet* or vkCmdPushDescriptorSet* time "
1211 "doesn't match actual image layout at time descriptor is used. See previous error callback for "
1212 "specific details.",
1213 report_data->FormatHandle(set).c_str(), caller);
1214 }
1215 if (checked_layouts) {
1216 checked_layouts->emplace(image_view, image_layout);
1217 }
1218 }
1219 }
locke-lunarg540b2252020-08-03 13:23:36 -06001220
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001221 // Verify Sample counts
1222 if ((reqs & DESCRIPTOR_REQ_SINGLE_SAMPLE) && image_view_state->samples != VK_SAMPLE_COUNT_1_BIT) {
1223 auto set = descriptor_set->GetSet();
1224 return LogError(set, vuids.descriptor_valid,
1225 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1226 "binding #%" PRIu32 " index %" PRIu32 " requires bound image to have VK_SAMPLE_COUNT_1_BIT but got %s.",
1227 report_data->FormatHandle(set).c_str(), caller, binding, index,
1228 string_VkSampleCountFlagBits(image_view_state->samples));
1229 }
1230 if ((reqs & DESCRIPTOR_REQ_MULTI_SAMPLE) && image_view_state->samples == VK_SAMPLE_COUNT_1_BIT) {
1231 auto set = descriptor_set->GetSet();
1232 return LogError(set, vuids.descriptor_valid,
1233 "Descriptor set %s encountered the following validation error at %s time: Descriptor "
1234 "in binding #%" PRIu32 " index %" PRIu32
1235 " requires bound image to have multiple samples, but got VK_SAMPLE_COUNT_1_BIT.",
1236 report_data->FormatHandle(set).c_str(), caller, binding, index);
1237 }
locke-lunarg36045992020-08-20 16:54:37 -06001238
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001239 // Verify VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
1240 if ((reqs & DESCRIPTOR_REQ_VIEW_ATOMIC_OPERATION) && (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) &&
1241 !(image_view_state->format_features & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)) {
1242 auto set = descriptor_set->GetSet();
1243 LogObjectList objlist(set);
1244 objlist.add(image_view);
1245 return LogError(objlist, vuids.imageview_atomic,
1246 "Descriptor set %s encountered the following validation error at %s time: Descriptor "
1247 "in binding #%" PRIu32 " index %" PRIu32
1248 ", %s, format %s, doesn't "
1249 "contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT.",
1250 report_data->FormatHandle(set).c_str(), caller, binding, index,
1251 report_data->FormatHandle(image_view).c_str(), string_VkFormat(image_view_ci.format));
1252 }
locke-lunarg654a9052020-10-13 16:28:42 -06001253
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001254 // Verify if attachments are used in DescriptorSet
Niels Möller1f945f62021-07-12 15:06:02 +02001255 if (attachments && attachments->size() > 0 && subpasses && (descriptor_type != VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
Jeremy Gebbenb4d17012021-07-08 13:18:15 -06001256 bool ds_aspect = (image_view_state->normalized_subresource_range.aspectMask &
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001257 (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
1258 ? true
1259 : false;
1260 uint32_t att_index = 0;
1261 for (const auto &view_state : *attachments) {
Niels Möller1f945f62021-07-12 15:06:02 +02001262 const SUBPASS_INFO& subpass = (*subpasses)[att_index];
1263 if (!subpass.used || !view_state || view_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001264 continue;
1265 }
Ricardo Garciafe2b7682021-07-30 10:44:57 +02001266 if (ds_aspect && (subpass.usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ||
1267 subpass.usage == VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001268 if ((image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ||
1269 image_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
1270 image_layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL) &&
Niels Möller1f945f62021-07-12 15:06:02 +02001271 (subpass.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ||
1272 subpass.layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
1273 subpass.layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL)) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001274 continue;
Chris Forbes1f7f3ca2017-05-08 13:54:50 -07001275 }
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001276 if ((image_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL &&
Niels Möller1f945f62021-07-12 15:06:02 +02001277 subpass.layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL) ||
1278 (subpass.layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL &&
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001279 image_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)) {
1280 continue;
1281 }
1282 }
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001283 if (view_state->image_view() == image_view) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001284 auto set = descriptor_set->GetSet();
1285 LogObjectList objlist(set);
1286 objlist.add(image_view);
1287 objlist.add(framebuffer);
1288 return LogError(objlist, vuids.image_subresources,
1289 "Descriptor set %s encountered the following validation error at %s time: %s is used in "
1290 "Descriptor in binding #%" PRIu32 " index %" PRIu32 " and %s attachment # %" PRIu32 ".",
1291 report_data->FormatHandle(set).c_str(), caller, report_data->FormatHandle(image_view).c_str(),
1292 binding, index, report_data->FormatHandle(framebuffer).c_str(), att_index);
1293 } else {
1294 if (image_view_state->OverlapSubresource(*view_state)) {
Karl Schultz76d16a42020-11-11 05:05:33 -07001295 auto set = descriptor_set->GetSet();
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001296 LogObjectList objlist(set);
1297 objlist.add(image_view);
1298 objlist.add(framebuffer);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001299 objlist.add(view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001300 return LogError(
1301 objlist, vuids.image_subresources,
1302 "Descriptor set %s encountered the following validation error at %s time: "
1303 "Image subresources of %s in "
1304 "Descriptor in binding #%" PRIu32 " index %" PRIu32 " and %s in %s attachment # %" PRIu32 " overlap.",
1305 report_data->FormatHandle(set).c_str(), caller, report_data->FormatHandle(image_view).c_str(), binding,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001306 index, report_data->FormatHandle(view_state->image_view()).c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001307 report_data->FormatHandle(framebuffer).c_str(), att_index);
Karl Schultz76d16a42020-11-11 05:05:33 -07001308 }
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001309 }
1310 ++att_index;
1311 }
1312 if (enabled_features.core11.protectedMemory == VK_TRUE) {
1313 if (ValidateProtectedImage(cb_node, image_view_state->image_state.get(), caller, vuids.unprotected_command_buffer,
1314 "Image is in a descriptorSet")) {
1315 return true;
1316 }
1317 if (binding_info.second.is_writable &&
1318 ValidateUnprotectedImage(cb_node, image_view_state->image_state.get(), caller, vuids.protected_command_buffer,
1319 "Image is in a descriptorSet")) {
1320 return true;
1321 }
1322 }
1323 }
Chris Forbese92dd1d2019-01-21 15:58:57 -08001324
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001325 for (const auto *sampler_state : sampler_states) {
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001326 if (!sampler_state || sampler_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001327 continue;
1328 }
locke-lunarg25b6c352020-08-06 17:44:18 -06001329
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001330 // TODO: Validate 04015 for DescriptorClass::PlainSampler
1331 if ((sampler_state->createInfo.borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT ||
1332 sampler_state->createInfo.borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT) &&
1333 (sampler_state->customCreateInfo.format == VK_FORMAT_UNDEFINED)) {
1334 if (image_view_state->create_info.format == VK_FORMAT_B4G4R4A4_UNORM_PACK16 ||
1335 image_view_state->create_info.format == VK_FORMAT_B5G6R5_UNORM_PACK16 ||
1336 image_view_state->create_info.format == VK_FORMAT_B5G5R5A1_UNORM_PACK16) {
1337 auto set = descriptor_set->GetSet();
1338 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001339 objlist.add(sampler_state->sampler());
1340 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001341 return LogError(objlist, "VUID-VkSamplerCustomBorderColorCreateInfoEXT-format-04015",
1342 "Descriptor set %s encountered the following validation error at %s time: Sampler %s in "
1343 "binding #%" PRIu32 " index %" PRIu32
1344 " has a custom border color with format = VK_FORMAT_UNDEFINED and is used to "
1345 "sample an image view %s with format %s",
1346 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001347 report_data->FormatHandle(sampler_state->sampler()).c_str(), binding, index,
1348 report_data->FormatHandle(image_view_state->image_view()).c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001349 string_VkFormat(image_view_state->create_info.format));
1350 }
1351 }
1352 VkFilter sampler_mag_filter = sampler_state->createInfo.magFilter;
1353 VkFilter sampler_min_filter = sampler_state->createInfo.minFilter;
1354 VkBool32 sampler_compare_enable = sampler_state->createInfo.compareEnable;
1355 if ((sampler_mag_filter == VK_FILTER_LINEAR || sampler_min_filter == VK_FILTER_LINEAR) &&
1356 (sampler_compare_enable == VK_FALSE) &&
1357 !(image_view_state->format_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
1358 auto set = descriptor_set->GetSet();
1359 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001360 objlist.add(sampler_state->sampler());
1361 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001362 return LogError(objlist, vuids.linear_sampler,
1363 "Descriptor set %s encountered the following validation error at %s time: Sampler "
1364 "(%s) is set to use VK_FILTER_LINEAR with "
Tony-LunarG81195df2021-12-02 15:01:58 -07001365 "compareEnable is set to VK_FALSE, but image view's (%s) format (%s) does not "
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001366 "contain VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT in its format features.",
1367 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001368 report_data->FormatHandle(sampler_state->sampler()).c_str(),
1369 report_data->FormatHandle(image_view_state->image_view()).c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001370 string_VkFormat(image_view_state->create_info.format));
1371 }
1372 if (sampler_mag_filter == VK_FILTER_CUBIC_EXT || sampler_min_filter == VK_FILTER_CUBIC_EXT) {
1373 if (!(image_view_state->format_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) {
1374 auto set = descriptor_set->GetSet();
1375 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001376 objlist.add(sampler_state->sampler());
1377 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001378 return LogError(objlist, vuids.cubic_sampler,
1379 "Descriptor set %s encountered the following validation error at %s time: "
1380 "Sampler (%s) is set to use VK_FILTER_CUBIC_EXT, then "
1381 "image view's (%s) format (%s) MUST contain "
1382 "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT in its format features.",
1383 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001384 report_data->FormatHandle(sampler_state->sampler()).c_str(),
1385 report_data->FormatHandle(image_view_state->image_view()).c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001386 string_VkFormat(image_view_state->create_info.format));
1387 }
1388
1389 if (IsExtEnabled(device_extensions.vk_ext_filter_cubic)) {
1390 const auto reduction_mode_info =
1391 LvlFindInChain<VkSamplerReductionModeCreateInfo>(sampler_state->createInfo.pNext);
1392 if (reduction_mode_info &&
1393 (reduction_mode_info->reductionMode == VK_SAMPLER_REDUCTION_MODE_MIN ||
1394 reduction_mode_info->reductionMode == VK_SAMPLER_REDUCTION_MODE_MAX) &&
1395 !image_view_state->filter_cubic_props.filterCubicMinmax) {
1396 auto set = descriptor_set->GetSet();
1397 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001398 objlist.add(sampler_state->sampler());
1399 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001400 return LogError(objlist, vuids.filter_cubic_min_max,
1401 "Descriptor set %s encountered the following validation error at %s time: "
1402 "Sampler (%s) is set to use VK_FILTER_CUBIC_EXT & %s, "
1403 "but image view (%s) doesn't support filterCubicMinmax.",
1404 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001405 report_data->FormatHandle(sampler_state->sampler()).c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001406 string_VkSamplerReductionMode(reduction_mode_info->reductionMode),
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001407 report_data->FormatHandle(image_view_state->image_view()).c_str());
Chris Forbese92dd1d2019-01-21 15:58:57 -08001408 }
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001409
1410 if (!image_view_state->filter_cubic_props.filterCubic) {
1411 auto set = descriptor_set->GetSet();
1412 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001413 objlist.add(sampler_state->sampler());
1414 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001415 return LogError(objlist, vuids.filter_cubic,
1416 "Descriptor set %s encountered the following validation error at %s time: "
1417 "Sampler (%s) is set to use VK_FILTER_CUBIC_EXT, "
1418 "but image view (%s) doesn't support filterCubic.",
1419 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001420 report_data->FormatHandle(sampler_state->sampler()).c_str(),
1421 report_data->FormatHandle(image_view_state->image_view()).c_str());
Jeff Bolz95176d02020-04-01 00:36:16 -05001422 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001423 }
locke-lunarg4e1e4632020-10-26 01:52:19 -06001424
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001425 if (IsExtEnabled(device_extensions.vk_img_filter_cubic)) {
Clemens Kern5a42ea62021-09-29 16:30:23 +02001426 if (image_view_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_3D ||
1427 image_view_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
1428 image_view_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001429 auto set = descriptor_set->GetSet();
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001430 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001431 objlist.add(sampler_state->sampler());
1432 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001433 return LogError(objlist, vuids.img_filter_cubic,
1434 "Descriptor set %s encountered the following validation error at %s time: Sampler "
1435 "(%s)is set to use VK_FILTER_CUBIC_EXT while the VK_IMG_filter_cubic extension "
1436 "is enabled, but image view (%s) has an invalid imageViewType (%s).",
1437 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001438 report_data->FormatHandle(sampler_state->sampler()).c_str(),
1439 report_data->FormatHandle(image_view_state->image_view()).c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001440 string_VkImageViewType(image_view_state->create_info.viewType));
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001441 }
1442 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001443 }
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001444
1445 if ((image_state->createInfo.flags & VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV) &&
1446 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ||
1447 sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ||
1448 sampler_state->createInfo.addressModeW != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)) {
1449 std::string address_mode_letter =
1450 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1451 ? "U"
1452 : (sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE) ? "V" : "W";
1453 VkSamplerAddressMode address_mode =
1454 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1455 ? sampler_state->createInfo.addressModeU
1456 : (sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1457 ? sampler_state->createInfo.addressModeV
1458 : sampler_state->createInfo.addressModeW;
1459 auto set = descriptor_set->GetSet();
1460 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001461 objlist.add(sampler_state->sampler());
1462 objlist.add(image_state->image());
1463 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001464 return LogError(objlist, vuids.corner_sampled_address_mode,
1465 "Descriptor set %s encountered the following validation error at %s time: Image "
1466 "(%s) in image view (%s) is created with flag "
1467 "VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV and can only be sampled using "
1468 "VK_SAMPLER_ADDRESS_MODE_CLAMP_EDGE, but sampler (%s) has "
1469 "createInfo.addressMode%s set to %s.",
1470 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001471 report_data->FormatHandle(image_state->image()).c_str(),
1472 report_data->FormatHandle(image_view_state->image_view()).c_str(),
1473 report_data->FormatHandle(sampler_state->sampler()).c_str(), address_mode_letter.c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001474 string_VkSamplerAddressMode(address_mode));
1475 }
1476
1477 // UnnormalizedCoordinates sampler validations
1478 if (sampler_state->createInfo.unnormalizedCoordinates) {
1479 // If ImageView is used by a unnormalizedCoordinates sampler, it needs to check ImageView type
1480 if (image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_3D || image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
1481 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY ||
1482 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY ||
1483 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
1484 auto set = descriptor_set->GetSet();
1485 LogObjectList objlist(set);
1486 objlist.add(image_view);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001487 objlist.add(sampler_state->sampler());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001488 return LogError(objlist, vuids.sampler_imageview_type,
1489 "Descriptor set %s encountered the following validation error at %s time: %s, type: %s in "
1490 "Descriptor in binding #%" PRIu32 " index %" PRIu32 "is used by %s.",
1491 report_data->FormatHandle(set).c_str(), caller, report_data->FormatHandle(image_view).c_str(),
1492 string_VkImageViewType(image_view_ci.viewType), binding, index,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001493 report_data->FormatHandle(sampler_state->sampler()).c_str());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001494 }
1495
1496 // sampler must not be used with any of the SPIR-V OpImageSample* or OpImageSparseSample*
1497 // instructions with ImplicitLod, Dref or Proj in their name
1498 if (reqs & DESCRIPTOR_REQ_SAMPLER_IMPLICITLOD_DREF_PROJ) {
1499 auto set = descriptor_set->GetSet();
1500 LogObjectList objlist(set);
1501 objlist.add(image_view);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001502 objlist.add(sampler_state->sampler());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001503 return LogError(objlist, vuids.sampler_implicitLod_dref_proj,
1504 "Descriptor set %s encountered the following validation error at %s time: %s in "
1505 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1506 " is used by %s that uses invalid operator.",
1507 report_data->FormatHandle(set).c_str(), caller, report_data->FormatHandle(image_view).c_str(),
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001508 binding, index, report_data->FormatHandle(sampler_state->sampler()).c_str());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001509 }
1510
1511 // sampler must not be used with any of the SPIR-V OpImageSample* or OpImageSparseSample*
1512 // instructions that includes a LOD bias or any offset values
1513 if (reqs & DESCRIPTOR_REQ_SAMPLER_BIAS_OFFSET) {
1514 auto set = descriptor_set->GetSet();
1515 LogObjectList objlist(set);
1516 objlist.add(image_view);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001517 objlist.add(sampler_state->sampler());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001518 return LogError(objlist, vuids.sampler_bias_offset,
1519 "Descriptor set %s encountered the following validation error at %s time: %s in "
1520 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1521 " is used by %s that uses invalid bias or offset operator.",
1522 report_data->FormatHandle(set).c_str(), caller, report_data->FormatHandle(image_view).c_str(),
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001523 binding, index, report_data->FormatHandle(sampler_state->sampler()).c_str());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001524 }
1525 }
1526 }
1527 }
1528 return false;
1529}
1530
1531bool CoreChecks::ValidateTexelDescriptor(const char *caller, const DrawDispatchVuid &vuids, const CMD_BUFFER_STATE *cb_node,
1532 const cvdescriptorset::DescriptorSet *descriptor_set,
1533 const cvdescriptorset::TexelDescriptor &texel_descriptor,
1534 const std::pair<const uint32_t, DescriptorRequirement> &binding_info,
1535 uint32_t index) const {
1536 auto buffer_view = texel_descriptor.GetBufferView();
1537 auto buffer_view_state = texel_descriptor.GetBufferViewState();
1538 const auto binding = binding_info.first;
1539 const auto reqs = binding_info.second.reqs;
1540 if ((!buffer_view_state && !enabled_features.robustness2_features.nullDescriptor) ||
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001541 (buffer_view_state && buffer_view_state->Destroyed())) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001542 auto set = descriptor_set->GetSet();
1543 return LogError(set, vuids.descriptor_valid,
1544 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1545 "binding #%" PRIu32 " index %" PRIu32 " is using bufferView %s that is invalid or has been destroyed.",
1546 report_data->FormatHandle(set).c_str(), caller, binding, index,
1547 report_data->FormatHandle(buffer_view).c_str());
1548 }
1549 if (buffer_view) {
1550 auto buffer = buffer_view_state->create_info.buffer;
1551 auto buffer_state = buffer_view_state->buffer_state.get();
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001552 if (buffer_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001553 auto set = descriptor_set->GetSet();
1554 return LogError(set, vuids.descriptor_valid,
1555 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1556 "binding #%" PRIu32 " index %" PRIu32 " is using buffer %s that has been destroyed.",
1557 report_data->FormatHandle(set).c_str(), caller, binding, index,
1558 report_data->FormatHandle(buffer).c_str());
1559 }
1560 auto format_bits = DescriptorRequirementsBitsFromFormat(buffer_view_state->create_info.format);
1561
1562 if (!(reqs & format_bits)) {
1563 // bad component type
1564 auto set = descriptor_set->GetSet();
1565 return LogError(set, vuids.descriptor_valid,
1566 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1567 "binding #%" PRIu32 " index %" PRIu32 " requires %s component type, but bound descriptor format is %s.",
1568 report_data->FormatHandle(set).c_str(), caller, binding, index, StringDescriptorReqComponentType(reqs),
1569 string_VkFormat(buffer_view_state->create_info.format));
1570 }
1571
1572 // Verify VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT
1573 if ((reqs & DESCRIPTOR_REQ_VIEW_ATOMIC_OPERATION) &&
1574 (descriptor_set->GetTypeFromBinding(binding) == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) &&
1575 !(buffer_view_state->format_features & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT)) {
1576 auto set = descriptor_set->GetSet();
1577 LogObjectList objlist(set);
1578 objlist.add(buffer_view);
1579 return LogError(objlist, "UNASSIGNED-None-MismatchAtomicBufferFeature",
1580 "Descriptor set %s encountered the following validation error at %s time: Descriptor "
1581 "in binding #%" PRIu32 " index %" PRIu32
1582 ", %s, format %s, doesn't "
1583 "contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT.",
1584 report_data->FormatHandle(set).c_str(), caller, binding, index,
1585 report_data->FormatHandle(buffer_view).c_str(), string_VkFormat(buffer_view_state->create_info.format));
1586 }
1587 if (enabled_features.core11.protectedMemory == VK_TRUE) {
1588 if (ValidateProtectedBuffer(cb_node, buffer_view_state->buffer_state.get(), caller, vuids.unprotected_command_buffer,
1589 "Buffer is in a descriptorSet")) {
1590 return true;
1591 }
1592 if (binding_info.second.is_writable &&
1593 ValidateUnprotectedBuffer(cb_node, buffer_view_state->buffer_state.get(), caller, vuids.protected_command_buffer,
1594 "Buffer is in a descriptorSet")) {
1595 return true;
1596 }
1597 }
1598 }
1599 return false;
1600}
1601
1602bool CoreChecks::ValidateAccelerationDescriptor(const char *caller, const DrawDispatchVuid &vuids, const CMD_BUFFER_STATE *cb_node,
1603 const cvdescriptorset::DescriptorSet *descriptor_set,
1604 const cvdescriptorset::AccelerationStructureDescriptor &descriptor,
1605 const std::pair<const uint32_t, DescriptorRequirement> &binding_info,
1606 uint32_t index) const {
1607 // Verify that acceleration structures are valid
1608 const auto binding = binding_info.first;
1609 if (descriptor.is_khr()) {
1610 auto acc = descriptor.GetAccelerationStructure();
1611 auto acc_node = descriptor.GetAccelerationStructureStateKHR();
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001612 if (!acc_node || acc_node->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001613 if (acc != VK_NULL_HANDLE || !enabled_features.robustness2_features.nullDescriptor) {
1614 auto set = descriptor_set->GetSet();
1615 return LogError(set, vuids.descriptor_valid,
1616 "Descriptor set %s encountered the following validation error at %s time: "
1617 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1618 " is using acceleration structure %s that is invalid or has been destroyed.",
1619 report_data->FormatHandle(set).c_str(), caller, binding, index,
1620 report_data->FormatHandle(acc).c_str());
1621 }
1622 } else {
Jeremy Gebben6fbf8242021-06-21 09:14:46 -06001623 for (const auto &item: acc_node->GetBoundMemory()) {
1624 auto &mem_binding = item.second;
1625 if (mem_binding.mem_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001626 auto set = descriptor_set->GetSet();
1627 return LogError(set, vuids.descriptor_valid,
1628 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1629 "binding #%" PRIu32 " index %" PRIu32
1630 " is using acceleration structure %s that references invalid memory %s.",
1631 report_data->FormatHandle(set).c_str(), caller, binding, index,
Jeremy Gebben6fbf8242021-06-21 09:14:46 -06001632 report_data->FormatHandle(acc).c_str(),
1633 report_data->FormatHandle(mem_binding.mem_state->mem()).c_str());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001634 }
1635 }
1636 }
1637 } else {
1638 auto acc = descriptor.GetAccelerationStructureNV();
1639 auto acc_node = descriptor.GetAccelerationStructureStateNV();
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001640 if (!acc_node || acc_node->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001641 if (acc != VK_NULL_HANDLE || !enabled_features.robustness2_features.nullDescriptor) {
1642 auto set = descriptor_set->GetSet();
1643 return LogError(set, vuids.descriptor_valid,
1644 "Descriptor set %s encountered the following validation error at %s time: "
1645 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1646 " is using acceleration structure %s that is invalid or has been destroyed.",
1647 report_data->FormatHandle(set).c_str(), caller, binding, index,
1648 report_data->FormatHandle(acc).c_str());
1649 }
1650 } else {
Jeremy Gebben6fbf8242021-06-21 09:14:46 -06001651 for (const auto &item : acc_node->GetBoundMemory()) {
1652 auto &mem_binding = item.second;
1653 if (mem_binding.mem_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001654 auto set = descriptor_set->GetSet();
1655 return LogError(set, vuids.descriptor_valid,
1656 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1657 "binding #%" PRIu32 " index %" PRIu32
1658 " is using acceleration structure %s that references invalid memory %s.",
1659 report_data->FormatHandle(set).c_str(), caller, binding, index,
Jeremy Gebben6fbf8242021-06-21 09:14:46 -06001660 report_data->FormatHandle(acc).c_str(),
1661 report_data->FormatHandle(mem_binding.mem_state->mem()).c_str());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001662 }
1663 }
1664 }
1665 }
1666 return false;
1667}
1668
1669// If the validation is related to both of image and sampler,
1670// please leave it in (descriptor_class == DescriptorClass::ImageSampler || descriptor_class ==
1671// DescriptorClass::Image) Here is to validate for only sampler.
1672bool CoreChecks::ValidateSamplerDescriptor(const char *caller, const DrawDispatchVuid &vuids, const CMD_BUFFER_STATE *cb_node,
1673 const cvdescriptorset::DescriptorSet *descriptor_set,
1674 const std::pair<const uint32_t, DescriptorRequirement> &binding_info, uint32_t index,
1675 VkSampler sampler, bool is_immutable, const SAMPLER_STATE *sampler_state) const {
1676 // Verify Sampler still valid
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001677 if (!sampler_state || sampler_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001678 auto set = descriptor_set->GetSet();
1679 return LogError(set, vuids.descriptor_valid,
1680 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1681 "binding #%" PRIu32 " index %" PRIu32 " is using sampler %s that is invalid or has been destroyed.",
1682 report_data->FormatHandle(set).c_str(), caller, binding_info.first, index,
1683 report_data->FormatHandle(sampler).c_str());
1684 } else {
1685 if (sampler_state->samplerConversion && !is_immutable) {
1686 auto set = descriptor_set->GetSet();
1687 return LogError(set, vuids.descriptor_valid,
1688 "Descriptor set %s encountered the following validation error at %s time: sampler (%s) "
1689 "in the descriptor set (%s) contains a YCBCR conversion (%s), then the sampler MUST "
1690 "also exist as an immutable sampler.",
1691 report_data->FormatHandle(set).c_str(), caller, report_data->FormatHandle(sampler).c_str(),
1692 report_data->FormatHandle(descriptor_set->GetSet()).c_str(),
1693 report_data->FormatHandle(sampler_state->samplerConversion).c_str());
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001694 }
1695 }
Tony-LunarGace473a2020-05-06 12:48:04 -06001696 return false;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001697}
Chris Forbes57989132016-07-26 17:06:10 +12001698
John Zulauf1d27e0a2018-11-05 10:12:48 -07001699// Loop through the write updates to do for a push descriptor set, ignoring dstSet
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001700void cvdescriptorset::DescriptorSet::PerformPushDescriptorsUpdate(ValidationStateTracker *dev_data, uint32_t write_count,
1701 const VkWriteDescriptorSet *p_wds) {
John Zulauf1d27e0a2018-11-05 10:12:48 -07001702 assert(IsPushDescriptor());
1703 for (uint32_t i = 0; i < write_count; i++) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001704 PerformWriteUpdate(dev_data, &p_wds[i]);
John Zulauf1d27e0a2018-11-05 10:12:48 -07001705 }
Jason Macnak83cfd582019-07-31 10:14:24 -07001706
1707 push_descriptor_set_writes.clear();
1708 push_descriptor_set_writes.reserve(static_cast<std::size_t>(write_count));
1709 for (uint32_t i = 0; i < write_count; i++) {
1710 push_descriptor_set_writes.push_back(safe_VkWriteDescriptorSet(&p_wds[i]));
1711 }
John Zulauf1d27e0a2018-11-05 10:12:48 -07001712}
1713
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001714// Perform write update in given update struct
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001715void cvdescriptorset::DescriptorSet::PerformWriteUpdate(ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update) {
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001716 // Perform update on a per-binding basis as consecutive updates roll over to next binding
1717 auto descriptors_remaining = update->descriptorCount;
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001718 auto offset = update->dstArrayElement;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001719 auto orig_binding = DescriptorSetLayout::ConstBindingIterator(layout_.get(), update->dstBinding);
locke-lunarge46b7782019-09-10 01:44:20 -06001720 auto current_binding = orig_binding;
1721
Tobin Ehlise16805c2017-08-09 09:10:37 -06001722 uint32_t update_index = 0;
locke-lunarge46b7782019-09-10 01:44:20 -06001723 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
1724 while (descriptors_remaining && orig_binding.IsConsistent(current_binding)) {
1725 const auto &index_range = current_binding.GetGlobalIndexRange();
1726 auto global_idx = index_range.start + offset;
1727 // global_idx is which descriptor is needed to update. If global_idx > index_range.end, it means the descriptor isn't in
1728 // this binding, maybe in next binding.
1729 if (global_idx >= index_range.end) {
1730 offset -= current_binding.GetDescriptorCount();
1731 ++current_binding;
1732 continue;
1733 }
1734
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001735 // Loop over the updates for a single binding at a time
locke-lunarge46b7782019-09-10 01:44:20 -06001736 uint32_t update_count = std::min(descriptors_remaining, current_binding.GetDescriptorCount() - offset);
Tobin Ehlise16805c2017-08-09 09:10:37 -06001737 for (uint32_t di = 0; di < update_count; ++di, ++update_index) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06001738 descriptors_[global_idx + di]->WriteUpdate(this, state_data_, update, update_index);
ziga-lunarge5d28542021-10-24 21:14:25 +02001739 descriptors_[global_idx + di]->SetDescriptorType(update->descriptorType);
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001740 }
1741 // Roll over to next binding in case of consecutive update
1742 descriptors_remaining -= update_count;
locke-lunarge46b7782019-09-10 01:44:20 -06001743 if (descriptors_remaining) {
1744 // Starting offset is beyond the current binding. Check consistency, update counters and advance to the next binding,
1745 // looking for the start point. All bindings (even those skipped) must be consistent with the update and with the
1746 // original binding.
1747 offset = 0;
1748 ++current_binding;
1749 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001750 }
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05001751 if (update->descriptorCount) {
1752 some_update_ = true;
1753 change_count_++;
1754 }
Tobin Ehlis56a30942016-05-19 08:00:00 -06001755
Jeremy Gebben5570abe2021-05-16 18:35:13 -06001756 if (!IsPushDescriptor() && !(layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Mike Schuchardt2df08912020-12-15 16:28:09 -08001757 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT))) {
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001758 Invalidate(false);
Jeff Bolzfdf96072018-04-10 14:32:18 -05001759 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001760}
Tobin Ehlis300888c2016-05-18 13:43:26 -06001761// Validate Copy update
John Zulaufc93c4252019-06-25 09:19:49 -06001762bool CoreChecks::ValidateCopyUpdate(const VkCopyDescriptorSet *update, const DescriptorSet *dst_set, const DescriptorSet *src_set,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05001763 const char *func_name, std::string *error_code, std::string *error_msg) const {
Jeff Bolz6aad1742019-10-16 11:10:09 -05001764 auto dst_layout = dst_set->GetLayout().get();
1765 auto src_layout = src_set->GetLayout().get();
John Zulaufd9435c32019-06-05 15:55:36 -06001766
John Zulauf5dfd45c2018-01-17 11:06:34 -07001767 // Verify dst layout still valid
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001768 if (dst_layout->Destroyed()) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001769 *error_code = "VUID-VkCopyDescriptorSet-dstSet-parameter";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06001770 std::ostringstream str;
1771 str << "Cannot call " << func_name << " to perform copy update on dstSet " << report_data->FormatHandle(dst_set->GetSet())
1772 << " created with destroyed " << report_data->FormatHandle(dst_layout->GetDescriptorSetLayout()) << ".";
1773 *error_msg = str.str();
John Zulauf5dfd45c2018-01-17 11:06:34 -07001774 return false;
1775 }
1776
1777 // Verify src layout still valid
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001778 if (src_layout->Destroyed()) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001779 *error_code = "VUID-VkCopyDescriptorSet-srcSet-parameter";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06001780 std::ostringstream str;
1781 str << "Cannot call " << func_name << " to perform copy update on dstSet " << report_data->FormatHandle(dst_set->GetSet())
1782 << " from srcSet " << report_data->FormatHandle(src_set->GetSet()) << " created with destroyed "
1783 << report_data->FormatHandle(src_layout->GetDescriptorSetLayout()) << ".";
1784 *error_msg = str.str();
John Zulauf5dfd45c2018-01-17 11:06:34 -07001785 return false;
1786 }
1787
John Zulaufd9435c32019-06-05 15:55:36 -06001788 if (!dst_layout->HasBinding(update->dstBinding)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001789 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-00347";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001790 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001791 error_str << "DescriptorSet " << report_data->FormatHandle(dst_set->GetSet())
1792 << " does not have copy update dest binding of " << update->dstBinding;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001793 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001794 return false;
1795 }
1796 if (!src_set->HasBinding(update->srcBinding)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001797 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-00345";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001798 std::stringstream error_str;
sourav parmarf4a78252020-04-10 13:04:21 -07001799 error_str << "DescriptorSet " << report_data->FormatHandle(src_set->GetSet())
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001800 << " does not have copy update src binding of " << update->srcBinding;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001801 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001802 return false;
1803 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001804 // Verify idle ds
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001805 if (dst_set->InUse() &&
John Zulaufd9435c32019-06-05 15:55:36 -06001806 !(dst_layout->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Mike Schuchardt2df08912020-12-15 16:28:09 -08001807 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT))) {
Jeff Bolzfdf96072018-04-10 14:32:18 -05001808 // TODO : Re-using Free Idle error code, need copy update idle error code
Dave Houlton00c154e2018-05-24 13:20:50 -06001809 *error_code = "VUID-vkFreeDescriptorSets-pDescriptorSets-00309";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001810 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001811 error_str << "Cannot call " << func_name << " to perform copy update on descriptor set "
1812 << report_data->FormatHandle(dst_set->GetSet()) << " that is in use by a command buffer";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001813 *error_msg = error_str.str();
1814 return false;
1815 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001816 // src & dst set bindings are valid
1817 // Check bounds of src & dst
John Zulaufc483f442017-12-15 14:02:06 -07001818 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001819 if ((src_start_idx + update->descriptorCount) > src_set->GetTotalDescriptorCount()) {
1820 // SRC update out of bounds
Dave Houlton00c154e2018-05-24 13:20:50 -06001821 *error_code = "VUID-VkCopyDescriptorSet-srcArrayElement-00346";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001822 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001823 error_str << "Attempting copy update from descriptorSet " << report_data->FormatHandle(update->srcSet) << " binding#"
1824 << update->srcBinding << " with offset index of "
1825 << src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start << " plus update array offset of "
1826 << update->srcArrayElement << " and update of " << update->descriptorCount
Tobin Ehlis1d81edd2016-11-21 09:50:49 -07001827 << " descriptors oversteps total number of descriptors in set: " << src_set->GetTotalDescriptorCount();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001828 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001829 return false;
1830 }
John Zulaufd9435c32019-06-05 15:55:36 -06001831 auto dst_start_idx = dst_layout->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
1832 if ((dst_start_idx + update->descriptorCount) > dst_layout->GetTotalDescriptorCount()) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001833 // DST update out of bounds
Dave Houlton00c154e2018-05-24 13:20:50 -06001834 *error_code = "VUID-VkCopyDescriptorSet-dstArrayElement-00348";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001835 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001836 error_str << "Attempting copy update to descriptorSet " << report_data->FormatHandle(dst_set->GetSet()) << " binding#"
1837 << update->dstBinding << " with offset index of "
1838 << dst_layout->GetGlobalIndexRangeFromBinding(update->dstBinding).start << " plus update array offset of "
1839 << update->dstArrayElement << " and update of " << update->descriptorCount
John Zulaufd9435c32019-06-05 15:55:36 -06001840 << " descriptors oversteps total number of descriptors in set: " << dst_layout->GetTotalDescriptorCount();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001841 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001842 return false;
1843 }
1844 // Check that types match
Shannon McPhersonafe55122020-05-25 16:20:19 -06001845 // TODO : Base default error case going from here is "VUID-VkAcquireNextImageInfoKHR-semaphore-parameter" 2ba which covers all
Dave Houltond8ed0212018-05-16 17:18:24 -06001846 // consistency issues, need more fine-grained error codes
Dave Houlton00c154e2018-05-24 13:20:50 -06001847 *error_code = "VUID-VkCopyDescriptorSet-srcSet-00349";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001848 auto src_type = src_set->GetTypeFromBinding(update->srcBinding);
John Zulaufd9435c32019-06-05 15:55:36 -06001849 auto dst_type = dst_layout->GetTypeFromBinding(update->dstBinding);
Ricardo Garcia14f4f762021-04-13 11:36:12 +02001850 if (src_type != VK_DESCRIPTOR_TYPE_MUTABLE_VALVE && dst_type != VK_DESCRIPTOR_TYPE_MUTABLE_VALVE && src_type != dst_type) {
sourav parmarf4a78252020-04-10 13:04:21 -07001851 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02632";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001852 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001853 error_str << "Attempting copy update to descriptorSet " << report_data->FormatHandle(dst_set->GetSet()) << " binding #"
1854 << update->dstBinding << " with type " << string_VkDescriptorType(dst_type) << " from descriptorSet "
1855 << report_data->FormatHandle(src_set->GetSet()) << " binding #" << update->srcBinding << " with type "
1856 << string_VkDescriptorType(src_type) << ". Types do not match";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001857 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001858 return false;
1859 }
1860 // Verify consistency of src & dst bindings if update crosses binding boundaries
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001861 if ((!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(src_layout, update->srcBinding),
John Zulauf4a015c92019-06-04 09:50:05 -06001862 update->srcArrayElement, update->descriptorCount, "copy update from", src_set->GetSet(),
1863 error_msg)) ||
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001864 (!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(dst_layout, update->dstBinding),
John Zulaufd9435c32019-06-05 15:55:36 -06001865 update->dstArrayElement, update->descriptorCount, "copy update to", dst_set->GetSet(),
1866 error_msg))) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001867 return false;
1868 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001869
Mike Schuchardt2df08912020-12-15 16:28:09 -08001870 if ((src_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT) &&
1871 !(dst_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001872 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01918";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001873 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001874 error_str << "If pname:srcSet's (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001875 << ") layout was created with the "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001876 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag "
Jeff Bolzfdf96072018-04-10 14:32:18 -05001877 "set, then pname:dstSet's ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001878 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001879 << ") layout must: also have been created with the "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001880 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag set";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001881 *error_msg = error_str.str();
1882 return false;
1883 }
1884
sfricke-samsung45996a42021-09-16 13:45:27 -07001885 if (IsExtEnabled(device_extensions.vk_valve_mutable_descriptor_type)) {
Mike Schuchardt294a1592021-05-12 15:38:00 -07001886 if (!(src_layout->GetCreateFlags() & (VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT |
1887 VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE)) &&
1888 (dst_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT)) {
1889 *error_code = "VUID-VkCopyDescriptorSet-srcSet-04885";
1890 std::stringstream error_str;
1891 error_str << "If pname:srcSet's (" << report_data->FormatHandle(update->srcSet)
1892 << ") layout was created with neither ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT nor "
1893 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE flags set, then pname:dstSet's ("
1894 << report_data->FormatHandle(update->dstSet)
1895 << ") layout must: have been created without the "
1896 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag set";
1897 *error_msg = error_str.str();
1898 return false;
1899 }
1900 } else {
1901 if (!(src_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT) &&
1902 (dst_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT)) {
1903 *error_code = "VUID-VkCopyDescriptorSet-srcSet-04886";
1904 std::stringstream error_str;
1905 error_str << "If pname:srcSet's (" << report_data->FormatHandle(update->srcSet)
1906 << ") layout was created without the ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag "
1907 "set, then pname:dstSet's ("
1908 << report_data->FormatHandle(update->dstSet)
1909 << ") layout must: also have been created without the "
1910 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag set";
1911 *error_msg = error_str.str();
1912 return false;
1913 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001914 }
1915
Mike Schuchardt2df08912020-12-15 16:28:09 -08001916 if ((src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT) &&
1917 !(dst_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001918 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01920";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001919 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001920 error_str << "If the descriptor pool from which pname:srcSet (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001921 << ") was allocated was created "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001922 "with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag "
Jeff Bolzfdf96072018-04-10 14:32:18 -05001923 "set, then the descriptor pool from which pname:dstSet ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001924 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001925 << ") was allocated must: "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001926 "also have been created with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag set";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001927 *error_msg = error_str.str();
1928 return false;
1929 }
1930
sfricke-samsung45996a42021-09-16 13:45:27 -07001931 if (IsExtEnabled(device_extensions.vk_valve_mutable_descriptor_type)) {
Mike Schuchardt294a1592021-05-12 15:38:00 -07001932 if (!(src_set->GetPoolState()->createInfo.flags &
1933 (VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE)) &&
1934 (dst_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT)) {
1935 *error_code = "VUID-VkCopyDescriptorSet-srcSet-04887";
1936 std::stringstream error_str;
1937 error_str << "If the descriptor pool from which pname:srcSet (" << report_data->FormatHandle(update->srcSet)
1938 << ") was allocated was created with neither ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT nor "
1939 "ename:VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE flags set, then the descriptor pool from which "
1940 "pname:dstSet ("
1941 << report_data->FormatHandle(update->dstSet)
1942 << ") was allocated must: have been created without the "
1943 "ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag set";
1944 *error_msg = error_str.str();
1945 return false;
1946 }
1947 } else {
1948 if (!(src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT) &&
1949 (dst_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT)) {
1950 *error_code = "VUID-VkCopyDescriptorSet-srcSet-04888";
1951 std::stringstream error_str;
1952 error_str << "If the descriptor pool from which pname:srcSet (" << report_data->FormatHandle(update->srcSet)
1953 << ") was allocated was created without the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag set, "
1954 "then the descriptor pool from which pname:dstSet ("
1955 << report_data->FormatHandle(update->dstSet)
1956 << ") was allocated must: also have been created without the "
1957 "ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag set";
1958 *error_msg = error_str.str();
1959 return false;
1960 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001961 }
1962
Jeff Bolze54ae892018-09-08 12:16:29 -05001963 if (src_type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
1964 if ((update->srcArrayElement % 4) != 0) {
1965 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-02223";
1966 std::stringstream error_str;
1967 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1968 << "srcArrayElement " << update->srcArrayElement << " not a multiple of 4";
1969 *error_msg = error_str.str();
1970 return false;
1971 }
1972 if ((update->dstArrayElement % 4) != 0) {
1973 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02224";
1974 std::stringstream error_str;
1975 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1976 << "dstArrayElement " << update->dstArrayElement << " not a multiple of 4";
1977 *error_msg = error_str.str();
1978 return false;
1979 }
1980 if ((update->descriptorCount % 4) != 0) {
1981 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-02225";
1982 std::stringstream error_str;
1983 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1984 << "descriptorCount " << update->descriptorCount << " not a multiple of 4";
1985 *error_msg = error_str.str();
1986 return false;
1987 }
1988 }
1989
ziga-lunarge5d28542021-10-24 21:14:25 +02001990 if (dst_type == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) {
1991 if (src_type != VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) {
1992 if (!dst_layout->IsTypeMutable(src_type, update->dstBinding)) {
1993 *error_code = "VUID-VkCopyDescriptorSet-dstSet-04612";
1994 std::stringstream error_str;
1995 error_str << "Attempting copy update with dstBinding descriptor type VK_DESCRIPTOR_TYPE_MUTABLE_VALVE, but the new "
1996 "active descriptor type "
1997 << string_VkDescriptorType(src_type)
1998 << " is not in the corresponding pMutableDescriptorTypeLists list.";
1999 *error_msg = error_str.str();
2000 return false;
2001 }
2002 }
2003 } else if (src_type == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) {
2004 const auto *descriptor = src_set->GetDescriptorFromGlobalIndex(update->srcBinding);
2005 if (descriptor->active_descriptor_type != dst_type) {
2006 *error_code = "VUID-VkCopyDescriptorSet-srcSet-04613";
2007 std::stringstream error_str;
2008 error_str << "Attempting copy update with srcBinding descriptor type VK_DESCRIPTOR_TYPE_MUTABLE_VALVE, but the "
2009 "active descriptor type ("
2010 << string_VkDescriptorType(descriptor->active_descriptor_type)
2011 << ") does not match the dstBinding descriptor type " << string_VkDescriptorType(dst_type) << ".";
2012 *error_msg = error_str.str();
2013 return false;
2014 }
2015 }
2016
2017 if (dst_type == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) {
2018 if (src_type == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) {
2019 const auto &mutable_src_types = src_layout->GetMutableTypes(update->srcBinding);
2020 const auto &mutable_dst_types = dst_layout->GetMutableTypes(update->dstBinding);
2021 bool complete_match = mutable_src_types.size() == mutable_dst_types.size();
2022 if (complete_match) {
2023 for (const auto mutable_src_type : mutable_src_types) {
2024 if (std::find(mutable_dst_types.begin(), mutable_dst_types.end(), mutable_src_type) ==
2025 mutable_dst_types.end()) {
2026 complete_match = false;
2027 break;
2028 }
2029 }
2030 }
2031 if (!complete_match) {
2032 *error_code = "VUID-VkCopyDescriptorSet-dstSet-04614";
2033 std::stringstream error_str;
2034 error_str << "Attempting copy update with dstBinding and new active descriptor type being "
2035 "VK_DESCRIPTOR_TYPE_MUTABLE_VALVE, but their corresponding pMutableDescriptorTypeLists do not match.";
2036 *error_msg = error_str.str();
2037 return false;
2038 }
2039 }
2040 }
2041
ziga-lunarg5b2bede2021-11-08 11:54:17 +01002042 // Update mutable types
2043 if (src_type == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) {
2044 src_type = src_set->GetDescriptorFromGlobalIndex(update->srcBinding)->active_descriptor_type;
2045 }
2046 if (dst_type == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) {
2047 dst_type = dst_set->GetDescriptorFromGlobalIndex(update->dstBinding)->active_descriptor_type;
2048 }
2049
Tobin Ehlisd41e7b62016-05-19 07:56:18 -06002050 // Update parameters all look good and descriptor updated so verify update contents
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002051 if (!VerifyCopyUpdateContents(update, src_set, src_type, src_start_idx, dst_set, dst_type, dst_start_idx, func_name, error_code,
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002052 error_msg)) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002053 return false;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002054 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002055
2056 // All checks passed so update is good
2057 return true;
2058}
2059// Perform Copy update
Jeff Bolz41a1ced2019-10-11 11:40:49 -05002060void cvdescriptorset::DescriptorSet::PerformCopyUpdate(ValidationStateTracker *dev_data, const VkCopyDescriptorSet *update,
2061 const DescriptorSet *src_set) {
John Zulaufc483f442017-12-15 14:02:06 -07002062 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002063 auto dst_start_idx = layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002064 // Update parameters all look good so perform update
2065 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Józef Kucia5297e372017-10-13 22:31:34 +02002066 auto src = src_set->descriptors_[src_start_idx + di].get();
2067 auto dst = descriptors_[dst_start_idx + di].get();
2068 if (src->updated) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002069 dst->CopyUpdate(this, state_data_, src);
Józef Kucia5297e372017-10-13 22:31:34 +02002070 some_update_ = true;
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05002071 change_count_++;
Józef Kucia5297e372017-10-13 22:31:34 +02002072 } else {
2073 dst->updated = false;
2074 }
ziga-lunarge5d28542021-10-24 21:14:25 +02002075 dst->active_descriptor_type = src->active_descriptor_type;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002076 }
Tobin Ehlis56a30942016-05-19 08:00:00 -06002077
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002078 if (!(layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Mike Schuchardt2df08912020-12-15 16:28:09 -08002079 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT))) {
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06002080 Invalidate(false);
Jeff Bolzfdf96072018-04-10 14:32:18 -05002081 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002082}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002083
John Zulauf6f3d2bd2018-10-29 17:08:42 -06002084// Update the drawing state for the affected descriptors.
2085// Set cb_node to this set and this set to cb_node.
2086// Add the bindings of the descriptor
2087// Set the layout based on the current descriptor layout (will mask subsequent layer mismatch errors)
2088// TODO: Modify the UpdateDrawState virtural functions to *only* set initial layout and not change layouts
Tobin Ehlisf9519102016-08-17 09:49:13 -06002089// Prereq: This should be called for a set that has been confirmed to be active for the given cb_node, meaning it's going
2090// to be used in a draw by the given cb_node
Jeremy Kniagere6827432020-04-01 09:05:56 -06002091void cvdescriptorset::DescriptorSet::UpdateDrawState(ValidationStateTracker *device_data, CMD_BUFFER_STATE *cb_node,
2092 CMD_TYPE cmd_type, const PIPELINE_STATE *pipe,
sfricke-samsung85584a72021-09-30 21:43:38 -07002093 const BindingReqMap &binding_req_map) {
Tony-LunarG77822802020-05-28 16:35:46 -06002094 if (!device_data->disabled[command_buffer_state] && !IsPushDescriptor()) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002095 cb_node->AddChild(this);
Jeff Bolzafa429a2019-08-14 09:59:22 -05002096 }
Jeff Bolze18e7242019-08-12 20:55:22 -05002097
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002098 // Descriptor UpdateDrawState only call image layout validation callbacks. If it is disabled, skip the entire loop.
2099 if (device_data->disabled[image_layout_validation]) {
Jeff Bolze18e7242019-08-12 20:55:22 -05002100 return;
2101 }
2102
Tobin Ehlisf9519102016-08-17 09:49:13 -06002103 // For the active slots, use set# to look up descriptorSet from boundDescriptorSets, and bind all of that descriptor set's
2104 // resources
locke-lunarg540b2252020-08-03 13:23:36 -06002105 CMD_BUFFER_STATE::CmdDrawDispatchInfo cmd_info = {};
John Zulauf79f06582021-02-27 18:38:39 -07002106 for (const auto &binding_req_pair : binding_req_map) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002107 auto index = layout_->GetIndexFromBinding(binding_req_pair.first);
locke-gb3ce08f2019-09-30 12:30:56 -06002108
Tony-LunarG62c5dba2018-12-20 14:27:23 -07002109 // We aren't validating descriptors created with PARTIALLY_BOUND or UPDATE_AFTER_BIND, so don't record state
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002110 auto flags = layout_->GetDescriptorBindingFlagsFromIndex(index);
Mike Schuchardt2df08912020-12-15 16:28:09 -08002111 if (flags & (VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT)) {
2112 if (!(flags & VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT)) {
locke-lunarg36045992020-08-20 16:54:37 -06002113 cmd_info.binding_infos.emplace_back(binding_req_pair);
locke-gb3ce08f2019-09-30 12:30:56 -06002114 }
Tony-LunarG62c5dba2018-12-20 14:27:23 -07002115 continue;
2116 }
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002117 auto range = layout_->GetGlobalIndexRangeFromIndex(index);
John Zulaufc483f442017-12-15 14:02:06 -07002118 for (uint32_t i = range.start; i < range.end; ++i) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002119 const auto descriptor_class = descriptors_[i]->GetClass();
2120 switch (descriptor_class) {
2121 case DescriptorClass::Image:
2122 case DescriptorClass::ImageSampler: {
2123 auto *image_desc = static_cast<ImageDescriptor *>(descriptors_[i].get());
2124 image_desc->UpdateDrawState(device_data, cb_node);
2125 break;
2126 }
2127 default:
2128 break;
2129 }
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06002130 }
2131 }
locke-lunarg540b2252020-08-03 13:23:36 -06002132
2133 if (cmd_info.binding_infos.size() > 0) {
2134 cmd_info.cmd_type = cmd_type;
locke-lunarg540b2252020-08-03 13:23:36 -06002135 if (cb_node->activeFramebuffer) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002136 cmd_info.framebuffer = cb_node->activeFramebuffer->framebuffer();
locke-lunargfc78e932020-11-19 17:06:24 -07002137 cmd_info.attachments = cb_node->active_attachments;
2138 cmd_info.subpasses = cb_node->active_subpasses;
locke-lunarg540b2252020-08-03 13:23:36 -06002139 }
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002140 cb_node->validate_descriptorsets_in_queuesubmit[GetSet()].emplace_back(cmd_info);
locke-lunarg540b2252020-08-03 13:23:36 -06002141 }
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06002142}
2143
John Zulauffbf3c202019-07-17 14:57:14 -06002144void cvdescriptorset::DescriptorSet::FilterOneBindingReq(const BindingReqMap::value_type &binding_req_pair, BindingReqMap *out_req,
2145 const TrackedBindings &bindings, uint32_t limit) {
2146 if (bindings.size() < limit) {
2147 const auto it = bindings.find(binding_req_pair.first);
2148 if (it == bindings.cend()) out_req->emplace(binding_req_pair);
John Zulauf48a6a702017-12-22 17:14:54 -07002149 }
2150}
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06002151
John Zulauffbf3c202019-07-17 14:57:14 -06002152void cvdescriptorset::DescriptorSet::FilterBindingReqs(const CMD_BUFFER_STATE &cb_state, const PIPELINE_STATE &pipeline,
2153 const BindingReqMap &in_req, BindingReqMap *out_req) const {
2154 // For const cleanliness we have to find in the maps...
Jeremy Gebben87db52f2021-10-14 13:55:09 -06002155 const auto validated_it = cb_state.descriptorset_cache.find(this);
2156 if (validated_it == cb_state.descriptorset_cache.end()) {
John Zulauffbf3c202019-07-17 14:57:14 -06002157 // We have nothing validated, copy in to out
2158 for (const auto &binding_req_pair : in_req) {
2159 out_req->emplace(binding_req_pair);
John Zulauf48a6a702017-12-22 17:14:54 -07002160 }
John Zulauffbf3c202019-07-17 14:57:14 -06002161 return;
John Zulauf48a6a702017-12-22 17:14:54 -07002162 }
John Zulauffbf3c202019-07-17 14:57:14 -06002163 const auto &validated = validated_it->second;
John Zulauf48a6a702017-12-22 17:14:54 -07002164
John Zulauffbf3c202019-07-17 14:57:14 -06002165 const auto image_sample_version_it = validated.image_samplers.find(&pipeline);
2166 const VersionedBindings *image_sample_version = nullptr;
2167 if (image_sample_version_it != validated.image_samplers.cend()) {
2168 image_sample_version = &(image_sample_version_it->second);
2169 }
2170 const auto &dynamic_buffers = validated.dynamic_buffers;
2171 const auto &non_dynamic_buffers = validated.non_dynamic_buffers;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002172 const auto &stats = layout_->GetBindingTypeStats();
John Zulauf48a6a702017-12-22 17:14:54 -07002173 for (const auto &binding_req_pair : in_req) {
2174 auto binding = binding_req_pair.first;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002175 VkDescriptorSetLayoutBinding const *layout_binding = layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
John Zulauf48a6a702017-12-22 17:14:54 -07002176 if (!layout_binding) {
2177 continue;
2178 }
2179 // Caching criteria differs per type.
2180 // If image_layout have changed , the image descriptors need to be validated against them.
sfricke-samsung60f29ec2021-03-10 20:37:25 -08002181 if (IsBufferDescriptor(layout_binding->descriptorType)) {
2182 if (IsDynamicDescriptor(layout_binding->descriptorType)) {
2183 FilterOneBindingReq(binding_req_pair, out_req, dynamic_buffers, stats.dynamic_buffer_count);
2184 } else {
2185 FilterOneBindingReq(binding_req_pair, out_req, non_dynamic_buffers, stats.non_dynamic_buffer_count);
2186 }
John Zulauf48a6a702017-12-22 17:14:54 -07002187 } else {
2188 // This is rather crude, as the changed layouts may not impact the bound descriptors,
2189 // but the simple "versioning" is a simple "dirt" test.
John Zulauffbf3c202019-07-17 14:57:14 -06002190 bool stale = true;
2191 if (image_sample_version) {
2192 const auto version_it = image_sample_version->find(binding);
2193 if (version_it != image_sample_version->cend() && (version_it->second == cb_state.image_layout_change_count)) {
2194 stale = false;
2195 }
2196 }
2197 if (stale) {
John Zulauf48a6a702017-12-22 17:14:54 -07002198 out_req->emplace(binding_req_pair);
2199 }
2200 }
2201 }
2202}
Tobin Ehlis9252c2b2016-07-21 14:40:22 -06002203
Jeremy Gebben87db52f2021-10-14 13:55:09 -06002204void cvdescriptorset::DescriptorSet::UpdateValidationCache(CMD_BUFFER_STATE &cb_state, const PIPELINE_STATE &pipeline,
John Zulauffbf3c202019-07-17 14:57:14 -06002205 const BindingReqMap &updated_bindings) {
Jeremy Gebben87db52f2021-10-14 13:55:09 -06002206 auto &validated = cb_state.descriptorset_cache[this];
John Zulauffbf3c202019-07-17 14:57:14 -06002207
2208 auto &image_sample_version = validated.image_samplers[&pipeline];
2209 auto &dynamic_buffers = validated.dynamic_buffers;
2210 auto &non_dynamic_buffers = validated.non_dynamic_buffers;
2211 for (const auto &binding_req_pair : updated_bindings) {
2212 auto binding = binding_req_pair.first;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002213 VkDescriptorSetLayoutBinding const *layout_binding = layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
John Zulauffbf3c202019-07-17 14:57:14 -06002214 if (!layout_binding) {
2215 continue;
2216 }
2217 // Caching criteria differs per type.
sfricke-samsung60f29ec2021-03-10 20:37:25 -08002218 if (IsBufferDescriptor(layout_binding->descriptorType)) {
2219 if (IsDynamicDescriptor(layout_binding->descriptorType)) {
2220 dynamic_buffers.emplace(binding);
2221 } else {
2222 non_dynamic_buffers.emplace(binding);
2223 }
John Zulauffbf3c202019-07-17 14:57:14 -06002224 } else {
2225 // Save the layout change version...
2226 image_sample_version[binding] = cb_state.image_layout_change_count;
2227 }
2228 }
2229}
2230
John Zulaufd2c3dae2019-12-12 11:02:17 -07002231cvdescriptorset::SamplerDescriptor::SamplerDescriptor(const ValidationStateTracker *dev_data, const VkSampler *immut)
Jeremy Gebben059ab502021-04-26 11:25:02 -06002232 : Descriptor(PlainSampler), immutable_(false) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002233 if (immut) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002234 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(*immut);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002235 immutable_ = true;
2236 updated = true;
2237 }
2238}
Tobin Ehlise2f80292016-06-02 10:08:53 -06002239// Validate given sampler. Currently this only checks to make sure it exists in the samplerMap
Jeremy Gebben9f537102021-10-05 16:37:12 -06002240bool CoreChecks::ValidateSampler(const VkSampler sampler) const { return Get<SAMPLER_STATE>(sampler).get() != nullptr; }
Tobin Ehlis56a30942016-05-19 08:00:00 -06002241
John Zulaufc93c4252019-06-25 09:19:49 -06002242bool CoreChecks::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type,
John Zulaufbd9b3412019-08-22 17:16:11 -06002243 const char *func_name, std::string *error_code, std::string *error_msg) const {
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06002244 auto iv_state = Get<IMAGE_VIEW_STATE>(image_view);
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002245 assert(iv_state);
2246
Tobin Ehlis81280962016-07-20 14:04:20 -06002247 // Note that when an imageview is created, we validated that memory is bound so no need to re-check here
Tobin Ehlis1809f912016-05-25 09:24:36 -06002248 // Validate that imageLayout is compatible with aspect_mask and image format
2249 // and validate that image usage bits are correct for given usage
Jeremy Gebbenb4d17012021-07-08 13:18:15 -06002250 VkImageAspectFlags aspect_mask = iv_state->normalized_subresource_range.aspectMask;
Tobin Ehlis8b26a382016-09-14 08:02:49 -06002251 VkImage image = iv_state->create_info.image;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002252 VkFormat format = VK_FORMAT_MAX_ENUM;
2253 VkImageUsageFlags usage = 0;
Jeremy Gebben057f9d52021-11-05 14:12:31 -06002254 auto *image_node = iv_state->image_state.get();
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002255 assert(image_node);
Chris Forbes67757ff2017-07-21 13:59:01 -07002256
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002257 format = image_node->createInfo.format;
2258 usage = image_node->createInfo.usage;
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07002259 const auto stencil_usage_info = LvlFindInChain<VkImageStencilUsageCreateInfo>(image_node->createInfo.pNext);
Ricardo Garcia3f5984c2020-04-09 10:56:34 +02002260 if (stencil_usage_info) {
2261 usage |= stencil_usage_info->stencilUsage;
2262 }
Mark Lobodzinski03d00062020-06-15 14:35:45 -06002263
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002264 // Validate that memory is bound to image
sfricke-samsung52dbd082021-09-23 11:17:58 -07002265 if (ValidateMemoryIsBoundToImage(image_node, func_name, kVUID_Core_Bound_Resource_FreedMemoryAccess)) {
2266 *error_code = kVUID_Core_Bound_Resource_FreedMemoryAccess;
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002267 *error_msg = "No memory bound to image.";
Tobin Ehlis1809f912016-05-25 09:24:36 -06002268 return false;
2269 }
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002270
2271 // KHR_maintenance1 allows rendering into 2D or 2DArray views which slice a 3D image,
2272 // but not binding them to descriptor sets.
Jeremy Gebben11a68a32021-07-29 11:59:22 -06002273 if (iv_state->IsDepthSliced()) {
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002274 *error_code = "VUID-VkDescriptorImageInfo-imageView-00343";
2275 *error_msg = "ImageView must not be a 2D or 2DArray view of a 3D image";
2276 return false;
2277 }
2278
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002279 // TODO : The various image aspect and format checks here are based on general spec language in 11.5 Image Views section under
2280 // vkCreateImageView(). What's the best way to create unique id for these cases?
sfricke-samsung52dbd082021-09-23 11:17:58 -07002281 *error_code = kVUID_Core_DrawState_InvalidImageView;
Dave Houlton1d2022c2017-03-29 11:43:58 -06002282 bool ds = FormatIsDepthOrStencil(format);
Tobin Ehlis1809f912016-05-25 09:24:36 -06002283 switch (image_layout) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002284 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
2285 // Only Color bit must be set
2286 if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
Tobin Ehlis1809f912016-05-25 09:24:36 -06002287 std::stringstream error_str;
Dave Houltona9df0ce2018-02-07 10:51:23 -07002288 error_str
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002289 << "ImageView (" << report_data->FormatHandle(image_view)
Dave Houltona9df0ce2018-02-07 10:51:23 -07002290 << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but does not have VK_IMAGE_ASPECT_COLOR_BIT set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002291 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -06002292 return false;
2293 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002294 // format must NOT be DS
2295 if (ds) {
2296 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002297 error_str << "ImageView (" << report_data->FormatHandle(image_view)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002298 << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but the image format is "
2299 << string_VkFormat(format) << " which is not a color format.";
2300 *error_msg = error_str.str();
2301 return false;
2302 }
2303 break;
2304 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
2305 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2306 // Depth or stencil bit must be set, but both must NOT be set
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06002307 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
2308 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
2309 // both must NOT be set
2310 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002311 error_str << "ImageView (" << report_data->FormatHandle(image_view)
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002312 << ") has both STENCIL and DEPTH aspects set";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002313 *error_msg = error_str.str();
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06002314 return false;
2315 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002316 } else if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
2317 // Neither were set
2318 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002319 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002320 << string_VkImageLayout(image_layout) << " but does not have STENCIL or DEPTH aspects set";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002321 *error_msg = error_str.str();
2322 return false;
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06002323 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002324 // format must be DS
2325 if (!ds) {
2326 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002327 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002328 << string_VkImageLayout(image_layout) << " but the image format is " << string_VkFormat(format)
2329 << " which is not a depth/stencil format.";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002330 *error_msg = error_str.str();
2331 return false;
2332 }
2333 break;
2334 default:
2335 // For other layouts if the source is depth/stencil image, both aspect bits must not be set
2336 if (ds) {
2337 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
2338 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
2339 // both must NOT be set
2340 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002341 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002342 << string_VkImageLayout(image_layout) << " and is using depth/stencil image of format "
2343 << string_VkFormat(format)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002344 << " but it has both STENCIL and DEPTH aspects set, which is illegal. When using a depth/stencil "
2345 "image in a descriptor set, please only set either VK_IMAGE_ASPECT_DEPTH_BIT or "
2346 "VK_IMAGE_ASPECT_STENCIL_BIT depending on whether it will be used for depth reads or stencil "
2347 "reads respectively.";
Mark Lobodzinski4d05d7a2019-06-25 09:12:06 -06002348 *error_code = "VUID-VkDescriptorImageInfo-imageView-01976";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002349 *error_msg = error_str.str();
2350 return false;
2351 }
2352 }
2353 }
2354 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002355 }
2356 // Now validate that usage flags are correctly set for given type of update
Tobin Ehlisfb4cf712016-10-10 14:02:48 -06002357 // As we're switching per-type, if any type has specific layout requirements, check those here as well
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002358 // TODO : The various image usage bit requirements are in general spec language for VkImageUsageFlags bit block in 11.3 Images
2359 // under vkCreateImage()
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002360 const char *error_usage_bit = nullptr;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002361 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002362 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
sfricke-samsung088f1242020-06-06 02:15:35 -07002363 if (iv_state->samplerConversion != VK_NULL_HANDLE) {
2364 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-01946";
2365 std::stringstream error_str;
2366 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ")"
2367 << "used as a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE can't be created with VkSamplerYcbcrConversion";
2368 *error_msg = error_str.str();
2369 return false;
2370 }
2371 // drop through
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002372 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
2373 if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
2374 error_usage_bit = "VK_IMAGE_USAGE_SAMPLED_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08002375 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00337";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002376 }
2377 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002378 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002379 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
2380 if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
2381 error_usage_bit = "VK_IMAGE_USAGE_STORAGE_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08002382 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00339";
sfricke-samsung45996a42021-09-16 13:45:27 -07002383 } else if ((VK_IMAGE_LAYOUT_GENERAL != image_layout) &&
2384 (!IsExtEnabled(device_extensions.vk_khr_shared_presentable_image) ||
2385 (VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR != image_layout))) {
sfricke-samsungf1058982020-09-10 22:36:49 -07002386 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04152";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002387 std::stringstream error_str;
sfricke-samsungada55a12020-08-15 03:39:41 -07002388 error_str << "Descriptor update with descriptorType VK_DESCRIPTOR_TYPE_STORAGE_IMAGE"
2389 << " is being updated with invalid imageLayout " << string_VkImageLayout(image_layout) << " for image "
2390 << report_data->FormatHandle(image) << " in imageView " << report_data->FormatHandle(image_view)
2391 << ". Allowed layouts are: VK_IMAGE_LAYOUT_GENERAL";
sfricke-samsung45996a42021-09-16 13:45:27 -07002392 if (IsExtEnabled(device_extensions.vk_khr_shared_presentable_image)) {
sfricke-samsungada55a12020-08-15 03:39:41 -07002393 error_str << " or VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR";
Tobin Ehlisbb03e5f2017-05-11 08:52:51 -06002394 }
sfricke-samsungada55a12020-08-15 03:39:41 -07002395 *error_msg = error_str.str();
2396 return false;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002397 }
2398 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002399 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002400 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
2401 if (!(usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
2402 error_usage_bit = "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08002403 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00338";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002404 }
2405 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002406 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002407 default:
2408 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002409 }
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002410 if (error_usage_bit) {
Tobin Ehlis1809f912016-05-25 09:24:36 -06002411 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002412 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") with usage mask " << std::hex << std::showbase
2413 << usage << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have "
2414 << error_usage_bit << " set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002415 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -06002416 return false;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002417 }
John Zulauff4c07882019-01-24 14:03:36 -07002418
sfricke-samsungada55a12020-08-15 03:39:41 -07002419 // All the following types share the same image layouts
2420 // checkf or Storage Images above
2421 if ((type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) || (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
2422 (type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
John Zulauff4c07882019-01-24 14:03:36 -07002423 // Test that the layout is compatible with the descriptorType for the two sampled image types
2424 const static std::array<VkImageLayout, 3> valid_layouts = {
Jeremy Hayesd0549f62019-06-05 10:15:36 -06002425 {VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL}};
John Zulauff4c07882019-01-24 14:03:36 -07002426
2427 struct ExtensionLayout {
2428 VkImageLayout layout;
Tony-LunarG2ec96bb2019-11-26 13:43:02 -07002429 ExtEnabled DeviceExtensions::*extension;
John Zulauff4c07882019-01-24 14:03:36 -07002430 };
Ricardo Garcia602c2022021-07-30 10:42:17 +02002431 const static std::array<ExtensionLayout, 7> extended_layouts{{
Jeremy Gebben579aaca2021-02-15 13:36:18 -07002432 // Note double brace req'd for aggregate initialization
2433 {VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR, &DeviceExtensions::vk_khr_shared_presentable_image},
2434 {VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, &DeviceExtensions::vk_khr_maintenance2},
2435 {VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, &DeviceExtensions::vk_khr_maintenance2},
Mike Schuchardtc57de4a2021-07-20 17:26:32 -07002436 {VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, &DeviceExtensions::vk_khr_synchronization2},
2437 {VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, &DeviceExtensions::vk_khr_synchronization2},
Ricardo Garcia602c2022021-07-30 10:42:17 +02002438 {VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, &DeviceExtensions::vk_khr_separate_depth_stencil_layouts},
2439 {VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, &DeviceExtensions::vk_khr_separate_depth_stencil_layouts},
Jeremy Gebben579aaca2021-02-15 13:36:18 -07002440 }};
John Zulaufc93c4252019-06-25 09:19:49 -06002441 auto is_layout = [image_layout, this](const ExtensionLayout &ext_layout) {
sfricke-samsung45996a42021-09-16 13:45:27 -07002442 return IsExtEnabled(device_extensions.*(ext_layout.extension)) && (ext_layout.layout == image_layout);
John Zulauff4c07882019-01-24 14:03:36 -07002443 };
2444
2445 bool valid_layout = (std::find(valid_layouts.cbegin(), valid_layouts.cend(), image_layout) != valid_layouts.cend()) ||
2446 std::any_of(extended_layouts.cbegin(), extended_layouts.cend(), is_layout);
2447
2448 if (!valid_layout) {
sfricke-samsungf1058982020-09-10 22:36:49 -07002449 // The following works as currently all 3 descriptor types share the same set of valid layouts
sfricke-samsungada55a12020-08-15 03:39:41 -07002450 switch (type) {
2451 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
Shannon McPherson2c793ba2020-08-28 12:13:24 -06002452 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04149";
sfricke-samsungada55a12020-08-15 03:39:41 -07002453 break;
2454 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
Shannon McPherson2c793ba2020-08-28 12:13:24 -06002455 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04150";
sfricke-samsungada55a12020-08-15 03:39:41 -07002456 break;
2457 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
sfricke-samsungf1058982020-09-10 22:36:49 -07002458 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04151";
sfricke-samsungada55a12020-08-15 03:39:41 -07002459 break;
2460 default:
2461 break;
2462 }
John Zulauff4c07882019-01-24 14:03:36 -07002463 std::stringstream error_str;
2464 error_str << "Descriptor update with descriptorType " << string_VkDescriptorType(type)
Mark Lobodzinski74eddba2019-06-21 14:16:33 -06002465 << " is being updated with invalid imageLayout " << string_VkImageLayout(image_layout) << " for image "
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002466 << report_data->FormatHandle(image) << " in imageView " << report_data->FormatHandle(image_view)
John Zulauff4c07882019-01-24 14:03:36 -07002467 << ". Allowed layouts are: VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "
2468 << "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL";
2469 for (auto &ext_layout : extended_layouts) {
sfricke-samsung45996a42021-09-16 13:45:27 -07002470 if (IsExtEnabled(device_extensions.*(ext_layout.extension))) {
John Zulauff4c07882019-01-24 14:03:36 -07002471 error_str << ", " << string_VkImageLayout(ext_layout.layout);
2472 }
2473 }
2474 *error_msg = error_str.str();
2475 return false;
2476 }
2477 }
2478
sfricke-samsungbd0e8052020-06-06 01:36:39 -07002479 if ((type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) || (type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
2480 const VkComponentMapping components = iv_state->create_info.components;
2481 if (IsIdentitySwizzle(components) == false) {
2482 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00336";
2483 std::stringstream error_str;
2484 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has a non-identiy swizzle component, "
2485 << " r swizzle = " << string_VkComponentSwizzle(components.r) << ","
2486 << " g swizzle = " << string_VkComponentSwizzle(components.g) << ","
2487 << " b swizzle = " << string_VkComponentSwizzle(components.b) << ","
2488 << " a swizzle = " << string_VkComponentSwizzle(components.a) << ".";
2489 *error_msg = error_str.str();
2490 return false;
2491 }
2492 }
2493
Tony-LunarG69604c42021-11-22 16:00:12 -07002494 if ((type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) && (iv_state->min_lod != 0.0f)) {
2495 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-06450";
2496 std::stringstream error_str;
2497 error_str << "ImageView (" << report_data->FormatHandle(image_view)
2498 << ") , written to a descriptor of type VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT with a minLod (" << iv_state->min_lod
2499 << ") that is not 0.0";
2500 *error_msg = error_str.str();
2501 return false;
2502 }
2503
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002504 return true;
2505}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002506
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002507// Helper template to change shared pointer members of a Descriptor, while
2508// correctly managing links to the parent DescriptorSet.
2509// src and dst are shared pointers.
2510template <typename T>
2511static void ReplaceStatePtr(DescriptorSet *set_state, T &dst, const T &src) {
2512 if (dst) {
2513 dst->RemoveParent(set_state);
2514 }
2515 dst = src;
2516 if (dst) {
2517 dst->AddParent(set_state);
2518 }
2519}
2520
2521void cvdescriptorset::SamplerDescriptor::WriteUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2522 const VkWriteDescriptorSet *update, const uint32_t index) {
Chris Forbesfea2c542018-04-13 09:34:15 -07002523 if (!immutable_) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002524 ReplaceStatePtr(set_state, sampler_state_ , dev_data->GetConstCastShared<SAMPLER_STATE>(update->pImageInfo[index].sampler));
Chris Forbesfea2c542018-04-13 09:34:15 -07002525 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002526 updated = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002527}
2528
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002529void cvdescriptorset::SamplerDescriptor::CopyUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2530 const Descriptor *src) {
Tony-LunarG80358322021-04-16 07:58:13 -06002531 updated = true;
2532 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2533 if (src->descriptor_class == Mutable) {
2534 this->descriptor_class = Mutable;
2535 return;
2536 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002537 auto *sampler_src = static_cast<const SamplerDescriptor *>(src);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002538 if (!immutable_) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002539 ReplaceStatePtr(set_state, sampler_state_, sampler_src->sampler_state_);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002540 }
2541}
2542
John Zulaufd2c3dae2019-12-12 11:02:17 -07002543cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(const ValidationStateTracker *dev_data, const VkSampler *immut)
Jeremy Gebben059ab502021-04-26 11:25:02 -06002544 : ImageDescriptor(ImageSampler), immutable_(false) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002545 if (immut) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002546 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(*immut);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002547 immutable_ = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002548 }
2549}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002550
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002551void cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
John Zulaufd2c3dae2019-12-12 11:02:17 -07002552 const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002553 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002554 const auto &image_info = update->pImageInfo[index];
Chris Forbesfea2c542018-04-13 09:34:15 -07002555 if (!immutable_) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002556 ReplaceStatePtr(set_state, sampler_state_, dev_data->GetConstCastShared<SAMPLER_STATE>(image_info.sampler));
Chris Forbesfea2c542018-04-13 09:34:15 -07002557 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002558 image_layout_ = image_info.imageLayout;
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002559 ReplaceStatePtr(set_state, image_view_state_, dev_data->GetConstCastShared<IMAGE_VIEW_STATE>(image_info.imageView));
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002560}
2561
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002562void cvdescriptorset::ImageSamplerDescriptor::CopyUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2563 const Descriptor *src) {
Tony-LunarG80358322021-04-16 07:58:13 -06002564 updated = true;
2565 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2566 if (src->descriptor_class == Mutable) {
2567 this->descriptor_class = Mutable;
2568 return;
2569 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002570 auto *image_src = static_cast<const ImageSamplerDescriptor *>(src);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002571 if (!immutable_) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002572 ReplaceStatePtr(set_state, sampler_state_, image_src->sampler_state_);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002573 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002574 ImageDescriptor::CopyUpdate(set_state, dev_data, src);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002575}
2576
Jeremy Gebben059ab502021-04-26 11:25:02 -06002577cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type)
2578 : Descriptor(Image), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {}
2579
2580cvdescriptorset::ImageDescriptor::ImageDescriptor(DescriptorClass class_)
2581 : Descriptor(class_), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {}
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002582
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002583void cvdescriptorset::ImageDescriptor::WriteUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2584 const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002585 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002586 const auto &image_info = update->pImageInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06002587 image_layout_ = image_info.imageLayout;
Karl Schultz76d16a42020-11-11 05:05:33 -07002588 image_view_state_ = dev_data->GetConstCastShared<IMAGE_VIEW_STATE>(image_info.imageView);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002589}
2590
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002591void cvdescriptorset::ImageDescriptor::CopyUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2592 const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002593 updated = true;
Tony-LunarG80358322021-04-16 07:58:13 -06002594 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2595 if (src->descriptor_class == Mutable) {
2596 this->descriptor_class = Mutable;
2597 return;
2598 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002599 auto *image_src = static_cast<const ImageDescriptor *>(src);
Tony-LunarG80358322021-04-16 07:58:13 -06002600
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002601 image_layout_ = image_src->image_layout_;
2602 ReplaceStatePtr(set_state, image_view_state_, image_src->image_view_state_);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002603}
2604
John Zulauffbf3c202019-07-17 14:57:14 -06002605void cvdescriptorset::ImageDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Tobin Ehlis81e46372016-08-17 13:33:44 -06002606 // Add binding for image
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002607 auto iv_state = GetImageViewState();
Tobin Ehlis8b26a382016-09-14 08:02:49 -06002608 if (iv_state) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002609 dev_data->CallSetImageViewInitialLayoutCallback(cb_node, *iv_state, image_layout_);
Jeff Bolz148d94e2018-12-13 21:25:56 -06002610 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002611}
2612
Jeremy Gebben059ab502021-04-26 11:25:02 -06002613cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type)
2614 : Descriptor(GeneralBuffer), offset_(0), range_(0) {}
2615
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002616void cvdescriptorset::BufferDescriptor::WriteUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2617 const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002618 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002619 const auto &buffer_info = update->pBufferInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06002620 offset_ = buffer_info.offset;
2621 range_ = buffer_info.range;
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002622 ReplaceStatePtr(set_state, buffer_state_, dev_data->GetConstCastShared<BUFFER_STATE>(buffer_info.buffer));
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002623}
2624
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002625void cvdescriptorset::BufferDescriptor::CopyUpdate(DescriptorSet* set_state, const ValidationStateTracker *dev_data,
2626 const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002627 updated = true;
Tony-LunarG80358322021-04-16 07:58:13 -06002628 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2629 if (src->descriptor_class == Mutable) {
2630 this->descriptor_class = Mutable;
2631 return;
2632 }
Karl Schultz76d16a42020-11-11 05:05:33 -07002633 const auto buff_desc = static_cast<const BufferDescriptor *>(src);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002634 offset_ = buff_desc->offset_;
2635 range_ = buff_desc->range_;
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002636 ReplaceStatePtr(set_state, buffer_state_, buff_desc->buffer_state_);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002637}
2638
Jeremy Gebben059ab502021-04-26 11:25:02 -06002639cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type) : Descriptor(TexelBuffer) {}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002640
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002641void cvdescriptorset::TexelDescriptor::WriteUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2642 const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002643 updated = true;
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002644 ReplaceStatePtr(set_state, buffer_view_state_,
2645 dev_data->GetConstCastShared<BUFFER_VIEW_STATE>(update->pTexelBufferView[index]));
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002646}
2647
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002648void cvdescriptorset::TexelDescriptor::CopyUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2649 const Descriptor *src) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002650 updated = true;
Tony-LunarG80358322021-04-16 07:58:13 -06002651 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2652 if (src->descriptor_class == Mutable) {
2653 this->descriptor_class = Mutable;
2654 return;
2655 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002656 ReplaceStatePtr(set_state, buffer_view_state_, static_cast<const TexelDescriptor *>(src)->buffer_view_state_);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002657}
2658
Jeff Bolz95176d02020-04-01 00:36:16 -05002659cvdescriptorset::AccelerationStructureDescriptor::AccelerationStructureDescriptor(const VkDescriptorType type)
Jeremy Gebben059ab502021-04-26 11:25:02 -06002660 : Descriptor(AccelerationStructure), acc_(VK_NULL_HANDLE), acc_nv_(VK_NULL_HANDLE) {
sourav parmarcd5fb182020-07-17 12:58:44 -07002661 is_khr_ = false;
Jeff Bolz95176d02020-04-01 00:36:16 -05002662}
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002663void cvdescriptorset::AccelerationStructureDescriptor::WriteUpdate(DescriptorSet *set_state,
2664 const ValidationStateTracker *dev_data,
Jeff Bolz95176d02020-04-01 00:36:16 -05002665 const VkWriteDescriptorSet *update, const uint32_t index) {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07002666 const auto *acc_info = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureKHR>(update->pNext);
2667 const auto *acc_info_nv = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureNV>(update->pNext);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002668 assert(acc_info || acc_info_nv);
2669 is_khr_ = (acc_info != NULL);
Jeff Bolz95176d02020-04-01 00:36:16 -05002670 updated = true;
sourav parmarcd5fb182020-07-17 12:58:44 -07002671 if (is_khr_) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002672 acc_ = acc_info->pAccelerationStructures[index];
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002673 ReplaceStatePtr(set_state, acc_state_, dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE_KHR>(acc_));
sourav parmarcd5fb182020-07-17 12:58:44 -07002674 } else {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002675 acc_nv_ = acc_info_nv->pAccelerationStructures[index];
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002676 ReplaceStatePtr(set_state, acc_state_nv_, dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE>(acc_nv_));
sourav parmarcd5fb182020-07-17 12:58:44 -07002677 }
Jeff Bolz95176d02020-04-01 00:36:16 -05002678}
2679
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002680void cvdescriptorset::AccelerationStructureDescriptor::CopyUpdate(DescriptorSet *set_state,
2681 const ValidationStateTracker *dev_data, const Descriptor *src) {
Jeff Bolz95176d02020-04-01 00:36:16 -05002682 auto acc_desc = static_cast<const AccelerationStructureDescriptor *>(src);
2683 updated = true;
Tony-LunarG80358322021-04-16 07:58:13 -06002684 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2685 if (src->descriptor_class == Mutable) {
2686 this->descriptor_class = Mutable;
2687 return;
2688 }
sourav parmarcd5fb182020-07-17 12:58:44 -07002689 if (is_khr_) {
2690 acc_ = acc_desc->acc_;
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002691 ReplaceStatePtr(set_state, acc_state_, dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE_KHR>(acc_));
sourav parmarcd5fb182020-07-17 12:58:44 -07002692 } else {
2693 acc_nv_ = acc_desc->acc_nv_;
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002694 ReplaceStatePtr(set_state, acc_state_nv_, dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE>(acc_nv_));
sourav parmarcd5fb182020-07-17 12:58:44 -07002695 }
Jeff Bolz95176d02020-04-01 00:36:16 -05002696}
2697
Jeremy Gebben059ab502021-04-26 11:25:02 -06002698cvdescriptorset::MutableDescriptor::MutableDescriptor() : Descriptor(Mutable) { active_descriptor_class_ = NoDescriptorClass; }
Tony-LunarGf563b362021-03-18 16:13:18 -06002699
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002700void cvdescriptorset::MutableDescriptor::WriteUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
Tony-LunarGf563b362021-03-18 16:13:18 -06002701 const VkWriteDescriptorSet *update, const uint32_t index) {
2702 updated = true;
2703}
2704
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002705void cvdescriptorset::MutableDescriptor::CopyUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2706 const Descriptor *src) {
Tony-LunarGf563b362021-03-18 16:13:18 -06002707 updated = true;
2708}
2709
Tobin Ehlis300888c2016-05-18 13:43:26 -06002710// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
2711// sets, and then calls their respective Validate[Write|Copy]Update functions.
2712// If the update hits an issue for which the callback returns "true", meaning that the call down the chain should
2713// be skipped, then true is returned.
2714// If there is no issue with the update, then false is returned.
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002715bool CoreChecks::ValidateUpdateDescriptorSets(uint32_t write_count, const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05002716 const VkCopyDescriptorSet *p_cds, const char *func_name) const {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002717 bool skip = false;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002718 // Validate Write updates
Tobin Ehlis56a30942016-05-19 08:00:00 -06002719 for (uint32_t i = 0; i < write_count; i++) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002720 auto dest_set = p_wds[i].dstSet;
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06002721 auto set_node = Get<cvdescriptorset::DescriptorSet>(dest_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002722 if (!set_node) {
sfricke-samsungbda4a852021-03-06 20:58:01 -08002723 skip |= LogError(dest_set, kVUID_Core_DrawState_InvalidDescriptorSet,
2724 "Cannot call %s on %s that has not been allocated in pDescriptorWrites[%u].", func_name,
2725 report_data->FormatHandle(dest_set).c_str(), i);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002726 } else {
Dave Houltond8ed0212018-05-16 17:18:24 -06002727 std::string error_code;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002728 std::string error_str;
Jeremy Gebben9f537102021-10-05 16:37:12 -06002729 if (!ValidateWriteUpdate(set_node.get(), &p_wds[i], func_name, &error_code, &error_str, false)) {
sfricke-samsungbda4a852021-03-06 20:58:01 -08002730 skip |=
2731 LogError(dest_set, error_code, "%s pDescriptorWrites[%u] failed write update validation for %s with error: %s.",
2732 func_name, i, report_data->FormatHandle(dest_set).c_str(), error_str.c_str());
Tobin Ehlis300888c2016-05-18 13:43:26 -06002733 }
2734 }
sourav parmara24fb7b2020-05-26 10:50:04 -07002735 if (p_wds[i].pNext) {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07002736 const auto *pnext_struct = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureKHR>(p_wds[i].pNext);
Mark Lobodzinski17dc4602020-05-29 07:48:40 -06002737 if (pnext_struct) {
2738 for (uint32_t j = 0; j < pnext_struct->accelerationStructureCount; ++j) {
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06002739 const auto as_state = Get<ACCELERATION_STRUCTURE_STATE_KHR>(pnext_struct->pAccelerationStructures[j]);
sourav parmarcd5fb182020-07-17 12:58:44 -07002740 if (as_state && (as_state->create_infoKHR.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR &&
sourav parmar766e2a72020-12-03 16:17:11 -08002741 (as_state->create_infoKHR.type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR &&
2742 as_state->create_infoKHR.type != VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR))) {
sourav parmara24fb7b2020-05-26 10:50:04 -07002743 skip |=
sourav parmarcd5fb182020-07-17 12:58:44 -07002744 LogError(dest_set, "VUID-VkWriteDescriptorSetAccelerationStructureKHR-pAccelerationStructures-03579",
sfricke-samsungbda4a852021-03-06 20:58:01 -08002745 "%s: For pDescriptorWrites[%u] acceleration structure in pAccelerationStructures[%u] must "
2746 "have been created with "
sourav parmarbcee7512020-12-28 14:34:49 -08002747 "VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR or VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR.",
sfricke-samsungbda4a852021-03-06 20:58:01 -08002748 func_name, i, j);
sourav parmara24fb7b2020-05-26 10:50:04 -07002749 }
2750 }
2751 }
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07002752 const auto *pnext_struct_nv = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureNV>(p_wds[i].pNext);
sourav parmarcd5fb182020-07-17 12:58:44 -07002753 if (pnext_struct_nv) {
2754 for (uint32_t j = 0; j < pnext_struct_nv->accelerationStructureCount; ++j) {
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06002755 const auto as_state = Get<ACCELERATION_STRUCTURE_STATE>(pnext_struct_nv->pAccelerationStructures[j]);
sourav parmarcd5fb182020-07-17 12:58:44 -07002756 if (as_state && (as_state->create_infoNV.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV &&
2757 as_state->create_infoNV.info.type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV)) {
2758 skip |= LogError(dest_set, "VUID-VkWriteDescriptorSetAccelerationStructureNV-pAccelerationStructures-03748",
sfricke-samsungbda4a852021-03-06 20:58:01 -08002759 "%s: For pDescriptorWrites[%u] acceleration structure in pAccelerationStructures[%u] must "
2760 "have been created with"
sourav parmarcd5fb182020-07-17 12:58:44 -07002761 " VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV.",
sfricke-samsungbda4a852021-03-06 20:58:01 -08002762 func_name, i, j);
sourav parmarcd5fb182020-07-17 12:58:44 -07002763 }
2764 }
2765 }
sourav parmara24fb7b2020-05-26 10:50:04 -07002766 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002767 }
2768 // Now validate copy updates
Tobin Ehlis56a30942016-05-19 08:00:00 -06002769 for (uint32_t i = 0; i < copy_count; ++i) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002770 auto dst_set = p_cds[i].dstSet;
2771 auto src_set = p_cds[i].srcSet;
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06002772 auto src_node = Get<cvdescriptorset::DescriptorSet>(src_set);
2773 auto dst_node = Get<cvdescriptorset::DescriptorSet>(dst_set);
Tobin Ehlisa1712752017-01-04 09:41:47 -07002774 // Object_tracker verifies that src & dest descriptor set are valid
2775 assert(src_node);
2776 assert(dst_node);
Dave Houltond8ed0212018-05-16 17:18:24 -06002777 std::string error_code;
Tobin Ehlisa1712752017-01-04 09:41:47 -07002778 std::string error_str;
Jeremy Gebben9f537102021-10-05 16:37:12 -06002779 if (!ValidateCopyUpdate(&p_cds[i], dst_node.get(), src_node.get(), func_name, &error_code, &error_str)) {
Mark Lobodzinski9d38ea22020-03-16 18:22:16 -06002780 LogObjectList objlist(dst_set);
2781 objlist.add(src_set);
sfricke-samsungbda4a852021-03-06 20:58:01 -08002782 skip |= LogError(objlist, error_code, "%s pDescriptorCopies[%u] failed copy update from %s to %s with error: %s.",
2783 func_name, i, report_data->FormatHandle(src_set).c_str(), report_data->FormatHandle(dst_set).c_str(),
2784 error_str.c_str());
Tobin Ehlis300888c2016-05-18 13:43:26 -06002785 }
2786 }
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002787 return skip;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002788}
2789// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
2790// sets, and then calls their respective Perform[Write|Copy]Update functions.
2791// Prerequisite : ValidateUpdateDescriptorSets() should be called and return "false" prior to calling PerformUpdateDescriptorSets()
2792// with the same set of updates.
2793// This is split from the validate code to allow validation prior to calling down the chain, and then update after
2794// calling down the chain.
John Zulaufe3b35f32019-06-25 14:21:21 -06002795void cvdescriptorset::PerformUpdateDescriptorSets(ValidationStateTracker *dev_data, uint32_t write_count,
2796 const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
2797 const VkCopyDescriptorSet *p_cds) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002798 // Write updates first
2799 uint32_t i = 0;
2800 for (i = 0; i < write_count; ++i) {
2801 auto dest_set = p_wds[i].dstSet;
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06002802 auto set_node = dev_data->Get<cvdescriptorset::DescriptorSet>(dest_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002803 if (set_node) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05002804 set_node->PerformWriteUpdate(dev_data, &p_wds[i]);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002805 }
2806 }
2807 // Now copy updates
2808 for (i = 0; i < copy_count; ++i) {
2809 auto dst_set = p_cds[i].dstSet;
2810 auto src_set = p_cds[i].srcSet;
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06002811 auto src_node = dev_data->Get<cvdescriptorset::DescriptorSet>(src_set);
2812 auto dst_node = dev_data->Get<cvdescriptorset::DescriptorSet>(dst_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002813 if (src_node && dst_node) {
Jeremy Gebben9f537102021-10-05 16:37:12 -06002814 dst_node->PerformCopyUpdate(dev_data, &p_cds[i], src_node.get());
Tobin Ehlis300888c2016-05-18 13:43:26 -06002815 }
2816 }
2817}
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002818
John Zulaufe3b35f32019-06-25 14:21:21 -06002819cvdescriptorset::DecodedTemplateUpdate::DecodedTemplateUpdate(const ValidationStateTracker *device_data,
Jeremy Gebbenfc890452021-10-27 10:56:49 -06002820 VkDescriptorSet descriptorSet,
2821 const UPDATE_TEMPLATE_STATE *template_state, const void *pData,
2822 VkDescriptorSetLayout push_layout) {
John Zulaufb845eb22018-10-12 11:41:06 -06002823 auto const &create_info = template_state->create_info;
2824 inline_infos.resize(create_info.descriptorUpdateEntryCount); // Make sure we have one if we need it
sourav parmar480d2772021-01-24 22:24:54 -08002825 inline_infos_khr.resize(create_info.descriptorUpdateEntryCount);
2826 inline_infos_nv.resize(create_info.descriptorUpdateEntryCount);
John Zulaufb845eb22018-10-12 11:41:06 -06002827 desc_writes.reserve(create_info.descriptorUpdateEntryCount); // emplaced, so reserved without initialization
John Zulauf1d27e0a2018-11-05 10:12:48 -07002828 VkDescriptorSetLayout effective_dsl = create_info.templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
2829 ? create_info.descriptorSetLayout
2830 : push_layout;
Jeremy Gebben9f537102021-10-05 16:37:12 -06002831 auto layout_obj = device_data->Get<cvdescriptorset::DescriptorSetLayout>(effective_dsl);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002832
2833 // Create a WriteDescriptorSet struct for each template update entry
2834 for (uint32_t i = 0; i < create_info.descriptorUpdateEntryCount; i++) {
2835 auto binding_count = layout_obj->GetDescriptorCountFromBinding(create_info.pDescriptorUpdateEntries[i].dstBinding);
2836 auto binding_being_updated = create_info.pDescriptorUpdateEntries[i].dstBinding;
2837 auto dst_array_element = create_info.pDescriptorUpdateEntries[i].dstArrayElement;
2838
John Zulaufb6d71202017-12-22 16:47:09 -07002839 desc_writes.reserve(desc_writes.size() + create_info.pDescriptorUpdateEntries[i].descriptorCount);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002840 for (uint32_t j = 0; j < create_info.pDescriptorUpdateEntries[i].descriptorCount; j++) {
2841 desc_writes.emplace_back();
2842 auto &write_entry = desc_writes.back();
2843
2844 size_t offset = create_info.pDescriptorUpdateEntries[i].offset + j * create_info.pDescriptorUpdateEntries[i].stride;
2845 char *update_entry = (char *)(pData) + offset;
2846
2847 if (dst_array_element >= binding_count) {
2848 dst_array_element = 0;
Mark Lobodzinski4aa479d2017-03-10 09:14:00 -07002849 binding_being_updated = layout_obj->GetNextValidBinding(binding_being_updated);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002850 }
2851
2852 write_entry.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2853 write_entry.pNext = NULL;
2854 write_entry.dstSet = descriptorSet;
2855 write_entry.dstBinding = binding_being_updated;
2856 write_entry.dstArrayElement = dst_array_element;
2857 write_entry.descriptorCount = 1;
2858 write_entry.descriptorType = create_info.pDescriptorUpdateEntries[i].descriptorType;
2859
2860 switch (create_info.pDescriptorUpdateEntries[i].descriptorType) {
2861 case VK_DESCRIPTOR_TYPE_SAMPLER:
2862 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2863 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2864 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2865 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2866 write_entry.pImageInfo = reinterpret_cast<VkDescriptorImageInfo *>(update_entry);
2867 break;
2868
2869 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2870 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2871 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2872 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2873 write_entry.pBufferInfo = reinterpret_cast<VkDescriptorBufferInfo *>(update_entry);
2874 break;
2875
2876 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2877 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2878 write_entry.pTexelBufferView = reinterpret_cast<VkBufferView *>(update_entry);
2879 break;
Dave Houlton142c4cb2018-10-17 15:04:41 -06002880 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: {
2881 VkWriteDescriptorSetInlineUniformBlockEXT *inline_info = &inline_infos[i];
2882 inline_info->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT;
2883 inline_info->pNext = nullptr;
2884 inline_info->dataSize = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2885 inline_info->pData = update_entry;
2886 write_entry.pNext = inline_info;
Ricardo Garciafee15732019-05-28 11:13:31 +02002887 // descriptorCount must match the dataSize member of the VkWriteDescriptorSetInlineUniformBlockEXT structure
2888 write_entry.descriptorCount = inline_info->dataSize;
Dave Houlton142c4cb2018-10-17 15:04:41 -06002889 // skip the rest of the array, they just represent bytes in the update
2890 j = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2891 break;
2892 }
sourav parmar480d2772021-01-24 22:24:54 -08002893 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: {
2894 VkWriteDescriptorSetAccelerationStructureKHR *inline_info_khr = &inline_infos_khr[i];
2895 inline_info_khr->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
2896 inline_info_khr->pNext = nullptr;
2897 inline_info_khr->accelerationStructureCount = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2898 inline_info_khr->pAccelerationStructures = reinterpret_cast<VkAccelerationStructureKHR *>(update_entry);
2899 write_entry.pNext = inline_info_khr;
2900 break;
2901 }
2902 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: {
2903 VkWriteDescriptorSetAccelerationStructureNV *inline_info_nv = &inline_infos_nv[i];
2904 inline_info_nv->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV;
2905 inline_info_nv->pNext = nullptr;
2906 inline_info_nv->accelerationStructureCount = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2907 inline_info_nv->pAccelerationStructures = reinterpret_cast<VkAccelerationStructureNV *>(update_entry);
2908 write_entry.pNext = inline_info_nv;
2909 break;
2910 }
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002911 default:
2912 assert(0);
2913 break;
2914 }
2915 dst_array_element++;
2916 }
2917 }
John Zulaufb845eb22018-10-12 11:41:06 -06002918}
John Zulaufb45fdc32018-10-12 15:14:17 -06002919// These helper functions carry out the validate and record descriptor updates peformed via update templates. They decode
2920// the templatized data and leverage the non-template UpdateDescriptor helper functions.
Jeremy Gebbenfc890452021-10-27 10:56:49 -06002921bool CoreChecks::ValidateUpdateDescriptorSetsWithTemplateKHR(VkDescriptorSet descriptorSet,
2922 const UPDATE_TEMPLATE_STATE *template_state, const void *pData) const {
John Zulaufb45fdc32018-10-12 15:14:17 -06002923 // Translate the templated update into a normal update for validation...
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002924 cvdescriptorset::DecodedTemplateUpdate decoded_update(this, descriptorSet, template_state, pData);
2925 return ValidateUpdateDescriptorSets(static_cast<uint32_t>(decoded_update.desc_writes.size()), decoded_update.desc_writes.data(),
2926 0, NULL, "vkUpdateDescriptorSetWithTemplate()");
John Zulaufb45fdc32018-10-12 15:14:17 -06002927}
John Zulaufb845eb22018-10-12 11:41:06 -06002928
John Zulauf4e7bcb52018-11-02 10:46:30 -06002929std::string cvdescriptorset::DescriptorSet::StringifySetAndLayout() const {
2930 std::string out;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002931 auto layout_handle = layout_->GetDescriptorSetLayout();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002932 if (IsPushDescriptor()) {
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002933 std::ostringstream str;
Tony-LunarG1d3ee2d2020-10-27 15:54:52 -06002934 str << "Push Descriptors defined with " << state_data_->report_data->FormatHandle(layout_handle);
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002935 out = str.str();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002936 } else {
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002937 std::ostringstream str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002938 str << state_data_->report_data->FormatHandle(GetSet()) << " allocated with "
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002939 << state_data_->report_data->FormatHandle(layout_handle);
2940 out = str.str();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002941 }
2942 return out;
2943};
2944
John Zulauf1d27e0a2018-11-05 10:12:48 -07002945// Loop through the write updates to validate for a push descriptor set, ignoring dstSet
John Zulaufc93c4252019-06-25 09:19:49 -06002946bool CoreChecks::ValidatePushDescriptorsUpdate(const DescriptorSet *push_set, uint32_t write_count,
John Zulaufbd9b3412019-08-22 17:16:11 -06002947 const VkWriteDescriptorSet *p_wds, const char *func_name) const {
John Zulaufd9435c32019-06-05 15:55:36 -06002948 assert(push_set->IsPushDescriptor());
John Zulauf1d27e0a2018-11-05 10:12:48 -07002949 bool skip = false;
2950 for (uint32_t i = 0; i < write_count; i++) {
2951 std::string error_code;
2952 std::string error_str;
ziga-lunarg6c46b242021-09-13 18:33:37 +02002953 if (!ValidateWriteUpdate(push_set, &p_wds[i], func_name, &error_code, &error_str, true)) {
sfricke-samsungbda4a852021-03-06 20:58:01 -08002954 skip |= LogError(push_set->GetDescriptorSetLayout(), error_code,
2955 "%s VkWriteDescriptorSet[%u] failed update validation: %s.", func_name, i, error_str.c_str());
John Zulauf1d27e0a2018-11-05 10:12:48 -07002956 }
2957 }
2958 return skip;
2959}
2960
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002961// For the given buffer, verify that its creation parameters are appropriate for the given type
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002962// If there's an error, update the error_msg string with details and return false, else return true
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002963bool cvdescriptorset::ValidateBufferUsage(debug_report_data *report_data, BUFFER_STATE const *buffer_node, VkDescriptorType type,
2964 std::string *error_code, std::string *error_msg) {
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002965 // Verify that usage bits set correctly for given type
Tobin Ehlis94bc5d22016-06-02 07:46:52 -06002966 auto usage = buffer_node->createInfo.usage;
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002967 const char *error_usage_bit = nullptr;
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002968 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002969 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2970 if (!(usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002971 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00334";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002972 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT";
2973 }
2974 break;
2975 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2976 if (!(usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002977 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00335";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002978 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT";
2979 }
2980 break;
2981 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2982 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2983 if (!(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002984 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00330";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002985 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT";
2986 }
2987 break;
2988 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2989 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2990 if (!(usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002991 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00331";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002992 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT";
2993 }
2994 break;
2995 default:
2996 break;
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002997 }
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002998 if (error_usage_bit) {
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002999 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003000 error_str << "Buffer (" << report_data->FormatHandle(buffer_node->buffer()) << ") with usage mask " << std::hex
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003001 << std::showbase << usage << " being used for a descriptor update of type " << string_VkDescriptorType(type)
3002 << " does not have " << error_usage_bit << " set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06003003 *error_msg = error_str.str();
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06003004 return false;
3005 }
3006 return true;
3007}
Tobin Ehlis3d38f082016-07-01 17:36:48 -06003008// For buffer descriptor updates, verify the buffer usage and VkDescriptorBufferInfo struct which includes:
3009// 1. buffer is valid
3010// 2. buffer was created with correct usage flags
3011// 3. offset is less than buffer size
3012// 4. range is either VK_WHOLE_SIZE or falls in (0, (buffer size - offset)]
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07003013// 5. range and offset are within the device's limits
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06003014// If there's an error, update the error_msg string with details and return false, else return true
John Zulaufc93c4252019-06-25 09:19:49 -06003015bool CoreChecks::ValidateBufferUpdate(VkDescriptorBufferInfo const *buffer_info, VkDescriptorType type, const char *func_name,
John Zulaufbd9b3412019-08-22 17:16:11 -06003016 std::string *error_code, std::string *error_msg) const {
Tobin Ehlis3d38f082016-07-01 17:36:48 -06003017 // First make sure that buffer is valid
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06003018 auto buffer_node = Get<BUFFER_STATE>(buffer_info->buffer);
Tobin Ehlisfa8b6182016-12-22 13:40:45 -07003019 // Any invalid buffer should already be caught by object_tracker
3020 assert(buffer_node);
Jeremy Gebben9f537102021-10-05 16:37:12 -06003021 if (ValidateMemoryIsBoundToBuffer(buffer_node.get(), func_name, "VUID-VkWriteDescriptorSet-descriptorType-00329")) {
Dave Houlton00c154e2018-05-24 13:20:50 -06003022 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00329";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06003023 *error_msg = "No memory bound to buffer.";
Tobin Ehlis81280962016-07-20 14:04:20 -06003024 return false;
Tobin Ehlisfed999f2016-09-21 15:09:45 -06003025 }
Tobin Ehlis3d38f082016-07-01 17:36:48 -06003026 // Verify usage bits
Jeremy Gebben9f537102021-10-05 16:37:12 -06003027 if (!cvdescriptorset::ValidateBufferUsage(report_data, buffer_node.get(), type, error_code, error_msg)) {
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06003028 // error_msg will have been updated by ValidateBufferUsage()
Tobin Ehlis3d38f082016-07-01 17:36:48 -06003029 return false;
3030 }
3031 // offset must be less than buffer size
Jeremy Hayesd1a6a822017-03-09 14:39:45 -07003032 if (buffer_info->offset >= buffer_node->createInfo.size) {
Dave Houlton00c154e2018-05-24 13:20:50 -06003033 *error_code = "VUID-VkDescriptorBufferInfo-offset-00340";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06003034 std::stringstream error_str;
Jeremy Hayesd1a6a822017-03-09 14:39:45 -07003035 error_str << "VkDescriptorBufferInfo offset of " << buffer_info->offset << " is greater than or equal to buffer "
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003036 << report_data->FormatHandle(buffer_node->buffer()) << " size of " << buffer_node->createInfo.size;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06003037 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06003038 return false;
3039 }
3040 if (buffer_info->range != VK_WHOLE_SIZE) {
3041 // Range must be VK_WHOLE_SIZE or > 0
3042 if (!buffer_info->range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06003043 *error_code = "VUID-VkDescriptorBufferInfo-range-00341";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06003044 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003045 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer())
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003046 << " VkDescriptorBufferInfo range is not VK_WHOLE_SIZE and is zero, which is not allowed.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06003047 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06003048 return false;
3049 }
3050 // Range must be VK_WHOLE_SIZE or <= (buffer size - offset)
3051 if (buffer_info->range > (buffer_node->createInfo.size - buffer_info->offset)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06003052 *error_code = "VUID-VkDescriptorBufferInfo-range-00342";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06003053 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003054 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer()) << " VkDescriptorBufferInfo range is "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003055 << buffer_info->range << " which is greater than buffer size (" << buffer_node->createInfo.size
3056 << ") minus requested offset of " << buffer_info->offset;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06003057 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06003058 return false;
3059 }
3060 }
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07003061 // Check buffer update sizes against device limits
John Zulaufc93c4252019-06-25 09:19:49 -06003062 const auto &limits = phys_dev_props.limits;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07003063 if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == type || VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) {
John Zulaufd9435c32019-06-05 15:55:36 -06003064 auto max_ub_range = limits.maxUniformBufferRange;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07003065 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_ub_range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06003066 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00332";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07003067 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003068 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer()) << " VkDescriptorBufferInfo range is "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003069 << buffer_info->range << " which is greater than this device's maxUniformBufferRange (" << max_ub_range
3070 << ")";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07003071 *error_msg = error_str.str();
3072 return false;
Peter Kohaut2794a292018-07-13 11:13:47 +02003073 } else if (buffer_info->range == VK_WHOLE_SIZE && (buffer_node->createInfo.size - buffer_info->offset) > max_ub_range) {
3074 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00332";
3075 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003076 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer())
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003077 << " VkDescriptorBufferInfo range is VK_WHOLE_SIZE but effective range "
Peter Kohaut18f413d2018-07-16 13:15:42 +02003078 << "(" << (buffer_node->createInfo.size - buffer_info->offset) << ") is greater than this device's "
Peter Kohaut2794a292018-07-13 11:13:47 +02003079 << "maxUniformBufferRange (" << max_ub_range << ")";
3080 *error_msg = error_str.str();
3081 return false;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07003082 }
3083 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type || VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) {
John Zulaufd9435c32019-06-05 15:55:36 -06003084 auto max_sb_range = limits.maxStorageBufferRange;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07003085 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_sb_range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06003086 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00333";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07003087 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003088 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer()) << " VkDescriptorBufferInfo range is "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003089 << buffer_info->range << " which is greater than this device's maxStorageBufferRange (" << max_sb_range
3090 << ")";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07003091 *error_msg = error_str.str();
3092 return false;
Peter Kohaut2794a292018-07-13 11:13:47 +02003093 } else if (buffer_info->range == VK_WHOLE_SIZE && (buffer_node->createInfo.size - buffer_info->offset) > max_sb_range) {
3094 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00333";
3095 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003096 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer())
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003097 << " VkDescriptorBufferInfo range is VK_WHOLE_SIZE but effective range "
Peter Kohaut18f413d2018-07-16 13:15:42 +02003098 << "(" << (buffer_node->createInfo.size - buffer_info->offset) << ") is greater than this device's "
Peter Kohaut2794a292018-07-13 11:13:47 +02003099 << "maxStorageBufferRange (" << max_sb_range << ")";
3100 *error_msg = error_str.str();
3101 return false;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07003102 }
3103 }
Tobin Ehlis3d38f082016-07-01 17:36:48 -06003104 return true;
3105}
sourav parmarcd5fb182020-07-17 12:58:44 -07003106template <typename T>
3107bool CoreChecks::ValidateAccelerationStructureUpdate(T acc_node, const char *func_name, std::string *error_code,
Jeff Bolz95176d02020-04-01 00:36:16 -05003108 std::string *error_msg) const {
ziga-lunarg5f3a0912021-11-06 19:18:45 +01003109 // nullDescriptor feature allows this to be VK_NULL_HANDLE
3110 if (acc_node) {
3111 if (ValidateMemoryIsBoundToAccelerationStructure(acc_node, func_name, kVUIDUndefined)) {
3112 *error_code = kVUIDUndefined;
3113 *error_msg = "No memory bound to acceleration structure.";
3114 return false;
3115 }
Jeff Bolz95176d02020-04-01 00:36:16 -05003116 }
3117 return true;
3118}
3119
Tobin Ehlis300888c2016-05-18 13:43:26 -06003120// Verify that the contents of the update are ok, but don't perform actual update
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003121bool CoreChecks::VerifyCopyUpdateContents(const VkCopyDescriptorSet *update, const DescriptorSet *src_set,
3122 VkDescriptorType src_type, uint32_t src_index, const DescriptorSet *dst_set,
3123 VkDescriptorType dst_type, uint32_t dst_index, const char *func_name,
3124 std::string *error_code, std::string *error_msg) const {
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06003125 // Note : Repurposing some Write update error codes here as specific details aren't called out for copy updates like they are
3126 // for write updates
John Zulaufc93c4252019-06-25 09:19:49 -06003127 using DescriptorClass = cvdescriptorset::DescriptorClass;
3128 using BufferDescriptor = cvdescriptorset::BufferDescriptor;
3129 using ImageDescriptor = cvdescriptorset::ImageDescriptor;
3130 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
3131 using SamplerDescriptor = cvdescriptorset::SamplerDescriptor;
3132 using TexelDescriptor = cvdescriptorset::TexelDescriptor;
3133
3134 auto device_data = this;
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003135
3136 if (dst_type == VK_DESCRIPTOR_TYPE_SAMPLER) {
3137 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3138 const auto dst_desc = dst_set->GetDescriptorFromGlobalIndex(dst_index + di);
3139 if (!dst_desc->updated) continue;
3140 if (dst_desc->IsImmutableSampler()) {
3141 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02753";
3142 std::stringstream error_str;
3143 error_str << "Attempted copy update to an immutable sampler descriptor.";
3144 *error_msg = error_str.str();
3145 return false;
3146 }
3147 }
3148 }
3149
3150 switch (src_set->GetDescriptorFromGlobalIndex(src_index)->descriptor_class) {
John Zulaufc93c4252019-06-25 09:19:49 -06003151 case DescriptorClass::PlainSampler: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003152 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003153 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02003154 if (!src_desc->updated) continue;
3155 if (!src_desc->IsImmutableSampler()) {
John Zulaufd9435c32019-06-05 15:55:36 -06003156 auto update_sampler = static_cast<const SamplerDescriptor *>(src_desc)->GetSampler();
John Zulaufc93c4252019-06-25 09:19:49 -06003157 if (!ValidateSampler(update_sampler)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06003158 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003159 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003160 error_str << "Attempted copy update to sampler descriptor with invalid sampler: "
3161 << report_data->FormatHandle(update_sampler) << ".";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003162 *error_msg = error_str.str();
3163 return false;
3164 }
3165 } else {
3166 // TODO : Warn here
3167 }
3168 }
3169 break;
3170 }
John Zulaufc93c4252019-06-25 09:19:49 -06003171 case DescriptorClass::ImageSampler: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003172 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003173 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02003174 if (!src_desc->updated) continue;
3175 auto img_samp_desc = static_cast<const ImageSamplerDescriptor *>(src_desc);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003176 // First validate sampler
3177 if (!img_samp_desc->IsImmutableSampler()) {
3178 auto update_sampler = img_samp_desc->GetSampler();
John Zulaufc93c4252019-06-25 09:19:49 -06003179 if (!ValidateSampler(update_sampler)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06003180 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003181 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003182 error_str << "Attempted copy update to sampler descriptor with invalid sampler: "
3183 << report_data->FormatHandle(update_sampler) << ".";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003184 *error_msg = error_str.str();
3185 return false;
3186 }
3187 } else {
3188 // TODO : Warn here
3189 }
3190 // Validate image
3191 auto image_view = img_samp_desc->GetImageView();
3192 auto image_layout = img_samp_desc->GetImageLayout();
Jeff Bolz165818a2020-05-08 11:19:03 -05003193 if (image_view) {
3194 if (!ValidateImageUpdate(image_view, image_layout, src_type, func_name, error_code, error_msg)) {
3195 std::stringstream error_str;
3196 error_str << "Attempted copy update to combined image sampler descriptor failed due to: "
3197 << error_msg->c_str();
3198 *error_msg = error_str.str();
3199 return false;
3200 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06003201 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06003202 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003203 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06003204 }
John Zulaufc93c4252019-06-25 09:19:49 -06003205 case DescriptorClass::Image: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003206 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003207 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02003208 if (!src_desc->updated) continue;
3209 auto img_desc = static_cast<const ImageDescriptor *>(src_desc);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003210 auto image_view = img_desc->GetImageView();
3211 auto image_layout = img_desc->GetImageLayout();
Jeff Bolz165818a2020-05-08 11:19:03 -05003212 if (image_view) {
3213 if (!ValidateImageUpdate(image_view, image_layout, src_type, func_name, error_code, error_msg)) {
3214 std::stringstream error_str;
3215 error_str << "Attempted copy update to image descriptor failed due to: " << error_msg->c_str();
3216 *error_msg = error_str.str();
3217 return false;
3218 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06003219 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06003220 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003221 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06003222 }
John Zulaufc93c4252019-06-25 09:19:49 -06003223 case DescriptorClass::TexelBuffer: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003224 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003225 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02003226 if (!src_desc->updated) continue;
John Zulaufd9435c32019-06-05 15:55:36 -06003227 auto buffer_view = static_cast<const TexelDescriptor *>(src_desc)->GetBufferView();
Jeff Bolz165818a2020-05-08 11:19:03 -05003228 if (buffer_view) {
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06003229 auto bv_state = device_data->Get<BUFFER_VIEW_STATE>(buffer_view);
Jeff Bolz165818a2020-05-08 11:19:03 -05003230 if (!bv_state) {
3231 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
3232 std::stringstream error_str;
3233 error_str << "Attempted copy update to texel buffer descriptor with invalid buffer view: "
3234 << report_data->FormatHandle(buffer_view);
3235 *error_msg = error_str.str();
3236 return false;
3237 }
3238 auto buffer = bv_state->create_info.buffer;
Jeremy Gebben9f537102021-10-05 16:37:12 -06003239 auto buffer_state = Get<BUFFER_STATE>(buffer);
3240 if (!cvdescriptorset::ValidateBufferUsage(report_data, buffer_state.get(), src_type, error_code, error_msg)) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003241 std::stringstream error_str;
3242 error_str << "Attempted copy update to texel buffer descriptor failed due to: " << error_msg->c_str();
3243 *error_msg = error_str.str();
3244 return false;
3245 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003246 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06003247 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003248 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06003249 }
John Zulaufc93c4252019-06-25 09:19:49 -06003250 case DescriptorClass::GeneralBuffer: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003251 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003252 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02003253 if (!src_desc->updated) continue;
Jeremy Gebben9f537102021-10-05 16:37:12 -06003254 auto buffer_state = static_cast<const BufferDescriptor *>(src_desc)->GetBufferState();
3255 if (buffer_state) {
3256 if (!cvdescriptorset::ValidateBufferUsage(report_data, buffer_state, src_type, error_code, error_msg)) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003257 std::stringstream error_str;
3258 error_str << "Attempted copy update to buffer descriptor failed due to: " << error_msg->c_str();
3259 *error_msg = error_str.str();
3260 return false;
3261 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003262 }
Tobin Ehliscbcf2342016-05-24 13:07:12 -06003263 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003264 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06003265 }
John Zulaufc93c4252019-06-25 09:19:49 -06003266 case DescriptorClass::InlineUniform:
3267 case DescriptorClass::AccelerationStructure:
Ricardo Garcia14f4f762021-04-13 11:36:12 +02003268 case DescriptorClass::Mutable:
Jeff Bolze54ae892018-09-08 12:16:29 -05003269 break;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003270 default:
3271 assert(0); // We've already verified update type so should never get here
3272 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06003273 }
3274 // All checks passed so update contents are good
3275 return true;
Chris Forbesb4e0bdb2016-05-31 16:34:40 +12003276}
Tobin Ehlisee471462016-05-26 11:21:59 -06003277// Verify that the state at allocate time is correct, but don't actually allocate the sets yet
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07003278bool CoreChecks::ValidateAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *p_alloc_info,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05003279 const cvdescriptorset::AllocateDescriptorSetsData *ds_data) const {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06003280 bool skip = false;
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06003281 auto pool_state = Get<DESCRIPTOR_POOL_STATE>(p_alloc_info->descriptorPool);
Tobin Ehlisee471462016-05-26 11:21:59 -06003282
3283 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
Jeremy Gebben9f537102021-10-05 16:37:12 -06003284 auto layout = Get<cvdescriptorset::DescriptorSetLayout>(p_alloc_info->pSetLayouts[i]);
John Zulauf5562d062018-01-24 11:54:05 -07003285 if (layout) { // nullptr layout indicates no valid layout handle for this device, validated/logged in object_tracker
John Zulauf1d27e0a2018-11-05 10:12:48 -07003286 if (layout->IsPushDescriptor()) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003287 skip |= LogError(p_alloc_info->pSetLayouts[i], "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-00308",
3288 "%s specified at pSetLayouts[%" PRIu32
3289 "] in vkAllocateDescriptorSets() was created with invalid flag %s set.",
3290 report_data->FormatHandle(p_alloc_info->pSetLayouts[i]).c_str(), i,
3291 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR");
John Zulauf5562d062018-01-24 11:54:05 -07003292 }
Mike Schuchardt2df08912020-12-15 16:28:09 -08003293 if (layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT &&
3294 !(pool_state->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT)) {
sfricke-samsungbda4a852021-03-06 20:58:01 -08003295 skip |= LogError(
3296 device, "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-03044",
3297 "vkAllocateDescriptorSets(): Descriptor set layout create flags and pool create flags mismatch for index (%d)",
3298 i);
Jeff Bolzfdf96072018-04-10 14:32:18 -05003299 }
ziga-lunarg2ab96532021-07-19 11:06:41 +02003300 if (layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE &&
3301 !(pool_state->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE)) {
3302 skip |= LogError(device, "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-04610",
3303 "vkAllocateDescriptorSets(): pSetLayouts[%d].flags contain "
3304 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE bit, but the pool was not created "
3305 "with the VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE bit.",
3306 i);
3307 }
Tobin Ehlisee471462016-05-26 11:21:59 -06003308 }
3309 }
sfricke-samsung45996a42021-09-16 13:45:27 -07003310 if (!IsExtEnabled(device_extensions.vk_khr_maintenance1)) {
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06003311 // Track number of descriptorSets allowable in this pool
3312 if (pool_state->availableSets < p_alloc_info->descriptorSetCount) {
Jeremy Gebben1fbebb82021-10-27 10:27:27 -06003313 skip |= LogError(pool_state->Handle(), "VUID-VkDescriptorSetAllocateInfo-descriptorSetCount-00306",
sfricke-samsungbda4a852021-03-06 20:58:01 -08003314 "vkAllocateDescriptorSets(): Unable to allocate %u descriptorSets from %s"
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003315 ". This pool only has %d descriptorSets remaining.",
Jeremy Gebben1fbebb82021-10-27 10:27:27 -06003316 p_alloc_info->descriptorSetCount, report_data->FormatHandle(pool_state->Handle()).c_str(),
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003317 pool_state->availableSets);
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06003318 }
3319 // Determine whether descriptor counts are satisfiable
Jeff Bolze54ae892018-09-08 12:16:29 -05003320 for (auto it = ds_data->required_descriptors_by_type.begin(); it != ds_data->required_descriptors_by_type.end(); ++it) {
Jeff Bolz46c0ea02019-10-09 13:06:29 -05003321 auto count_iter = pool_state->availableDescriptorTypeCount.find(it->first);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003322 uint32_t available_count = (count_iter != pool_state->availableDescriptorTypeCount.end()) ? count_iter->second : 0;
Jeff Bolz46c0ea02019-10-09 13:06:29 -05003323
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003324 if (ds_data->required_descriptors_by_type.at(it->first) > available_count) {
Jeremy Gebben1fbebb82021-10-27 10:27:27 -06003325 skip |= LogError(pool_state->Handle(), "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307",
sfricke-samsungbda4a852021-03-06 20:58:01 -08003326 "vkAllocateDescriptorSets(): Unable to allocate %u descriptors of type %s from %s"
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003327 ". This pool only has %d descriptors of this type remaining.",
3328 ds_data->required_descriptors_by_type.at(it->first),
3329 string_VkDescriptorType(VkDescriptorType(it->first)),
Jeremy Gebben1fbebb82021-10-27 10:27:27 -06003330 report_data->FormatHandle(pool_state->Handle()).c_str(), available_count);
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06003331 }
Tobin Ehlisee471462016-05-26 11:21:59 -06003332 }
3333 }
Tobin Ehlis5d749ea2016-07-18 13:14:01 -06003334
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07003335 const auto *count_allocate_info = LvlFindInChain<VkDescriptorSetVariableDescriptorCountAllocateInfo>(p_alloc_info->pNext);
Jeff Bolzfdf96072018-04-10 14:32:18 -05003336
3337 if (count_allocate_info) {
3338 if (count_allocate_info->descriptorSetCount != 0 &&
3339 count_allocate_info->descriptorSetCount != p_alloc_info->descriptorSetCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003340 skip |= LogError(device, "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfo-descriptorSetCount-03045",
sfricke-samsungbda4a852021-03-06 20:58:01 -08003341 "vkAllocateDescriptorSets(): VkDescriptorSetAllocateInfo::descriptorSetCount (%d) != "
Mike Schuchardt2df08912020-12-15 16:28:09 -08003342 "VkDescriptorSetVariableDescriptorCountAllocateInfo::descriptorSetCount (%d)",
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003343 p_alloc_info->descriptorSetCount, count_allocate_info->descriptorSetCount);
Jeff Bolzfdf96072018-04-10 14:32:18 -05003344 }
3345 if (count_allocate_info->descriptorSetCount == p_alloc_info->descriptorSetCount) {
3346 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06003347 auto layout = Get<cvdescriptorset::DescriptorSetLayout>(p_alloc_info->pSetLayouts[i]);
Jeff Bolzfdf96072018-04-10 14:32:18 -05003348 if (count_allocate_info->pDescriptorCounts[i] > layout->GetDescriptorCountFromBinding(layout->GetMaxBinding())) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003349 skip |= LogError(device, "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfo-pSetLayouts-03046",
sfricke-samsungbda4a852021-03-06 20:58:01 -08003350 "vkAllocateDescriptorSets(): pDescriptorCounts[%d] = (%d), binding's descriptorCount = (%d)",
3351 i, count_allocate_info->pDescriptorCounts[i],
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003352 layout->GetDescriptorCountFromBinding(layout->GetMaxBinding()));
Jeff Bolzfdf96072018-04-10 14:32:18 -05003353 }
3354 }
3355 }
3356 }
3357
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06003358 return skip;
Tobin Ehlisee471462016-05-26 11:21:59 -06003359}
John Zulauf48a6a702017-12-22 17:14:54 -07003360
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05003361const BindingReqMap &cvdescriptorset::PrefilterBindRequestMap::FilteredMap(const CMD_BUFFER_STATE &cb_state,
3362 const PIPELINE_STATE &pipeline) {
John Zulauffbf3c202019-07-17 14:57:14 -06003363 if (IsManyDescriptors()) {
Karl Schultz7090a052020-11-10 08:54:21 -07003364 filtered_map_.reset(new BindingReqMap);
John Zulauffbf3c202019-07-17 14:57:14 -06003365 descriptor_set_.FilterBindingReqs(cb_state, pipeline, orig_map_, filtered_map_.get());
3366 return *filtered_map_;
John Zulauf48a6a702017-12-22 17:14:54 -07003367 }
John Zulauffbf3c202019-07-17 14:57:14 -06003368 return orig_map_;
Artem Kharytoniuk2456f992018-01-12 14:17:41 +01003369}
John Zulauf4a015c92019-06-04 09:50:05 -06003370
3371// Starting at offset descriptor of given binding, parse over update_count
3372// descriptor updates and verify that for any binding boundaries that are crossed, the next binding(s) are all consistent
3373// Consistency means that their type, stage flags, and whether or not they use immutable samplers matches
3374// If so, return true. If not, fill in error_msg and return false
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003375bool cvdescriptorset::VerifyUpdateConsistency(debug_report_data *report_data,
3376 DescriptorSetLayout::ConstBindingIterator current_binding, uint32_t offset,
John Zulauf4a015c92019-06-04 09:50:05 -06003377 uint32_t update_count, const char *type, const VkDescriptorSet set,
3378 std::string *error_msg) {
locke-lunarge46b7782019-09-10 01:44:20 -06003379 bool pass = true;
John Zulauf4a015c92019-06-04 09:50:05 -06003380 // Verify consecutive bindings match (if needed)
3381 auto orig_binding = current_binding;
locke-lunarge46b7782019-09-10 01:44:20 -06003382
3383 while (pass && update_count) {
3384 // First, it's legal to offset beyond your own binding so handle that case
3385 if (offset > 0) {
3386 const auto &index_range = current_binding.GetGlobalIndexRange();
3387 // index_range.start + offset is which descriptor is needed to update. If it > index_range.end, it means the descriptor
3388 // isn't in this binding, maybe in next binding.
3389 if ((index_range.start + offset) >= index_range.end) {
3390 // Advance to next binding, decrement offset by binding size
3391 offset -= current_binding.GetDescriptorCount();
3392 ++current_binding;
3393 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
3394 if (!orig_binding.IsConsistent(current_binding)) {
3395 pass = false;
3396 }
3397 continue;
John Zulauf4a015c92019-06-04 09:50:05 -06003398 }
John Zulauf4a015c92019-06-04 09:50:05 -06003399 }
locke-lunarge46b7782019-09-10 01:44:20 -06003400
3401 update_count -= std::min(update_count, current_binding.GetDescriptorCount() - offset);
3402 if (update_count) {
3403 // Starting offset is beyond the current binding. Check consistency, update counters and advance to the next binding,
3404 // looking for the start point. All bindings (even those skipped) must be consistent with the update and with the
3405 // original binding.
3406 offset = 0;
3407 ++current_binding;
3408 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
3409 if (!orig_binding.IsConsistent(current_binding)) {
3410 pass = false;
3411 }
3412 }
John Zulauf4a015c92019-06-04 09:50:05 -06003413 }
locke-lunarge46b7782019-09-10 01:44:20 -06003414
3415 if (!pass) {
3416 std::stringstream error_str;
3417 error_str << "Attempting " << type;
3418 if (current_binding.Layout()->IsPushDescriptor()) {
3419 error_str << " push descriptors";
3420 } else {
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003421 error_str << " descriptor set " << report_data->FormatHandle(set);
locke-lunarge46b7782019-09-10 01:44:20 -06003422 }
3423 error_str << " binding #" << orig_binding.Binding() << " with #" << update_count
3424 << " descriptors being updated but this update oversteps the bounds of this binding and the next binding is "
sfricke-samsung5de34882021-04-15 22:33:23 -07003425 "not consistent with current binding";
3426
3427 // Get what was not consistent in IsConsistent() as a more detailed error message
3428 const auto *binding_ci = orig_binding.GetDescriptorSetLayoutBindingPtr();
3429 const auto *other_binding_ci = current_binding.GetDescriptorSetLayoutBindingPtr();
3430 if (binding_ci == nullptr || other_binding_ci == nullptr) {
3431 error_str << " (No two valid DescriptorSetLayoutBinding to compare)";
3432 } else if (binding_ci->descriptorType != other_binding_ci->descriptorType) {
3433 error_str << " (" << string_VkDescriptorType(binding_ci->descriptorType)
3434 << " != " << string_VkDescriptorType(other_binding_ci->descriptorType) << ")";
3435 } else if (binding_ci->stageFlags != other_binding_ci->stageFlags) {
3436 error_str << " (" << string_VkShaderStageFlags(binding_ci->stageFlags)
3437 << " != " << string_VkShaderStageFlags(other_binding_ci->stageFlags) << ")";
3438 } else if (!hash_util::similar_for_nullity(binding_ci->pImmutableSamplers, other_binding_ci->pImmutableSamplers)) {
3439 error_str << " (pImmutableSamplers don't match)";
3440 } else if (orig_binding.GetDescriptorBindingFlags() != current_binding.GetDescriptorBindingFlags()) {
3441 error_str << " (" << string_VkDescriptorBindingFlags(orig_binding.GetDescriptorBindingFlags())
3442 << " != " << string_VkDescriptorBindingFlags(current_binding.GetDescriptorBindingFlags()) << ")";
3443 }
3444
3445 error_str << " so this update is invalid";
locke-lunarge46b7782019-09-10 01:44:20 -06003446 *error_msg = error_str.str();
3447 }
3448 return pass;
John Zulauf4a015c92019-06-04 09:50:05 -06003449}
John Zulauf4956fff2019-06-04 16:54:38 -06003450
3451// Validate the state for a given write update but don't actually perform the update
3452// If an error would occur for this update, return false and fill in details in error_msg string
John Zulaufc93c4252019-06-25 09:19:49 -06003453bool CoreChecks::ValidateWriteUpdate(const DescriptorSet *dest_set, const VkWriteDescriptorSet *update, const char *func_name,
ziga-lunarg6c46b242021-09-13 18:33:37 +02003454 std::string *error_code, std::string *error_msg, bool push) const {
Jeff Bolz6aad1742019-10-16 11:10:09 -05003455 const auto dest_layout = dest_set->GetLayout().get();
John Zulauf4956fff2019-06-04 16:54:38 -06003456
3457 // Verify dst layout still valid
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06003458 if (dest_layout->Destroyed()) {
John Zulauf4956fff2019-06-04 16:54:38 -06003459 *error_code = "VUID-VkWriteDescriptorSet-dstSet-00320";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06003460 std::ostringstream str;
3461 str << "Cannot call " << func_name << " to perform write update on " << dest_set->StringifySetAndLayout()
3462 << " which has been destroyed";
3463 *error_msg = str.str();
John Zulauf4956fff2019-06-04 16:54:38 -06003464 return false;
3465 }
3466 // Verify dst binding exists
3467 if (!dest_layout->HasBinding(update->dstBinding)) {
3468 *error_code = "VUID-VkWriteDescriptorSet-dstBinding-00315";
3469 std::stringstream error_str;
3470 error_str << dest_set->StringifySetAndLayout() << " does not have binding " << update->dstBinding;
3471 *error_msg = error_str.str();
3472 return false;
3473 }
3474
Jeff Bolz6aad1742019-10-16 11:10:09 -05003475 DescriptorSetLayout::ConstBindingIterator dest(dest_layout, update->dstBinding);
John Zulauf4956fff2019-06-04 16:54:38 -06003476 // Make sure binding isn't empty
3477 if (0 == dest.GetDescriptorCount()) {
3478 *error_code = "VUID-VkWriteDescriptorSet-dstBinding-00316";
3479 std::stringstream error_str;
3480 error_str << dest_set->StringifySetAndLayout() << " cannot updated binding " << update->dstBinding
3481 << " that has 0 descriptors";
3482 *error_msg = error_str.str();
3483 return false;
3484 }
3485
3486 // Verify idle ds
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06003487 if (dest_set->InUse() && !(dest.GetDescriptorBindingFlags() & (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT |
Mike Schuchardt2df08912020-12-15 16:28:09 -08003488 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT))) {
John Zulauf4956fff2019-06-04 16:54:38 -06003489 // TODO : Re-using Free Idle error code, need write update idle error code
3490 *error_code = "VUID-vkFreeDescriptorSets-pDescriptorSets-00309";
3491 std::stringstream error_str;
3492 error_str << "Cannot call " << func_name << " to perform write update on " << dest_set->StringifySetAndLayout()
3493 << " that is in use by a command buffer";
3494 *error_msg = error_str.str();
3495 return false;
3496 }
3497 // We know that binding is valid, verify update and do update on each descriptor
3498 auto start_idx = dest.GetGlobalIndexRange().start + update->dstArrayElement;
3499 auto type = dest.GetType();
Tony-LunarGf563b362021-03-18 16:13:18 -06003500 if ((type != VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) && (type != update->descriptorType)) {
John Zulauf4956fff2019-06-04 16:54:38 -06003501 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00319";
3502 std::stringstream error_str;
3503 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3504 << " with type " << string_VkDescriptorType(type) << " but update type is "
3505 << string_VkDescriptorType(update->descriptorType);
3506 *error_msg = error_str.str();
3507 return false;
3508 }
John Zulauf4956fff2019-06-04 16:54:38 -06003509 if (type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
3510 if ((update->dstArrayElement % 4) != 0) {
3511 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02219";
3512 std::stringstream error_str;
3513 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3514 << " with "
3515 << "dstArrayElement " << update->dstArrayElement << " not a multiple of 4";
3516 *error_msg = error_str.str();
3517 return false;
3518 }
3519 if ((update->descriptorCount % 4) != 0) {
3520 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02220";
3521 std::stringstream error_str;
3522 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3523 << " with "
3524 << "descriptorCount " << update->descriptorCount << " not a multiple of 4";
3525 *error_msg = error_str.str();
3526 return false;
3527 }
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07003528 const auto *write_inline_info = LvlFindInChain<VkWriteDescriptorSetInlineUniformBlockEXT>(update->pNext);
John Zulauf4956fff2019-06-04 16:54:38 -06003529 if (!write_inline_info || write_inline_info->dataSize != update->descriptorCount) {
3530 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02221";
3531 std::stringstream error_str;
3532 if (!write_inline_info) {
3533 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #"
3534 << update->dstBinding << " with "
3535 << "VkWriteDescriptorSetInlineUniformBlockEXT missing";
3536 } else {
3537 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #"
3538 << update->dstBinding << " with "
3539 << "VkWriteDescriptorSetInlineUniformBlockEXT dataSize " << write_inline_info->dataSize
3540 << " not equal to "
3541 << "VkWriteDescriptorSet descriptorCount " << update->descriptorCount;
3542 }
3543 *error_msg = error_str.str();
3544 return false;
3545 }
3546 // This error is probably unreachable due to the previous two errors
3547 if (write_inline_info && (write_inline_info->dataSize % 4) != 0) {
3548 *error_code = "VUID-VkWriteDescriptorSetInlineUniformBlockEXT-dataSize-02222";
3549 std::stringstream error_str;
3550 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3551 << " with "
3552 << "VkWriteDescriptorSetInlineUniformBlockEXT dataSize " << write_inline_info->dataSize
3553 << " not a multiple of 4";
3554 *error_msg = error_str.str();
3555 return false;
3556 }
3557 }
sfricke-samsung941d48b2020-02-10 00:20:01 -08003558 // Verify all bindings update share identical properties across all items
3559 if (update->descriptorCount > 0) {
3560 // Save first binding information and error if something different is found
3561 DescriptorSetLayout::ConstBindingIterator current_binding(dest_layout, update->dstBinding);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003562 VkShaderStageFlags stage_flags = current_binding.GetStageFlags();
3563 VkDescriptorType descriptor_type = current_binding.GetType();
3564 bool immutable_samplers = (current_binding.GetImmutableSamplerPtr() == nullptr);
3565 uint32_t dst_array_element = update->dstArrayElement;
sfricke-samsung941d48b2020-02-10 00:20:01 -08003566
Jeff Bolz9198e882020-03-18 13:03:30 -05003567 for (uint32_t i = 0; i < update->descriptorCount;) {
sfricke-samsung941d48b2020-02-10 00:20:01 -08003568 if (current_binding.AtEnd() == true) {
3569 break; // prevents setting error here if bindings don't exist
3570 }
3571
Quentin Huot-Marchand98d84dd2021-06-24 09:54:58 +02003572 // All consecutive bindings updated, except those with a descriptorCount of zero, must have identical descType and stageFlags
3573 if(current_binding.GetDescriptorCount() > 0) {
3574 // Check for consistent stageFlags and descriptorType
3575 if ((current_binding.GetStageFlags() != stage_flags) || (current_binding.GetType() != descriptor_type)) {
3576 *error_code = "VUID-VkWriteDescriptorSet-descriptorCount-00317";
3577 std::stringstream error_str;
3578 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3579 << current_binding.GetIndex() << " (" << i << " from dstBinding offset)"
3580 << " with a different stageFlag and/or descriptorType from previous bindings."
3581 << " All bindings must have consecutive stageFlag and/or descriptorType across a VkWriteDescriptorSet";
3582 *error_msg = error_str.str();
3583 return false;
3584 }
3585 // Check if all immutableSamplers or not
3586 if ((current_binding.GetImmutableSamplerPtr() == nullptr) != immutable_samplers) {
3587 *error_code = "VUID-VkWriteDescriptorSet-descriptorCount-00318";
3588 std::stringstream error_str;
3589 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3590 << current_binding.GetIndex() << " (" << i << " from dstBinding offset)"
3591 << " with a different usage of immutable samplers from previous bindings."
3592 << " All bindings must have all or none usage of immutable samplers across a VkWriteDescriptorSet";
3593 *error_msg = error_str.str();
3594 return false;
3595 }
sfricke-samsung941d48b2020-02-10 00:20:01 -08003596 }
Jeff Bolz9198e882020-03-18 13:03:30 -05003597
3598 // Skip the remaining descriptors for this binding, and move to the next binding
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003599 i += (current_binding.GetDescriptorCount() - dst_array_element);
3600 dst_array_element = 0;
sfricke-samsung941d48b2020-02-10 00:20:01 -08003601 ++current_binding;
3602 }
3603 }
3604
John Zulauf4956fff2019-06-04 16:54:38 -06003605 // Verify consecutive bindings match (if needed)
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003606 if (!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(dest_layout, update->dstBinding),
John Zulauf4956fff2019-06-04 16:54:38 -06003607 update->dstArrayElement, update->descriptorCount, "write update to", dest_set->GetSet(),
3608 error_msg)) {
John Zulauf4956fff2019-06-04 16:54:38 -06003609 *error_code = "VUID-VkWriteDescriptorSet-dstArrayElement-00321";
3610 return false;
3611 }
Tony-LunarG1f79c952020-10-27 15:55:51 -06003612 // Verify write to variable descriptor
3613 if (dest_set->IsVariableDescriptorCount(update->dstBinding)) {
3614 if ((update->dstArrayElement + update->descriptorCount) > dest_set->GetVariableDescriptorCount()) {
3615 std::stringstream error_str;
3616 *error_code = "VUID-VkWriteDescriptorSet-dstArrayElement-00321";
3617 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3618 << update->dstBinding << " array element " << update->dstArrayElement << " with " << update->descriptorCount
3619 << " writes but variable descriptor size is " << dest_set->GetVariableDescriptorCount();
3620 *error_msg = error_str.str();
3621 return false;
3622 }
3623 }
John Zulauf4956fff2019-06-04 16:54:38 -06003624 // Update is within bounds and consistent so last step is to validate update contents
ziga-lunarg6c46b242021-09-13 18:33:37 +02003625 if (!VerifyWriteUpdateContents(dest_set, update, start_idx, func_name, error_code, error_msg, push)) {
John Zulauf4956fff2019-06-04 16:54:38 -06003626 std::stringstream error_str;
3627 error_str << "Write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3628 << " failed with error message: " << error_msg->c_str();
3629 *error_msg = error_str.str();
3630 return false;
3631 }
ziga-lunargd67b5f52021-10-16 23:52:59 +02003632 const auto orig_binding = DescriptorSetLayout::ConstBindingIterator(dest_set->GetLayout().get(), update->dstBinding);
3633 if (!orig_binding.AtEnd() && orig_binding.GetType() == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) {
3634 // Check if the new descriptor descriptor type is in the list of allowed mutable types for this binding
3635 if (!orig_binding.Layout()->IsTypeMutable(update->descriptorType, update->dstBinding)) {
3636 *error_code = "VUID-VkWriteDescriptorSet-dstSet-04611";
3637 std::stringstream error_str;
3638 error_str << "Write update type is " << string_VkDescriptorType(update->descriptorType)
3639 << ", but descriptor set layout binding was created with type VK_DESCRIPTOR_TYPE_MUTABLE_VALVE and used type "
3640 "is not in VkMutableDescriptorTypeListVALVE::pDescriptorTypes for this binding.";
3641 *error_msg = error_str.str();
3642 return false;
3643 }
3644 }
John Zulauf4956fff2019-06-04 16:54:38 -06003645 // All checks passed, update is clean
3646 return true;
3647}
John Zulaufadb3f542019-06-04 17:01:00 -06003648
3649// Verify that the contents of the update are ok, but don't perform actual update
John Zulaufc93c4252019-06-25 09:19:49 -06003650bool CoreChecks::VerifyWriteUpdateContents(const DescriptorSet *dest_set, const VkWriteDescriptorSet *update, const uint32_t index,
ziga-lunarg6c46b242021-09-13 18:33:37 +02003651 const char *func_name, std::string *error_code, std::string *error_msg,
3652 bool push) const {
John Zulaufc93c4252019-06-25 09:19:49 -06003653 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
Nathaniel Cesarioff521512020-12-11 16:00:26 -07003654 using Descriptor = cvdescriptorset::Descriptor;
John Zulaufc93c4252019-06-25 09:19:49 -06003655
John Zulaufadb3f542019-06-04 17:01:00 -06003656 switch (update->descriptorType) {
3657 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
3658 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3659 // Validate image
3660 auto image_view = update->pImageInfo[di].imageView;
3661 auto image_layout = update->pImageInfo[di].imageLayout;
Mark Lobodzinski3ca937b2020-02-14 14:56:06 -07003662 auto sampler = update->pImageInfo[di].sampler;
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06003663 auto iv_state = Get<IMAGE_VIEW_STATE>(image_view);
Nathaniel Cesarioff521512020-12-11 16:00:26 -07003664 const ImageSamplerDescriptor *desc =
3665 (const ImageSamplerDescriptor *)dest_set->GetDescriptorFromGlobalIndex(index + di);
Jeff Bolz165818a2020-05-08 11:19:03 -05003666 if (image_view) {
3667 auto image_state = iv_state->image_state.get();
3668 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, func_name, error_code, error_msg)) {
3669 std::stringstream error_str;
3670 error_str << "Attempted write update to combined image sampler descriptor failed due to: "
3671 << error_msg->c_str();
3672 *error_msg = error_str.str();
3673 return false;
3674 }
sfricke-samsung45996a42021-09-16 13:45:27 -07003675 if (IsExtEnabled(device_extensions.vk_khr_sampler_ycbcr_conversion)) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003676 if (desc->IsImmutableSampler()) {
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06003677 auto sampler_state = Get<SAMPLER_STATE>(desc->GetSampler());
Jeff Bolz165818a2020-05-08 11:19:03 -05003678 if (iv_state && sampler_state) {
3679 if (iv_state->samplerConversion != sampler_state->samplerConversion) {
3680 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-01948";
3681 std::stringstream error_str;
3682 error_str
3683 << "Attempted write update to combined image sampler and image view and sampler ycbcr "
3684 "conversions are not identical, sampler: "
3685 << report_data->FormatHandle(desc->GetSampler())
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003686 << " image view: " << report_data->FormatHandle(iv_state->image_view()) << ".";
Jeff Bolz165818a2020-05-08 11:19:03 -05003687 *error_msg = error_str.str();
3688 return false;
3689 }
3690 }
3691 } else {
3692 if (iv_state && (iv_state->samplerConversion != VK_NULL_HANDLE)) {
3693 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02738";
John Zulaufadb3f542019-06-04 17:01:00 -06003694 std::stringstream error_str;
Jeff Bolz165818a2020-05-08 11:19:03 -05003695 error_str << "Because dstSet (" << report_data->FormatHandle(update->dstSet)
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003696 << ") is bound to image view (" << report_data->FormatHandle(iv_state->image_view())
Jeff Bolz165818a2020-05-08 11:19:03 -05003697 << ") that includes a YCBCR conversion, it must have been allocated with a layout that "
3698 "includes an immutable sampler.";
John Zulaufadb3f542019-06-04 17:01:00 -06003699 *error_msg = error_str.str();
3700 return false;
3701 }
3702 }
Jeff Bolz165818a2020-05-08 11:19:03 -05003703 }
John Baumanda8abff2020-10-19 21:25:21 +00003704 // If there is an immutable sampler then |sampler| isn't used, so the following VU does not apply.
3705 if (sampler && !desc->IsImmutableSampler() && FormatIsMultiplane(image_state->createInfo.format)) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003706 // multiplane formats must be created with mutable format bit
3707 if (0 == (image_state->createInfo.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) {
3708 *error_code = "VUID-VkDescriptorImageInfo-sampler-01564";
John Zulaufadb3f542019-06-04 17:01:00 -06003709 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003710 error_str << "image " << report_data->FormatHandle(image_state->image())
Jeff Bolz165818a2020-05-08 11:19:03 -05003711 << " combined image sampler is a multi-planar "
3712 << "format and was not was not created with the VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT";
John Zulaufadb3f542019-06-04 17:01:00 -06003713 *error_msg = error_str.str();
3714 return false;
3715 }
Jeff Bolz165818a2020-05-08 11:19:03 -05003716 // image view need aspect mask for only the planes supported of format
3717 VkImageAspectFlags legal_aspect_flags = (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT);
3718 legal_aspect_flags |=
3719 (FormatPlaneCount(image_state->createInfo.format) == 3) ? VK_IMAGE_ASPECT_PLANE_2_BIT : 0;
3720 if (0 != (iv_state->create_info.subresourceRange.aspectMask & (~legal_aspect_flags))) {
3721 *error_code = "VUID-VkDescriptorImageInfo-sampler-01564";
3722 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003723 error_str << "image " << report_data->FormatHandle(image_state->image())
Jeff Bolz165818a2020-05-08 11:19:03 -05003724 << " combined image sampler is a multi-planar "
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003725 << "format and " << report_data->FormatHandle(iv_state->image_view())
Jeff Bolz165818a2020-05-08 11:19:03 -05003726 << " aspectMask must only include " << string_VkImageAspectFlags(legal_aspect_flags);
3727 *error_msg = error_str.str();
3728 return false;
3729 }
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003730 }
Nathaniel Cesario23afadd2020-11-17 12:51:45 -07003731
3732 // Verify portability
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06003733 auto sampler_state = Get<SAMPLER_STATE>(sampler);
Nathaniel Cesario23afadd2020-11-17 12:51:45 -07003734 if (sampler_state) {
sfricke-samsung45996a42021-09-16 13:45:27 -07003735 if (IsExtEnabled(device_extensions.vk_khr_portability_subset)) {
Nathaniel Cesario23afadd2020-11-17 12:51:45 -07003736 if ((VK_FALSE == enabled_features.portability_subset_features.mutableComparisonSamplers) &&
3737 (VK_FALSE != sampler_state->createInfo.compareEnable)) {
3738 LogError(device, "VUID-VkDescriptorImageInfo-mutableComparisonSamplers-04450",
3739 "%s (portability error): sampler comparison not available.", func_name);
3740 }
3741 }
3742 }
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003743 }
John Zulaufadb3f542019-06-04 17:01:00 -06003744 }
3745 }
Mark Lobodzinskiac727772020-01-08 10:47:30 -07003746 // Fall through
John Zulaufadb3f542019-06-04 17:01:00 -06003747 case VK_DESCRIPTOR_TYPE_SAMPLER: {
3748 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003749 const auto *desc = static_cast<const Descriptor *>(dest_set->GetDescriptorFromGlobalIndex(index + di));
John Zulaufadb3f542019-06-04 17:01:00 -06003750 if (!desc->IsImmutableSampler()) {
John Zulaufc93c4252019-06-25 09:19:49 -06003751 if (!ValidateSampler(update->pImageInfo[di].sampler)) {
John Zulaufadb3f542019-06-04 17:01:00 -06003752 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
3753 std::stringstream error_str;
3754 error_str << "Attempted write update to sampler descriptor with invalid sampler: "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003755 << report_data->FormatHandle(update->pImageInfo[di].sampler) << ".";
John Zulaufadb3f542019-06-04 17:01:00 -06003756 *error_msg = error_str.str();
3757 return false;
3758 }
ziga-lunarg6c46b242021-09-13 18:33:37 +02003759 } else if (update->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER && !push) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003760 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02752";
3761 std::stringstream error_str;
3762 error_str << "Attempted write update to an immutable sampler descriptor.";
3763 *error_msg = error_str.str();
3764 return false;
John Zulaufadb3f542019-06-04 17:01:00 -06003765 }
3766 }
3767 break;
3768 }
3769 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
3770 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
3771 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
3772 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3773 auto image_view = update->pImageInfo[di].imageView;
3774 auto image_layout = update->pImageInfo[di].imageLayout;
Jeff Bolz165818a2020-05-08 11:19:03 -05003775 if (image_view) {
3776 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, func_name, error_code, error_msg)) {
3777 std::stringstream error_str;
3778 error_str << "Attempted write update to image descriptor failed due to: " << error_msg->c_str();
3779 *error_msg = error_str.str();
3780 return false;
3781 }
John Zulaufadb3f542019-06-04 17:01:00 -06003782 }
3783 }
3784 break;
3785 }
3786 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
3787 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
3788 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3789 auto buffer_view = update->pTexelBufferView[di];
Jeff Bolz165818a2020-05-08 11:19:03 -05003790 if (buffer_view) {
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06003791 auto bv_state = Get<BUFFER_VIEW_STATE>(buffer_view);
Jeff Bolz165818a2020-05-08 11:19:03 -05003792 if (!bv_state) {
3793 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
3794 std::stringstream error_str;
3795 error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: "
3796 << report_data->FormatHandle(buffer_view);
3797 *error_msg = error_str.str();
3798 return false;
3799 }
3800 auto buffer = bv_state->create_info.buffer;
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06003801 auto buffer_state = Get<BUFFER_STATE>(buffer);
Jeff Bolz165818a2020-05-08 11:19:03 -05003802 // Verify that buffer underlying the view hasn't been destroyed prematurely
3803 if (!buffer_state) {
3804 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
3805 std::stringstream error_str;
3806 error_str << "Attempted write update to texel buffer descriptor failed because underlying buffer ("
3807 << report_data->FormatHandle(buffer) << ") has been destroyed: " << error_msg->c_str();
3808 *error_msg = error_str.str();
3809 return false;
Jeremy Gebben9f537102021-10-05 16:37:12 -06003810 } else if (!cvdescriptorset::ValidateBufferUsage(report_data, buffer_state.get(), update->descriptorType,
3811 error_code, error_msg)) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003812 std::stringstream error_str;
3813 error_str << "Attempted write update to texel buffer descriptor failed due to: " << error_msg->c_str();
3814 *error_msg = error_str.str();
3815 return false;
3816 }
John Zulaufadb3f542019-06-04 17:01:00 -06003817 }
3818 }
3819 break;
3820 }
3821 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
3822 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
3823 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
3824 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
3825 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003826 if (update->pBufferInfo[di].buffer) {
3827 if (!ValidateBufferUpdate(update->pBufferInfo + di, update->descriptorType, func_name, error_code, error_msg)) {
3828 std::stringstream error_str;
3829 error_str << "Attempted write update to buffer descriptor failed due to: " << error_msg->c_str();
3830 *error_msg = error_str.str();
3831 return false;
3832 }
John Zulaufadb3f542019-06-04 17:01:00 -06003833 }
3834 }
3835 break;
3836 }
3837 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
3838 break;
Jeff Bolz95176d02020-04-01 00:36:16 -05003839 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07003840 const auto *acc_info = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureNV>(update->pNext);
Jeff Bolz95176d02020-04-01 00:36:16 -05003841 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Jeremy Gebben9f537102021-10-05 16:37:12 -06003842 auto as_state = Get<ACCELERATION_STRUCTURE_STATE>(acc_info->pAccelerationStructures[di]);
3843 if (!ValidateAccelerationStructureUpdate(as_state.get(), func_name, error_code, error_msg)) {
Jeff Bolz95176d02020-04-01 00:36:16 -05003844 std::stringstream error_str;
3845 error_str << "Attempted write update to acceleration structure descriptor failed due to: "
3846 << error_msg->c_str();
3847 *error_msg = error_str.str();
3848 return false;
3849 }
3850 }
3851
3852 } break;
sourav parmarcd5fb182020-07-17 12:58:44 -07003853 // KHR acceleration structures don't require memory to be bound manually to them.
3854 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
3855 break;
John Zulaufadb3f542019-06-04 17:01:00 -06003856 default:
3857 assert(0); // We've already verified update type so should never get here
3858 break;
3859 }
3860 // All checks passed so update contents are good
3861 return true;
3862}