blob: 6c1f55ba8de34da6482b773887e1def213cb58ad [file] [log] [blame]
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07001/* Copyright (c) 2015-2020 The Khronos Group Inc.
2 * Copyright (c) 2015-2020 Valve Corporation
3 * Copyright (c) 2015-2020 LunarG, Inc.
4 * Copyright (C) 2015-2020 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
Jeff Bolzfdf96072018-04-10 14:32:18 -050037// ExtendedBinding collects a VkDescriptorSetLayoutBinding and any extended
38// state that comes from a different array/structure so they can stay together
39// while being sorted by binding number.
40struct ExtendedBinding {
41 ExtendedBinding(const VkDescriptorSetLayoutBinding *l, VkDescriptorBindingFlagsEXT f) : layout_binding(l), binding_flags(f) {}
42
43 const VkDescriptorSetLayoutBinding *layout_binding;
44 VkDescriptorBindingFlagsEXT binding_flags;
45};
46
John Zulauf508d13a2018-01-05 15:10:34 -070047struct BindingNumCmp {
Jeff Bolzfdf96072018-04-10 14:32:18 -050048 bool operator()(const ExtendedBinding &a, const ExtendedBinding &b) const {
49 return a.layout_binding->binding < b.layout_binding->binding;
John Zulauf508d13a2018-01-05 15:10:34 -070050 }
51};
52
John Zulauf613fd982019-06-04 15:14:41 -060053using DescriptorSet = cvdescriptorset::DescriptorSet;
John Zulauf4a015c92019-06-04 09:50:05 -060054using DescriptorSetLayout = cvdescriptorset::DescriptorSetLayout;
John Zulaufd47d0612018-02-16 13:00:34 -070055using DescriptorSetLayoutDef = cvdescriptorset::DescriptorSetLayoutDef;
56using DescriptorSetLayoutId = cvdescriptorset::DescriptorSetLayoutId;
57
John Zulauf34ebf272018-02-16 13:08:47 -070058// Canonical dictionary of DescriptorSetLayoutDef (without any handle/device specific information)
59cvdescriptorset::DescriptorSetLayoutDict descriptor_set_layout_dict;
John Zulaufd47d0612018-02-16 13:00:34 -070060
Shannon McPhersonc06c33d2018-06-28 17:21:12 -060061DescriptorSetLayoutId GetCanonicalId(const VkDescriptorSetLayoutCreateInfo *p_create_info) {
John Zulauf34ebf272018-02-16 13:08:47 -070062 return descriptor_set_layout_dict.look_up(DescriptorSetLayoutDef(p_create_info));
John Zulaufd47d0612018-02-16 13:00:34 -070063}
John Zulauf34ebf272018-02-16 13:08:47 -070064
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060065// Construct DescriptorSetLayout instance from given create info
John Zulauf48a6a702017-12-22 17:14:54 -070066// Proactively reserve and resize as possible, as the reallocation was visible in profiling
John Zulauf1f8174b2018-02-16 12:58:37 -070067cvdescriptorset::DescriptorSetLayoutDef::DescriptorSetLayoutDef(const VkDescriptorSetLayoutCreateInfo *p_create_info)
68 : flags_(p_create_info->flags), binding_count_(0), descriptor_count_(0), dynamic_descriptor_count_(0) {
Jeff Bolzfdf96072018-04-10 14:32:18 -050069 const auto *flags_create_info = lvl_find_in_chain<VkDescriptorSetLayoutBindingFlagsCreateInfoEXT>(p_create_info->pNext);
70
John Zulauf48a6a702017-12-22 17:14:54 -070071 binding_type_stats_ = {0, 0, 0};
Jeff Bolzfdf96072018-04-10 14:32:18 -050072 std::set<ExtendedBinding, BindingNumCmp> sorted_bindings;
John Zulauf508d13a2018-01-05 15:10:34 -070073 const uint32_t input_bindings_count = p_create_info->bindingCount;
74 // Sort the input bindings in binding number order, eliminating duplicates
75 for (uint32_t i = 0; i < input_bindings_count; i++) {
Jeff Bolzfdf96072018-04-10 14:32:18 -050076 VkDescriptorBindingFlagsEXT flags = 0;
77 if (flags_create_info && flags_create_info->bindingCount == p_create_info->bindingCount) {
78 flags = flags_create_info->pBindingFlags[i];
79 }
80 sorted_bindings.insert(ExtendedBinding(p_create_info->pBindings + i, flags));
John Zulaufb6d71202017-12-22 16:47:09 -070081 }
82
83 // Store the create info in the sorted order from above
Tobin Ehlisa3525e02016-11-17 10:50:52 -070084 std::map<uint32_t, uint32_t> binding_to_dyn_count;
John Zulauf508d13a2018-01-05 15:10:34 -070085 uint32_t index = 0;
86 binding_count_ = static_cast<uint32_t>(sorted_bindings.size());
87 bindings_.reserve(binding_count_);
Jeff Bolzfdf96072018-04-10 14:32:18 -050088 binding_flags_.reserve(binding_count_);
John Zulauf508d13a2018-01-05 15:10:34 -070089 binding_to_index_map_.reserve(binding_count_);
90 for (auto input_binding : sorted_bindings) {
91 // Add to binding and map, s.t. it is robust to invalid duplication of binding_num
Jeff Bolzfdf96072018-04-10 14:32:18 -050092 const auto binding_num = input_binding.layout_binding->binding;
John Zulauf508d13a2018-01-05 15:10:34 -070093 binding_to_index_map_[binding_num] = index++;
Jeff Bolzfdf96072018-04-10 14:32:18 -050094 bindings_.emplace_back(input_binding.layout_binding);
John Zulauf508d13a2018-01-05 15:10:34 -070095 auto &binding_info = bindings_.back();
Jeff Bolzfdf96072018-04-10 14:32:18 -050096 binding_flags_.emplace_back(input_binding.binding_flags);
John Zulauf508d13a2018-01-05 15:10:34 -070097
John Zulaufb6d71202017-12-22 16:47:09 -070098 descriptor_count_ += binding_info.descriptorCount;
99 if (binding_info.descriptorCount > 0) {
100 non_empty_bindings_.insert(binding_num);
Tobin Ehlis9637fb22016-12-12 15:59:34 -0700101 }
John Zulaufb6d71202017-12-22 16:47:09 -0700102
103 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
104 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
105 binding_to_dyn_count[binding_num] = binding_info.descriptorCount;
106 dynamic_descriptor_count_ += binding_info.descriptorCount;
John Zulauf48a6a702017-12-22 17:14:54 -0700107 binding_type_stats_.dynamic_buffer_count++;
108 } else if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
109 (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)) {
110 binding_type_stats_.non_dynamic_buffer_count++;
111 } else {
112 binding_type_stats_.image_sampler_count++;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600113 }
114 }
Tobin Ehlis9637fb22016-12-12 15:59:34 -0700115 assert(bindings_.size() == binding_count_);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500116 assert(binding_flags_.size() == binding_count_);
Tobin Ehlis9637fb22016-12-12 15:59:34 -0700117 uint32_t global_index = 0;
John Zulauf7705bfc2019-06-10 09:52:04 -0600118 global_index_range_.reserve(binding_count_);
119 // Vector order is finalized so build vectors of descriptors and dynamic offsets by binding index
Tobin Ehlis9637fb22016-12-12 15:59:34 -0700120 for (uint32_t i = 0; i < binding_count_; ++i) {
John Zulaufc483f442017-12-15 14:02:06 -0700121 auto final_index = global_index + bindings_[i].descriptorCount;
John Zulauf7705bfc2019-06-10 09:52:04 -0600122 global_index_range_.emplace_back(global_index, final_index);
John Zulaufc483f442017-12-15 14:02:06 -0700123 global_index = final_index;
Tobin Ehlis9637fb22016-12-12 15:59:34 -0700124 }
John Zulaufb6d71202017-12-22 16:47:09 -0700125
Tobin Ehlisa3525e02016-11-17 10:50:52 -0700126 // Now create dyn offset array mapping for any dynamic descriptors
127 uint32_t dyn_array_idx = 0;
John Zulaufb6d71202017-12-22 16:47:09 -0700128 binding_to_dynamic_array_idx_map_.reserve(binding_to_dyn_count.size());
Tobin Ehlisa3525e02016-11-17 10:50:52 -0700129 for (const auto &bc_pair : binding_to_dyn_count) {
130 binding_to_dynamic_array_idx_map_[bc_pair.first] = dyn_array_idx;
131 dyn_array_idx += bc_pair.second;
132 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600133}
Tobin Ehlis154c2692016-10-25 09:36:53 -0600134
John Zulaufd47d0612018-02-16 13:00:34 -0700135size_t cvdescriptorset::DescriptorSetLayoutDef::hash() const {
136 hash_util::HashCombiner hc;
137 hc << flags_;
138 hc.Combine(bindings_);
John Zulauf223b69d2018-11-09 16:00:59 -0700139 hc.Combine(binding_flags_);
John Zulaufd47d0612018-02-16 13:00:34 -0700140 return hc.Value();
141}
142//
143
John Zulauf1f8174b2018-02-16 12:58:37 -0700144// Return valid index or "end" i.e. binding_count_;
145// The asserts in "Get" are reduced to the set where no valid answer(like null or 0) could be given
146// Common code for all binding lookups.
147uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetIndexFromBinding(uint32_t binding) const {
148 const auto &bi_itr = binding_to_index_map_.find(binding);
149 if (bi_itr != binding_to_index_map_.cend()) return bi_itr->second;
150 return GetBindingCount();
151}
152VkDescriptorSetLayoutBinding const *cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorSetLayoutBindingPtrFromIndex(
153 const uint32_t index) const {
154 if (index >= bindings_.size()) return nullptr;
155 return bindings_[index].ptr();
156}
157// Return descriptorCount for given index, 0 if index is unavailable
158uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorCountFromIndex(const uint32_t index) const {
159 if (index >= bindings_.size()) return 0;
160 return bindings_[index].descriptorCount;
161}
162// For the given index, return descriptorType
163VkDescriptorType cvdescriptorset::DescriptorSetLayoutDef::GetTypeFromIndex(const uint32_t index) const {
164 assert(index < bindings_.size());
165 if (index < bindings_.size()) return bindings_[index].descriptorType;
166 return VK_DESCRIPTOR_TYPE_MAX_ENUM;
167}
168// For the given index, return stageFlags
169VkShaderStageFlags cvdescriptorset::DescriptorSetLayoutDef::GetStageFlagsFromIndex(const uint32_t index) const {
170 assert(index < bindings_.size());
171 if (index < bindings_.size()) return bindings_[index].stageFlags;
172 return VkShaderStageFlags(0);
173}
Jeff Bolzfdf96072018-04-10 14:32:18 -0500174// Return binding flags for given index, 0 if index is unavailable
175VkDescriptorBindingFlagsEXT cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorBindingFlagsFromIndex(
176 const uint32_t index) const {
177 if (index >= binding_flags_.size()) return 0;
178 return binding_flags_[index];
179}
John Zulauf1f8174b2018-02-16 12:58:37 -0700180
John Zulauf7705bfc2019-06-10 09:52:04 -0600181const cvdescriptorset::IndexRange &cvdescriptorset::DescriptorSetLayoutDef::GetGlobalIndexRangeFromIndex(uint32_t index) const {
182 const static IndexRange kInvalidRange = {0xFFFFFFFF, 0xFFFFFFFF};
183 if (index >= binding_flags_.size()) return kInvalidRange;
184 return global_index_range_[index];
John Zulauf1f8174b2018-02-16 12:58:37 -0700185}
186
John Zulauf7705bfc2019-06-10 09:52:04 -0600187// For the given binding, return the global index range (half open)
188// As start and end are often needed in pairs, get both with a single lookup.
John Zulauf1f8174b2018-02-16 12:58:37 -0700189const cvdescriptorset::IndexRange &cvdescriptorset::DescriptorSetLayoutDef::GetGlobalIndexRangeFromBinding(
190 const uint32_t binding) const {
John Zulauf7705bfc2019-06-10 09:52:04 -0600191 uint32_t index = GetIndexFromBinding(binding);
192 return GetGlobalIndexRangeFromIndex(index);
John Zulauf1f8174b2018-02-16 12:58:37 -0700193}
194
195// For given binding, return ptr to ImmutableSampler array
196VkSampler const *cvdescriptorset::DescriptorSetLayoutDef::GetImmutableSamplerPtrFromBinding(const uint32_t binding) const {
197 const auto &bi_itr = binding_to_index_map_.find(binding);
198 if (bi_itr != binding_to_index_map_.end()) {
199 return bindings_[bi_itr->second].pImmutableSamplers;
200 }
201 return nullptr;
202}
203// Move to next valid binding having a non-zero binding count
204uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetNextValidBinding(const uint32_t binding) const {
205 auto it = non_empty_bindings_.upper_bound(binding);
206 assert(it != non_empty_bindings_.cend());
207 if (it != non_empty_bindings_.cend()) return *it;
208 return GetMaxBinding() + 1;
209}
210// For given index, return ptr to ImmutableSampler array
211VkSampler const *cvdescriptorset::DescriptorSetLayoutDef::GetImmutableSamplerPtrFromIndex(const uint32_t index) const {
212 if (index < bindings_.size()) {
213 return bindings_[index].pImmutableSamplers;
214 }
215 return nullptr;
216}
John Zulauf9ce3b252019-06-06 15:20:22 -0600217
218// If our layout is compatible with rh_ds_layout, return true.
219bool cvdescriptorset::DescriptorSetLayout::IsCompatible(DescriptorSetLayout const *rh_ds_layout) const {
220 bool compatible = (this == rh_ds_layout) || (GetLayoutDef() == rh_ds_layout->GetLayoutDef());
221 return compatible;
222}
John Zulauf1f8174b2018-02-16 12:58:37 -0700223
John Zulauff43695f2019-09-13 17:56:26 -0600224// TODO: Find a way to add smarts to the autogenerated version of this
225static std::string smart_string_VkShaderStageFlags(VkShaderStageFlags stage_flags) {
226 if (stage_flags == VK_SHADER_STAGE_ALL) {
227 return string_VkShaderStageFlagBits(VK_SHADER_STAGE_ALL);
228 }
229
230 return string_VkShaderStageFlags(stage_flags);
231}
232
233// If our layout is compatible with bound_dsl, return true,
234// else return false and fill in error_msg will description of what causes incompatibility
235bool cvdescriptorset::VerifySetLayoutCompatibility(const debug_report_data *report_data, DescriptorSetLayout const *layout_dsl,
236 DescriptorSetLayout const *bound_dsl, std::string *error_msg) {
237 // Short circuit the detailed check.
238 if (layout_dsl->IsCompatible(bound_dsl)) return true;
239
240 // 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 -0600241 // Should only be run if trivial accept has failed, and in that context should return false.
John Zulauff43695f2019-09-13 17:56:26 -0600242 VkDescriptorSetLayout layout_dsl_handle = layout_dsl->GetDescriptorSetLayout();
243 VkDescriptorSetLayout bound_dsl_handle = bound_dsl->GetDescriptorSetLayout();
244 DescriptorSetLayoutDef const *layout_ds_layout_def = layout_dsl->GetLayoutDef();
245 DescriptorSetLayoutDef const *bound_ds_layout_def = bound_dsl->GetLayoutDef();
John Zulauf9ce3b252019-06-06 15:20:22 -0600246
247 // Check descriptor counts
John Zulauff43695f2019-09-13 17:56:26 -0600248 const auto bound_total_count = bound_ds_layout_def->GetTotalDescriptorCount();
249 if (layout_ds_layout_def->GetTotalDescriptorCount() != bound_ds_layout_def->GetTotalDescriptorCount()) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700250 std::stringstream error_str;
John Zulauff43695f2019-09-13 17:56:26 -0600251 error_str << report_data->FormatHandle(layout_dsl_handle) << " from pipeline layout has "
252 << layout_ds_layout_def->GetTotalDescriptorCount() << " total descriptors, but "
253 << report_data->FormatHandle(bound_dsl_handle) << ", which is bound, has " << bound_total_count
254 << " total descriptors.";
John Zulauf1f8174b2018-02-16 12:58:37 -0700255 *error_msg = error_str.str();
256 return false; // trivial fail case
257 }
John Zulaufd47d0612018-02-16 13:00:34 -0700258
John Zulauf1f8174b2018-02-16 12:58:37 -0700259 // Descriptor counts match so need to go through bindings one-by-one
260 // and verify that type and stageFlags match
John Zulauff43695f2019-09-13 17:56:26 -0600261 for (const auto &layout_binding : layout_ds_layout_def->GetBindings()) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700262 // TODO : Do we also need to check immutable samplers?
John Zulauff43695f2019-09-13 17:56:26 -0600263 const auto bound_binding = bound_ds_layout_def->GetBindingInfoFromBinding(layout_binding.binding);
264 if (layout_binding.descriptorCount != bound_binding->descriptorCount) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700265 std::stringstream error_str;
John Zulauff43695f2019-09-13 17:56:26 -0600266 error_str << "Binding " << layout_binding.binding << " for " << report_data->FormatHandle(layout_dsl_handle)
267 << " from pipeline layout has a descriptorCount of " << layout_binding.descriptorCount << " but binding "
268 << layout_binding.binding << " for " << report_data->FormatHandle(bound_dsl_handle)
269 << ", which is bound, has a descriptorCount of " << bound_binding->descriptorCount;
John Zulauf1f8174b2018-02-16 12:58:37 -0700270 *error_msg = error_str.str();
271 return false;
John Zulauff43695f2019-09-13 17:56:26 -0600272 } else if (layout_binding.descriptorType != bound_binding->descriptorType) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700273 std::stringstream error_str;
John Zulauff43695f2019-09-13 17:56:26 -0600274 error_str << "Binding " << layout_binding.binding << " for " << report_data->FormatHandle(layout_dsl_handle)
275 << " from pipeline layout is type '" << string_VkDescriptorType(layout_binding.descriptorType)
276 << "' but binding " << layout_binding.binding << " for " << report_data->FormatHandle(bound_dsl_handle)
277 << ", which is bound, is type '" << string_VkDescriptorType(bound_binding->descriptorType) << "'";
John Zulauf1f8174b2018-02-16 12:58:37 -0700278 *error_msg = error_str.str();
279 return false;
John Zulauff43695f2019-09-13 17:56:26 -0600280 } else if (layout_binding.stageFlags != bound_binding->stageFlags) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700281 std::stringstream error_str;
John Zulauff43695f2019-09-13 17:56:26 -0600282 error_str << "Binding " << layout_binding.binding << " for " << report_data->FormatHandle(layout_dsl_handle)
283 << " from pipeline layout has stageFlags " << smart_string_VkShaderStageFlags(layout_binding.stageFlags)
284 << " but binding " << layout_binding.binding << " for " << report_data->FormatHandle(bound_dsl_handle)
285 << ", which is bound, has stageFlags " << smart_string_VkShaderStageFlags(bound_binding->stageFlags);
John Zulauf1f8174b2018-02-16 12:58:37 -0700286 *error_msg = error_str.str();
287 return false;
288 }
289 }
Tony-LunarG692b8b42019-09-30 16:07:26 -0600290
291 const auto &ds_layout_flags = layout_ds_layout_def->GetBindingFlags();
292 const auto &bound_layout_flags = bound_ds_layout_def->GetBindingFlags();
293 if (bound_layout_flags != ds_layout_flags) {
294 std::stringstream error_str;
295 assert(ds_layout_flags.size() == bound_layout_flags.size());
296 size_t i;
297 for (i = 0; i < ds_layout_flags.size(); i++) {
298 if (ds_layout_flags[i] != bound_layout_flags[i]) break;
299 }
300 error_str << report_data->FormatHandle(layout_dsl_handle)
301 << " from pipeline layout does not have the same binding flags at binding " << i << " ( "
302 << string_VkDescriptorBindingFlagsEXT(ds_layout_flags[i]) << " ) as "
303 << report_data->FormatHandle(bound_dsl_handle) << " ( "
304 << string_VkDescriptorBindingFlagsEXT(bound_layout_flags[i]) << " ), which is bound";
305 *error_msg = error_str.str();
306 return false;
307 }
308
John Zulauf9ce3b252019-06-06 15:20:22 -0600309 // No detailed check should succeed if the trivial check failed -- or the dictionary has failed somehow.
310 bool compatible = true;
311 assert(!compatible);
312 return compatible;
John Zulauf1f8174b2018-02-16 12:58:37 -0700313}
314
315bool cvdescriptorset::DescriptorSetLayoutDef::IsNextBindingConsistent(const uint32_t binding) const {
316 if (!binding_to_index_map_.count(binding + 1)) return false;
317 auto const &bi_itr = binding_to_index_map_.find(binding);
318 if (bi_itr != binding_to_index_map_.end()) {
319 const auto &next_bi_itr = binding_to_index_map_.find(binding + 1);
320 if (next_bi_itr != binding_to_index_map_.end()) {
321 auto type = bindings_[bi_itr->second].descriptorType;
322 auto stage_flags = bindings_[bi_itr->second].stageFlags;
323 auto immut_samp = bindings_[bi_itr->second].pImmutableSamplers ? true : false;
Jeff Bolzfdf96072018-04-10 14:32:18 -0500324 auto flags = binding_flags_[bi_itr->second];
John Zulauf1f8174b2018-02-16 12:58:37 -0700325 if ((type != bindings_[next_bi_itr->second].descriptorType) ||
326 (stage_flags != bindings_[next_bi_itr->second].stageFlags) ||
Jeff Bolzfdf96072018-04-10 14:32:18 -0500327 (immut_samp != (bindings_[next_bi_itr->second].pImmutableSamplers ? true : false)) ||
328 (flags != binding_flags_[next_bi_itr->second])) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700329 return false;
330 }
331 return true;
332 }
333 }
334 return false;
335}
John Zulauf1f8174b2018-02-16 12:58:37 -0700336
337// The DescriptorSetLayout stores the per handle data for a descriptor set layout, and references the common defintion for the
338// handle invariant portion
339cvdescriptorset::DescriptorSetLayout::DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info,
340 const VkDescriptorSetLayout layout)
Jeff Bolz6ae39612019-10-11 20:57:36 -0500341 : layout_(layout), layout_id_(GetCanonicalId(p_create_info)) {}
John Zulauf1f8174b2018-02-16 12:58:37 -0700342
Tobin Ehlis154c2692016-10-25 09:36:53 -0600343// Validate descriptor set layout create info
John Zulaufd9435c32019-06-05 15:55:36 -0600344bool cvdescriptorset::ValidateDescriptorSetLayoutCreateInfo(
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700345 const ValidationObject *val_obj, const VkDescriptorSetLayoutCreateInfo *create_info, const bool push_descriptor_ext,
Jeff Bolzfdf96072018-04-10 14:32:18 -0500346 const uint32_t max_push_descriptors, const bool descriptor_indexing_ext,
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700347 const VkPhysicalDeviceVulkan12Features *core12_features,
Jeff Bolze54ae892018-09-08 12:16:29 -0500348 const VkPhysicalDeviceInlineUniformBlockFeaturesEXT *inline_uniform_block_features,
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600349 const VkPhysicalDeviceInlineUniformBlockPropertiesEXT *inline_uniform_block_props, const DeviceExtensions *device_extensions) {
Tobin Ehlis154c2692016-10-25 09:36:53 -0600350 bool skip = false;
351 std::unordered_set<uint32_t> bindings;
John Zulauf0fdeab32018-01-23 11:27:35 -0700352 uint64_t total_descriptors = 0;
353
Jeff Bolzfdf96072018-04-10 14:32:18 -0500354 const auto *flags_create_info = lvl_find_in_chain<VkDescriptorSetLayoutBindingFlagsCreateInfoEXT>(create_info->pNext);
355
356 const bool push_descriptor_set = !!(create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR);
John Zulauf0fdeab32018-01-23 11:27:35 -0700357 if (push_descriptor_set && !push_descriptor_ext) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700358 skip |= val_obj->LogError(val_obj->device, kVUID_Core_DrawState_ExtensionNotEnabled,
359 "Attempted to use %s in %s but its required extension %s has not been enabled.\n",
360 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR",
361 "VkDescriptorSetLayoutCreateInfo::flags", VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
John Zulauf0fdeab32018-01-23 11:27:35 -0700362 }
363
Jeff Bolzfdf96072018-04-10 14:32:18 -0500364 const bool update_after_bind_set = !!(create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT);
365 if (update_after_bind_set && !descriptor_indexing_ext) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700366 skip |= val_obj->LogError(val_obj->device, kVUID_Core_DrawState_ExtensionNotEnabled,
367 "Attemped to use %s in %s but its required extension %s has not been enabled.\n",
368 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT",
369 "VkDescriptorSetLayoutCreateInfo::flags", VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500370 }
371
John Zulauf0fdeab32018-01-23 11:27:35 -0700372 auto valid_type = [push_descriptor_set](const VkDescriptorType type) {
373 return !push_descriptor_set ||
Dave Houlton142c4cb2018-10-17 15:04:41 -0600374 ((type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) && (type != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) &&
Jeff Bolze54ae892018-09-08 12:16:29 -0500375 (type != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT));
John Zulauf0fdeab32018-01-23 11:27:35 -0700376 };
377
Jeff Bolzfdf96072018-04-10 14:32:18 -0500378 uint32_t max_binding = 0;
379
Tobin Ehlis154c2692016-10-25 09:36:53 -0600380 for (uint32_t i = 0; i < create_info->bindingCount; ++i) {
John Zulauf0fdeab32018-01-23 11:27:35 -0700381 const auto &binding_info = create_info->pBindings[i];
Jeff Bolzfdf96072018-04-10 14:32:18 -0500382 max_binding = std::max(max_binding, binding_info.binding);
383
John Zulauf0fdeab32018-01-23 11:27:35 -0700384 if (!bindings.insert(binding_info.binding).second) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700385 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-binding-00279",
386 "duplicated binding number in VkDescriptorSetLayoutBinding.");
Tobin Ehlis154c2692016-10-25 09:36:53 -0600387 }
John Zulauf0fdeab32018-01-23 11:27:35 -0700388 if (!valid_type(binding_info.descriptorType)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700389 skip |= val_obj->LogError(val_obj->device,
390 (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
391 ? "VUID-VkDescriptorSetLayoutCreateInfo-flags-02208"
392 : "VUID-VkDescriptorSetLayoutCreateInfo-flags-00280",
393 "invalid type %s ,for push descriptors in VkDescriptorSetLayoutBinding entry %" PRIu32 ".",
394 string_VkDescriptorType(binding_info.descriptorType), i);
John Zulauf0fdeab32018-01-23 11:27:35 -0700395 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500396
397 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600398 if (!device_extensions->vk_ext_inline_uniform_block) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700399 skip |= val_obj->LogError(
400 val_obj->device, "UNASSIGNED-Extension not enabled",
401 "Creating VkDescriptorSetLayout with descriptor type VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT "
402 "but extension %s is missing",
403 VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME);
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600404 } else {
405 if ((binding_info.descriptorCount % 4) != 0) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700406 skip |=
407 val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-02209",
408 "descriptorCount =(%" PRIu32 ") must be a multiple of 4", binding_info.descriptorCount);
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600409 }
410 if (binding_info.descriptorCount > inline_uniform_block_props->maxInlineUniformBlockSize) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700411 skip |=
412 val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-02210",
413 "descriptorCount =(%" PRIu32 ") must be less than or equal to maxInlineUniformBlockSize",
414 binding_info.descriptorCount);
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600415 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500416 }
417 }
418
Tony-LunarG7337b312020-04-15 16:40:25 -0600419 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
420 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
421 binding_info.pImmutableSamplers && device_extensions->vk_ext_custom_border_color) {
422 const CoreChecks *core_checks = reinterpret_cast<const CoreChecks *>(val_obj);
423 for (uint32_t j = 0; j < binding_info.descriptorCount; j++) {
424 const SAMPLER_STATE *sampler_state = core_checks->GetSamplerState(binding_info.pImmutableSamplers[j]);
425 if (sampler_state && (sampler_state->createInfo.borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT ||
426 sampler_state->createInfo.borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT)) {
427 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-pImmutableSamplers-04009",
428 "Sampler %" PRIu64 " presented as immutable has a custom border color",
429 binding_info.pImmutableSamplers[j]);
430 }
431 }
432 }
433
John Zulauf0fdeab32018-01-23 11:27:35 -0700434 total_descriptors += binding_info.descriptorCount;
Tobin Ehlis154c2692016-10-25 09:36:53 -0600435 }
John Zulauf0fdeab32018-01-23 11:27:35 -0700436
Jeff Bolzfdf96072018-04-10 14:32:18 -0500437 if (flags_create_info) {
438 if (flags_create_info->bindingCount != 0 && flags_create_info->bindingCount != create_info->bindingCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700439 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-bindingCount-03002",
440 "VkDescriptorSetLayoutCreateInfo::bindingCount (%d) != "
441 "VkDescriptorSetLayoutBindingFlagsCreateInfoEXT::bindingCount (%d)",
442 create_info->bindingCount, flags_create_info->bindingCount);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500443 }
444
445 if (flags_create_info->bindingCount == create_info->bindingCount) {
446 for (uint32_t i = 0; i < create_info->bindingCount; ++i) {
447 const auto &binding_info = create_info->pBindings[i];
448
449 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT) {
450 if (!update_after_bind_set) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700451 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-flags-03000",
452 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500453 }
454
455 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700456 !core12_features->descriptorBindingUniformBufferUpdateAfterBind) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700457 skip |= val_obj->LogError(val_obj->device,
458 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
459 "descriptorBindingUniformBufferUpdateAfterBind-03005",
460 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500461 }
462 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
463 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
464 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700465 !core12_features->descriptorBindingSampledImageUpdateAfterBind) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700466 skip |= val_obj->LogError(val_obj->device,
467 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
468 "descriptorBindingSampledImageUpdateAfterBind-03006",
469 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500470 }
471 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700472 !core12_features->descriptorBindingStorageImageUpdateAfterBind) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700473 skip |= val_obj->LogError(val_obj->device,
474 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
475 "descriptorBindingStorageImageUpdateAfterBind-03007",
476 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500477 }
478 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700479 !core12_features->descriptorBindingStorageBufferUpdateAfterBind) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700480 skip |= val_obj->LogError(val_obj->device,
481 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
482 "descriptorBindingStorageBufferUpdateAfterBind-03008",
483 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500484 }
485 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700486 !core12_features->descriptorBindingUniformTexelBufferUpdateAfterBind) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700487 skip |= val_obj->LogError(val_obj->device,
488 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
489 "descriptorBindingUniformTexelBufferUpdateAfterBind-03009",
490 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500491 }
492 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700493 !core12_features->descriptorBindingStorageTexelBufferUpdateAfterBind) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700494 skip |= val_obj->LogError(val_obj->device,
495 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
496 "descriptorBindingStorageTexelBufferUpdateAfterBind-03010",
497 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500498 }
499 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ||
500 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
501 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700502 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-None-03011",
503 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500504 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500505
506 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT &&
507 !inline_uniform_block_features->descriptorBindingInlineUniformBlockUpdateAfterBind) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700508 skip |= val_obj->LogError(val_obj->device,
509 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
510 "descriptorBindingInlineUniformBlockUpdateAfterBind-02211",
511 "Invalid flags (VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT) for "
512 "VkDescriptorSetLayoutBinding entry %" PRIu32
513 " with descriptorBindingInlineUniformBlockUpdateAfterBind not enabled",
514 i);
Jeff Bolze54ae892018-09-08 12:16:29 -0500515 }
Jeff Bolzfdf96072018-04-10 14:32:18 -0500516 }
517
518 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT) {
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700519 if (!core12_features->descriptorBindingUpdateUnusedWhilePending) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700520 skip |= val_obj->LogError(
521 val_obj->device,
Mike Schuchardt65847d92019-12-20 13:50:47 -0800522 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingUpdateUnusedWhilePending-03012",
Dave Houltond8ed0212018-05-16 17:18:24 -0600523 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500524 }
525 }
526
527 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT) {
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700528 if (!core12_features->descriptorBindingPartiallyBound) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700529 skip |= val_obj->LogError(
530 val_obj->device,
531 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingPartiallyBound-03013",
532 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500533 }
534 }
535
536 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT) {
537 if (binding_info.binding != max_binding) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700538 skip |= val_obj->LogError(val_obj->device,
539 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03004",
540 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500541 }
542
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700543 if (!core12_features->descriptorBindingVariableDescriptorCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700544 skip |= val_obj->LogError(
545 val_obj->device,
Mike Schuchardt65847d92019-12-20 13:50:47 -0800546 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingVariableDescriptorCount-03014",
Dave Houltond8ed0212018-05-16 17:18:24 -0600547 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500548 }
549 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
550 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700551 skip |= val_obj->LogError(val_obj->device,
552 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03015",
553 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500554 }
555 }
556
557 if (push_descriptor_set &&
558 (flags_create_info->pBindingFlags[i] &
559 (VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT |
560 VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT))) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700561 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-flags-03003",
562 "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500563 }
564 }
565 }
566 }
567
John Zulauf0fdeab32018-01-23 11:27:35 -0700568 if ((push_descriptor_set) && (total_descriptors > max_push_descriptors)) {
569 const char *undefined = push_descriptor_ext ? "" : " -- undefined";
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700570 skip |= val_obj->LogError(
571 val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-flags-00281",
572 "for push descriptor, total descriptor count in layout (%" PRIu64
573 ") must not be greater than VkPhysicalDevicePushDescriptorPropertiesKHR::maxPushDescriptors (%" PRIu32 "%s).",
574 total_descriptors, max_push_descriptors, undefined);
John Zulauf0fdeab32018-01-23 11:27:35 -0700575 }
576
Tobin Ehlis154c2692016-10-25 09:36:53 -0600577 return skip;
578}
579
Mark Lobodzinskie12b6e32020-06-29 11:44:15 -0600580void cvdescriptorset::AllocateDescriptorSetsData::Init(uint32_t count) {
581 layout_nodes.resize(count);
582 for (auto node : layout_nodes) {
583 node = nullptr;
584 }
585}
Tobin Ehlis68d0adf2016-06-01 11:33:50 -0600586
Jeff Bolz41a1ced2019-10-11 11:40:49 -0500587cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, DESCRIPTOR_POOL_STATE *pool_state,
Jeff Bolzfdf96072018-04-10 14:32:18 -0500588 const std::shared_ptr<DescriptorSetLayout const> &layout, uint32_t variable_count,
John Zulaufd2c3dae2019-12-12 11:02:17 -0700589 const cvdescriptorset::DescriptorSet::StateTracker *state_data)
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -0700590 : some_update_(false),
591 set_(set),
Jeff Bolz41a1ced2019-10-11 11:40:49 -0500592 pool_state_(pool_state),
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600593 p_layout_(layout),
John Zulaufd2c3dae2019-12-12 11:02:17 -0700594 state_data_(state_data),
Jeff Bolzdd4cfa12019-08-11 20:57:51 -0500595 variable_count_(variable_count),
596 change_count_(0) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600597 // Foreach binding, create default descriptors of given type
John Zulaufb6d71202017-12-22 16:47:09 -0700598 descriptors_.reserve(p_layout_->GetTotalDescriptorCount());
John Zulaufe4850d42019-12-30 16:10:55 -0700599 descriptor_store_.resize(p_layout_->GetTotalDescriptorCount());
600 auto free_descriptor = descriptor_store_.data();
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600601 for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) {
602 auto type = p_layout_->GetTypeFromIndex(i);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600603 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700604 case VK_DESCRIPTOR_TYPE_SAMPLER: {
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600605 auto immut_sampler = p_layout_->GetImmutableSamplerPtrFromIndex(i);
606 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) {
Tobin Ehlis082c7512017-05-08 11:24:57 -0600607 if (immut_sampler) {
John Zulaufe4850d42019-12-30 16:10:55 -0700608 descriptors_.emplace_back(new ((free_descriptor++)->Sampler())
609 SamplerDescriptor(state_data, immut_sampler + di));
Tobin Ehlis082c7512017-05-08 11:24:57 -0600610 some_update_ = true; // Immutable samplers are updated at creation
611 } else
John Zulaufe4850d42019-12-30 16:10:55 -0700612 descriptors_.emplace_back(new ((free_descriptor++)->Sampler()) SamplerDescriptor(state_data, nullptr));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700613 }
614 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600615 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700616 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600617 auto immut = p_layout_->GetImmutableSamplerPtrFromIndex(i);
618 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) {
Tobin Ehlis082c7512017-05-08 11:24:57 -0600619 if (immut) {
John Zulaufe4850d42019-12-30 16:10:55 -0700620 descriptors_.emplace_back(new ((free_descriptor++)->ImageSampler())
621 ImageSamplerDescriptor(state_data, immut + di));
Tobin Ehlis082c7512017-05-08 11:24:57 -0600622 some_update_ = true; // Immutable samplers are updated at creation
623 } else
John Zulaufe4850d42019-12-30 16:10:55 -0700624 descriptors_.emplace_back(new ((free_descriptor++)->ImageSampler())
625 ImageSamplerDescriptor(state_data, nullptr));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700626 }
627 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600628 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700629 // ImageDescriptors
630 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
631 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
632 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600633 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
John Zulaufe4850d42019-12-30 16:10:55 -0700634 descriptors_.emplace_back(new ((free_descriptor++)->Image()) ImageDescriptor(type));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700635 break;
636 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
637 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600638 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
John Zulaufe4850d42019-12-30 16:10:55 -0700639 descriptors_.emplace_back(new ((free_descriptor++)->Texel()) TexelDescriptor(type));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700640 break;
641 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
642 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
643 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
644 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600645 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
John Zulaufe4850d42019-12-30 16:10:55 -0700646 descriptors_.emplace_back(new ((free_descriptor++)->Buffer()) BufferDescriptor(type));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700647 break;
Jeff Bolze54ae892018-09-08 12:16:29 -0500648 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
649 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
John Zulaufe4850d42019-12-30 16:10:55 -0700650 descriptors_.emplace_back(new ((free_descriptor++)->InlineUniform()) InlineUniformDescriptor(type));
Jeff Bolze54ae892018-09-08 12:16:29 -0500651 break;
Eric Werness30127fd2018-10-31 21:01:03 -0700652 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
Jeff Bolzfbe51582018-09-13 10:01:35 -0500653 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
John Zulaufe4850d42019-12-30 16:10:55 -0700654 descriptors_.emplace_back(new ((free_descriptor++)->AccelerationStructure())
655 AccelerationStructureDescriptor(type));
Jeff Bolzfbe51582018-09-13 10:01:35 -0500656 break;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700657 default:
658 assert(0); // Bad descriptor type specified
659 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600660 }
661 }
662}
Tobin Ehlis56a30942016-05-19 08:00:00 -0600663
Jeff Bolz41a1ced2019-10-11 11:40:49 -0500664cvdescriptorset::DescriptorSet::~DescriptorSet() {}
Chris Forbes57989132016-07-26 17:06:10 +1200665
Shannon McPhersonc06c33d2018-06-28 17:21:12 -0600666static std::string StringDescriptorReqViewType(descriptor_req req) {
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700667 std::string result("");
Mark Lobodzinski29f451a2020-02-10 16:15:30 -0700668 for (unsigned i = 0; i <= VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; i++) {
Chris Forbes57989132016-07-26 17:06:10 +1200669 if (req & (1 << i)) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700670 if (result.size()) result += ", ";
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700671 result += string_VkImageViewType(VkImageViewType(i));
Chris Forbes57989132016-07-26 17:06:10 +1200672 }
673 }
674
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700675 if (!result.size()) result = "(none)";
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700676
677 return result;
Chris Forbes57989132016-07-26 17:06:10 +1200678}
679
Chris Forbesda01e8d2018-08-27 15:36:57 -0700680static char const *StringDescriptorReqComponentType(descriptor_req req) {
681 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_SINT) return "SINT";
682 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_UINT) return "UINT";
683 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT) return "FLOAT";
684 return "(none)";
685}
686
Jeff Bolz6cede832019-08-09 23:30:39 -0500687unsigned DescriptorRequirementsBitsFromFormat(VkFormat fmt) {
Chris Forbesda01e8d2018-08-27 15:36:57 -0700688 if (FormatIsSInt(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_SINT;
689 if (FormatIsUInt(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_UINT;
690 if (FormatIsDepthAndStencil(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT | DESCRIPTOR_REQ_COMPONENT_TYPE_UINT;
691 if (fmt == VK_FORMAT_UNDEFINED) return 0;
692 // everything else -- UNORM/SNORM/FLOAT/USCALED/SSCALED is all float in the shader.
693 return DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT;
694}
695
Tobin Ehlis3066db62016-08-22 08:12:23 -0600696// 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 -0600697// This includes validating that all descriptors in the given bindings are updated,
698// that any update buffers are valid, and that any dynamic offsets are within the bounds of their buffers.
699// Return true if state is acceptable, or false and write an error message into error string
locke-lunarg654a9052020-10-13 16:28:42 -0600700bool CoreChecks::ValidateDrawState(VkPipelineBindPoint bind_point, const DescriptorSet *descriptor_set,
Karl Schultz7090a052020-11-10 08:54:21 -0700701 const BindingReqMap &bindings, const std::vector<uint32_t> &dynamic_offsets,
702 const CMD_BUFFER_STATE *cb_node, const std::vector<VkImageView> &attachment_views,
703 const char *caller, const DrawDispatchVuid &vuids) const {
Tony-LunarGace473a2020-05-06 12:48:04 -0600704 bool result = false;
locke-lunarg540b2252020-08-03 13:23:36 -0600705 VkFramebuffer framebuffer = cb_node->activeFramebuffer ? cb_node->activeFramebuffer->framebuffer : VK_NULL_HANDLE;
Chris Forbesc7090a82016-07-25 18:10:41 +1200706 for (auto binding_pair : bindings) {
707 auto binding = binding_pair.first;
John Zulauf382e1912019-06-10 15:27:44 -0600708 DescriptorSetLayout::ConstBindingIterator binding_it(descriptor_set->GetLayout().get(), binding);
709 if (binding_it.AtEnd()) { // End at construction is the condition for an invalid binding.
Tony-LunarGace473a2020-05-06 12:48:04 -0600710 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600711 result |= LogError(set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -0600712 "%s encountered the following validation error at %s time: Attempting to "
713 "validate DrawState for binding #%u which is an invalid binding for this descriptor set.",
714 report_data->FormatHandle(set).c_str(), caller, binding);
715 return result;
Tobin Ehlis58c59582016-06-21 12:34:33 -0600716 }
Jeff Bolz6cede832019-08-09 23:30:39 -0500717
718 if (binding_it.GetDescriptorBindingFlags() &
719 (VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT)) {
720 // Can't validate the descriptor because it may not have been updated,
721 // or the view could have been destroyed
722 continue;
723 }
locke-lunarg654a9052020-10-13 16:28:42 -0600724 result |= ValidateDescriptorSetBindingData(bind_point, cb_node, descriptor_set, dynamic_offsets, binding_pair, framebuffer,
locke-lunarg36045992020-08-20 16:54:37 -0600725 attachment_views, caller, vuids);
unknown3087a642019-09-26 17:21:05 -0600726 }
Tony-LunarGace473a2020-05-06 12:48:04 -0600727 return result;
unknown3087a642019-09-26 17:21:05 -0600728}
Jeff Bolz6cede832019-08-09 23:30:39 -0500729
locke-lunarg654a9052020-10-13 16:28:42 -0600730std::vector<const SAMPLER_STATE *> GetUnnormalizedCoordinatesSamplerStatesFromDescriptorSet(
731 VkPipelineBindPoint bind_point, const cvdescriptorset::DescriptorClass descriptor_class,
732 const cvdescriptorset::Descriptor &descriptor, const CMD_BUFFER_STATE &cb_node,
Karl Schultz7090a052020-11-10 08:54:21 -0700733 std::pair<const uint32_t, DescriptorRequirement> &binding_info, uint32_t image_index) {
locke-lunarg654a9052020-10-13 16:28:42 -0600734 std::vector<const SAMPLER_STATE *> sampler_states;
735
736 if (descriptor_class == cvdescriptorset::DescriptorClass::ImageSampler) {
737 const cvdescriptorset::ImageSamplerDescriptor *image_descriptor =
738 static_cast<const cvdescriptorset::ImageSamplerDescriptor *>(&descriptor);
739 const auto *sampler_state = image_descriptor->GetSamplerState();
740
741 if (sampler_state->createInfo.unnormalizedCoordinates) sampler_states.emplace_back(sampler_state);
742
743 } else if (descriptor_class == cvdescriptorset::DescriptorClass::Image &&
744 binding_info.second.samplers_used_by_image.size() > image_index) {
745 for (auto &sampler : binding_info.second.samplers_used_by_image[image_index]) {
746 auto *descriptorset = cb_node.GetDescriptorSet(bind_point, sampler.first.sampler_slot.first);
747 if (!descriptorset) {
748 continue;
749 }
750 const auto key = descriptorset->GetSet();
751 auto it = sampler.second.find(key);
752 if (it != sampler.second.end()) {
753 const auto *sampler_state = static_cast<const cvdescriptorset::SamplerDescriptor *>(it->second)->GetSamplerState();
754 if (sampler_state->createInfo.unnormalizedCoordinates) {
755 sampler_states.emplace_back(sampler_state);
756 }
757 continue;
758 }
759
760 const auto *descriptor2 =
761 descriptorset->GetDescriptorFromBinding(sampler.first.sampler_slot.second, sampler.first.sampler_index);
762 if (descriptor2->GetClass() == cvdescriptorset::DescriptorClass::PlainSampler) {
763 sampler.second.emplace(key, descriptor2);
764
765 const auto *sampler_state = static_cast<const cvdescriptorset::SamplerDescriptor *>(descriptor2)->GetSamplerState();
766 if (sampler_state->createInfo.unnormalizedCoordinates) {
767 sampler_states.emplace_back(sampler_state);
768 }
769 }
770 }
771 }
772 return sampler_states;
773}
774
775bool CoreChecks::ValidateDescriptorSetBindingData(VkPipelineBindPoint bind_point, const CMD_BUFFER_STATE *cb_node,
776 const DescriptorSet *descriptor_set, const std::vector<uint32_t> &dynamic_offsets,
Karl Schultz7090a052020-11-10 08:54:21 -0700777 std::pair<const uint32_t, DescriptorRequirement> &binding_info,
locke-lunarg654a9052020-10-13 16:28:42 -0600778 VkFramebuffer framebuffer, const std::vector<VkImageView> &attachment_views,
779 const char *caller, const DrawDispatchVuid &vuids) const {
unknown3087a642019-09-26 17:21:05 -0600780 using DescriptorClass = cvdescriptorset::DescriptorClass;
781 using BufferDescriptor = cvdescriptorset::BufferDescriptor;
782 using ImageDescriptor = cvdescriptorset::ImageDescriptor;
783 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
784 using SamplerDescriptor = cvdescriptorset::SamplerDescriptor;
785 using TexelDescriptor = cvdescriptorset::TexelDescriptor;
Jeff Bolz95176d02020-04-01 00:36:16 -0500786 using AccelerationStructureDescriptor = cvdescriptorset::AccelerationStructureDescriptor;
locke-lunarg36045992020-08-20 16:54:37 -0600787 const auto reqs = binding_info.second.reqs;
788 const auto binding = binding_info.first;
unknown3087a642019-09-26 17:21:05 -0600789 DescriptorSetLayout::ConstBindingIterator binding_it(descriptor_set->GetLayout().get(), binding);
790 {
John Zulauf382e1912019-06-10 15:27:44 -0600791 // Copy the range, the end range is subject to update based on variable length descriptor arrays.
792 cvdescriptorset::IndexRange index_range = binding_it.GetGlobalIndexRange();
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700793 auto array_idx = 0; // Track array idx if we're dealing with array descriptors
Jeff Bolzfdf96072018-04-10 14:32:18 -0500794
John Zulauf382e1912019-06-10 15:27:44 -0600795 if (binding_it.IsVariableDescriptorCount()) {
Jeff Bolzfdf96072018-04-10 14:32:18 -0500796 // Only validate the first N descriptors if it uses variable_count
John Zulauf382e1912019-06-10 15:27:44 -0600797 index_range.end = index_range.start + descriptor_set->GetVariableDescriptorCount();
Jeff Bolzfdf96072018-04-10 14:32:18 -0500798 }
799
John Zulaufc483f442017-12-15 14:02:06 -0700800 for (uint32_t i = index_range.start; i < index_range.end; ++i, ++array_idx) {
Lockeb994adf2019-03-29 23:52:31 -0600801 uint32_t index = i - index_range.start;
John Zulauf382e1912019-06-10 15:27:44 -0600802 const auto *descriptor = descriptor_set->GetDescriptorFromGlobalIndex(i);
Lockeb994adf2019-03-29 23:52:31 -0600803
Jeff Bolz6cede832019-08-09 23:30:39 -0500804 if (descriptor->GetClass() == DescriptorClass::InlineUniform) {
805 // Can't validate the descriptor because it may not have been updated.
Jeff Bolzfdf96072018-04-10 14:32:18 -0500806 continue;
John Zulauf382e1912019-06-10 15:27:44 -0600807 } else if (!descriptor->updated) {
Tony-LunarGace473a2020-05-06 12:48:04 -0600808 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600809 return LogError(set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -0600810 "%s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
811 " index %" PRIu32
812 " is being used in draw but has never been updated via vkUpdateDescriptorSets() or a similar call.",
813 report_data->FormatHandle(set).c_str(), caller, binding, index);
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700814 } else {
John Zulauf382e1912019-06-10 15:27:44 -0600815 auto descriptor_class = descriptor->GetClass();
John Zulaufc93c4252019-06-25 09:19:49 -0600816 if (descriptor_class == DescriptorClass::GeneralBuffer) {
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700817 // Verify that buffers are valid
John Zulauf382e1912019-06-10 15:27:44 -0600818 auto buffer = static_cast<const BufferDescriptor *>(descriptor)->GetBuffer();
Jeff Bolzfaffeb32019-10-04 12:47:16 -0500819 auto buffer_node = static_cast<const BufferDescriptor *>(descriptor)->GetBufferState();
Karl Schultz76d16a42020-11-11 05:05:33 -0700820 if ((!buffer_node && !enabled_features.robustness2_features.nullDescriptor) ||
821 (buffer_node && buffer_node->destroyed)) {
822 auto set = descriptor_set->GetSet();
823 return LogError(set, vuids.descriptor_valid,
824 "%s encountered the following validation error at %s time: Descriptor in "
825 "binding #%" PRIu32 " index %" PRIu32
826 " is using buffer %s that is invalid or has been destroyed.",
827 report_data->FormatHandle(set).c_str(), caller, binding, index,
828 report_data->FormatHandle(buffer).c_str());
829 }
Jeff Bolz165818a2020-05-08 11:19:03 -0500830 if (buffer) {
Karl Schultz76d16a42020-11-11 05:05:33 -0700831 if (!buffer_node->sparse) {
Jeff Bolz165818a2020-05-08 11:19:03 -0500832 for (auto mem_binding : buffer_node->GetBoundMemory()) {
833 if (mem_binding->destroyed) {
834 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600835 return LogError(set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500836 "%s encountered the following validation error at %s time: Descriptor in "
837 "binding #%" PRIu32 " index %" PRIu32
838 " is uses buffer %s that references invalid memory %s.",
839 report_data->FormatHandle(set).c_str(), caller, binding, index,
840 report_data->FormatHandle(buffer).c_str(),
841 report_data->FormatHandle(mem_binding->mem).c_str());
842 }
Tobin Ehlisc8266452017-04-07 12:20:30 -0600843 }
844 }
Jeff Bolz165818a2020-05-08 11:19:03 -0500845 if (descriptor->IsDynamic()) {
846 // Validate that dynamic offsets are within the buffer
847 auto buffer_size = buffer_node->createInfo.size;
848 auto range = static_cast<const BufferDescriptor *>(descriptor)->GetRange();
849 auto desc_offset = static_cast<const BufferDescriptor *>(descriptor)->GetOffset();
850 auto dyn_offset = dynamic_offsets[binding_it.GetDynamicOffsetIndex() + array_idx];
851 if (VK_WHOLE_SIZE == range) {
852 if ((dyn_offset + desc_offset) > buffer_size) {
853 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600854 return LogError(set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500855 "%s encountered the following validation error at %s time: Descriptor in "
856 "binding #%" PRIu32 " index %" PRIu32
857 " is using buffer %s with update range of VK_WHOLE_SIZE has dynamic offset "
858 "%" PRIu32 " combined with offset %" PRIu64
859 " that oversteps the buffer size of %" PRIu64 ".",
860 report_data->FormatHandle(set).c_str(), caller, binding, index,
861 report_data->FormatHandle(buffer).c_str(), dyn_offset, desc_offset,
862 buffer_size);
863 }
864 } else {
865 if ((dyn_offset + desc_offset + range) > buffer_size) {
866 auto set = descriptor_set->GetSet();
867 return LogError(
locke-lunarg1328e8e2020-08-20 12:40:08 -0600868 set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500869 "%s encountered the following validation error at %s time: "
870 "Descriptor in binding #%" PRIu32 " index %" PRIu32
871 " is uses buffer %s with dynamic offset %" PRIu32 " combined with offset %" PRIu64
872 " and range %" PRIu64 " that oversteps the buffer size of %" PRIu64 ".",
873 report_data->FormatHandle(set).c_str(), caller, binding, index,
874 report_data->FormatHandle(buffer).c_str(), dyn_offset, desc_offset, range, buffer_size);
875 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700876 }
877 }
878 }
John Zulaufc93c4252019-06-25 09:19:49 -0600879 } else if (descriptor_class == DescriptorClass::ImageSampler || descriptor_class == DescriptorClass::Image) {
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700880 VkImageView image_view;
881 VkImageLayout image_layout;
Jeff Bolzfaffeb32019-10-04 12:47:16 -0500882 const IMAGE_VIEW_STATE *image_view_state;
locke-lunarg36045992020-08-20 16:54:37 -0600883
John Zulaufc93c4252019-06-25 09:19:49 -0600884 if (descriptor_class == DescriptorClass::ImageSampler) {
locke-lunarg36045992020-08-20 16:54:37 -0600885 const ImageSamplerDescriptor *image_descriptor = static_cast<const ImageSamplerDescriptor *>(descriptor);
886 image_view = image_descriptor->GetImageView();
887 image_view_state = image_descriptor->GetImageViewState();
888 image_layout = image_descriptor->GetImageLayout();
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700889 } else {
locke-lunarg36045992020-08-20 16:54:37 -0600890 const ImageDescriptor *image_descriptor = static_cast<const ImageDescriptor *>(descriptor);
891 image_view = image_descriptor->GetImageView();
892 image_view_state = image_descriptor->GetImageViewState();
893 image_layout = image_descriptor->GetImageLayout();
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700894 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700895
Karl Schultz76d16a42020-11-11 05:05:33 -0700896 if ((!image_view_state && !enabled_features.robustness2_features.nullDescriptor) ||
897 (image_view_state && image_view_state->destroyed)) {
898 // Image view must have been destroyed since initial update. Could potentially flag the descriptor
899 // as "invalid" (updated = false) at DestroyImageView() time and detect this error at bind time
900
901 auto set = descriptor_set->GetSet();
902 return LogError(set, vuids.descriptor_valid,
903 "%s encountered the following validation error at %s time: Descriptor in "
904 "binding #%" PRIu32 " index %" PRIu32
905 " is using imageView %s that is invalid or has been destroyed.",
906 report_data->FormatHandle(set).c_str(), caller, binding, index,
907 report_data->FormatHandle(image_view).c_str());
908 }
Jeff Bolz165818a2020-05-08 11:19:03 -0500909 if (image_view) {
Jeff Bolz165818a2020-05-08 11:19:03 -0500910 const auto &image_view_ci = image_view_state->create_info;
Jeff Bolz165818a2020-05-08 11:19:03 -0500911 if (reqs & DESCRIPTOR_REQ_ALL_VIEW_TYPE_BITS) {
912 if (~reqs & (1 << image_view_ci.viewType)) {
913 auto set = descriptor_set->GetSet();
914 return LogError(
locke-lunarg1328e8e2020-08-20 12:40:08 -0600915 set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500916 "%s encountered the following validation error at %s time: Descriptor "
917 "in binding #%" PRIu32 " index %" PRIu32 " requires an image view of type %s but got %s.",
918 report_data->FormatHandle(set).c_str(), caller, binding, index,
919 StringDescriptorReqViewType(reqs).c_str(), string_VkImageViewType(image_view_ci.viewType));
920 }
921
922 if (!(reqs & image_view_state->descriptor_format_bits)) {
923 // bad component type
924 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600925 return LogError(set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500926 "%s encountered the following validation error at %s time: Descriptor in binding "
927 "#%" PRIu32 " index %" PRIu32
928 " requires %s component type, but bound descriptor format is %s.",
929 report_data->FormatHandle(set).c_str(), caller, binding, index,
930 StringDescriptorReqComponentType(reqs), string_VkFormat(image_view_ci.format));
931 }
932 }
933
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -0600934 if (!disabled[image_layout_validation]) {
Jeff Bolz165818a2020-05-08 11:19:03 -0500935 auto image_node = image_view_state->image_state.get();
936 assert(image_node);
937 // Verify Image Layout
938 // No "invalid layout" VUID required for this call, since the optimal_layout parameter is UNDEFINED.
939 bool hit_error = false;
940 VerifyImageLayout(cb_node, image_node, image_view_state->normalized_subresource_range,
941 image_view_ci.subresourceRange.aspectMask, image_layout, VK_IMAGE_LAYOUT_UNDEFINED,
942 caller, kVUIDUndefined, "VUID-VkDescriptorImageInfo-imageLayout-00344", &hit_error);
943 if (hit_error) {
944 auto set = descriptor_set->GetSet();
945 return LogError(
locke-lunarg1328e8e2020-08-20 12:40:08 -0600946 set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500947 "%s encountered the following validation error at %s time: Image layout specified "
948 "at vkUpdateDescriptorSet* or vkCmdPushDescriptorSet* time "
949 "doesn't match actual image layout at time descriptor is used. See previous error callback for "
950 "specific details.",
951 report_data->FormatHandle(set).c_str(), caller);
952 }
953 }
954
955 // Verify Sample counts
956 if ((reqs & DESCRIPTOR_REQ_SINGLE_SAMPLE) && image_view_state->samples != VK_SAMPLE_COUNT_1_BIT) {
957 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600958 return LogError(set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500959 "%s encountered the following validation error at %s time: Descriptor in "
960 "binding #%" PRIu32 " index %" PRIu32
961 " requires bound image to have VK_SAMPLE_COUNT_1_BIT but got %s.",
962 report_data->FormatHandle(set).c_str(), caller, binding, index,
963 string_VkSampleCountFlagBits(image_view_state->samples));
964 }
965 if ((reqs & DESCRIPTOR_REQ_MULTI_SAMPLE) && image_view_state->samples == VK_SAMPLE_COUNT_1_BIT) {
Tony-LunarGace473a2020-05-06 12:48:04 -0600966 auto set = descriptor_set->GetSet();
967 return LogError(
locke-lunarg1328e8e2020-08-20 12:40:08 -0600968 set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500969 "%s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
970 " index %" PRIu32 " requires bound image to have multiple samples, but got VK_SAMPLE_COUNT_1_BIT.",
971 report_data->FormatHandle(set).c_str(), caller, binding, index);
Jeff Bolz6cede832019-08-09 23:30:39 -0500972 }
locke-lunarg25b6c352020-08-06 17:44:18 -0600973
locke-lunarge4bf18f2020-08-21 10:23:08 -0600974 const VkDescriptorType descriptor_type = descriptor_set->GetTypeFromBinding(binding);
locke-lunarg540b2252020-08-03 13:23:36 -0600975
locke-lunarg25b6c352020-08-06 17:44:18 -0600976 // Verify VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
977 if ((reqs & DESCRIPTOR_REQ_VIEW_ATOMIC_OPERATION) &&
locke-lunarg540b2252020-08-03 13:23:36 -0600978 (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) &&
locke-lunarg25b6c352020-08-06 17:44:18 -0600979 !(image_view_state->format_features & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)) {
980 auto set = descriptor_set->GetSet();
981 LogObjectList objlist(set);
982 objlist.add(image_view);
983 return LogError(
984 objlist, vuids.imageview_atomic,
985 "%s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
986 " index %" PRIu32
987 ", %s, format %s, doesn't "
988 "contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT.",
989 report_data->FormatHandle(set).c_str(), caller, binding, index,
990 report_data->FormatHandle(image_view).c_str(), string_VkFormat(image_view_ci.format));
991 }
locke-lunarg540b2252020-08-03 13:23:36 -0600992
993 // Verify if attachments are used in DescriptorSet
994 if (attachment_views.size() > 0 && (descriptor_type != VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
995 uint32_t view_index = 0;
996 for (const auto &view : attachment_views) {
997 if (view == image_view) {
998 auto set = descriptor_set->GetSet();
999 LogObjectList objlist(set);
1000 objlist.add(image_view);
1001 objlist.add(framebuffer);
1002 return LogError(objlist, vuids.image_subresources,
1003 "%s encountered the following validation error at %s time: %s is used in "
1004 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1005 " and %s attachment # %" PRIu32 ".",
1006 report_data->FormatHandle(set).c_str(), caller,
1007 report_data->FormatHandle(image_view).c_str(), binding, index,
1008 report_data->FormatHandle(framebuffer).c_str(), view_index);
1009 } else if (view != VK_NULL_HANDLE) {
1010 const auto *view_state = Get<IMAGE_VIEW_STATE>(view);
1011 if (image_view_state->OverlapSubresource(*view_state)) {
1012 auto set = descriptor_set->GetSet();
1013 LogObjectList objlist(set);
1014 objlist.add(image_view);
1015 objlist.add(framebuffer);
1016 objlist.add(view);
1017 return LogError(
1018 objlist, vuids.image_subresources,
1019 "%s encountered the following validation error at %s time: Image subresources of %s in "
1020 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1021 " and %s in %s attachment # %" PRIu32 " overlap.",
1022 report_data->FormatHandle(set).c_str(), caller,
1023 report_data->FormatHandle(image_view).c_str(), binding, index,
1024 report_data->FormatHandle(view).c_str(), report_data->FormatHandle(framebuffer).c_str(),
1025 view_index);
1026 }
1027 }
1028 ++view_index;
1029 }
1030 }
locke-lunarg36045992020-08-20 16:54:37 -06001031
locke-lunarg654a9052020-10-13 16:28:42 -06001032 // Here is some unnormalizedCoordinates sampler validations. But because it might take long time to find out
1033 // samplers, it will look for them when it needs.
1034 std::vector<const SAMPLER_STATE *> unnormalizedCoordinates_sampler_states;
1035 bool update_unnormalizedCoordinates_sampler_states = false;
1036
1037 // If ImageView is used by a unnormalizedCoordinates sampler, it needs to check ImageView type
1038 if (image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_3D || image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
1039 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY ||
1040 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY ||
1041 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
1042 update_unnormalizedCoordinates_sampler_states = true;
1043 unnormalizedCoordinates_sampler_states = GetUnnormalizedCoordinatesSamplerStatesFromDescriptorSet(
1044 bind_point, descriptor_class, *descriptor, *cb_node, binding_info, index);
1045
1046 for (const auto *sampler_state : unnormalizedCoordinates_sampler_states) {
locke-lunarg36045992020-08-20 16:54:37 -06001047 auto set = descriptor_set->GetSet();
1048 LogObjectList objlist(set);
1049 objlist.add(image_view);
1050 objlist.add(sampler_state->sampler);
1051 return LogError(objlist, vuids.sampler_imageview_type,
1052 "%s encountered the following validation error at %s time: %s, type: %s in "
1053 "Descriptor in binding #%" PRIu32 " index %" PRIu32 "is used by %s.",
1054 report_data->FormatHandle(set).c_str(), caller,
1055 report_data->FormatHandle(image_view).c_str(),
1056 string_VkImageViewType(image_view_ci.viewType), binding, index,
1057 report_data->FormatHandle(sampler_state->sampler).c_str());
1058 }
locke-lunarg654a9052020-10-13 16:28:42 -06001059 }
1060
1061 // sampler must not be used with any of the SPIR-V OpImageSample* or OpImageSparseSample* instructions
1062 // with ImplicitLod, Dref or Proj in their name
1063 if (reqs & DESCRIPTOR_REQ_SAMPLER_IMPLICITLOD_DREF_PROJ) {
1064 if (!update_unnormalizedCoordinates_sampler_states) {
1065 update_unnormalizedCoordinates_sampler_states = true;
1066 unnormalizedCoordinates_sampler_states = GetUnnormalizedCoordinatesSamplerStatesFromDescriptorSet(
1067 bind_point, descriptor_class, *descriptor, *cb_node, binding_info, index);
1068 }
1069
1070 for (const auto *sampler_state : unnormalizedCoordinates_sampler_states) {
locke-lunarg12d20992020-09-21 12:46:49 -06001071 auto set = descriptor_set->GetSet();
1072 LogObjectList objlist(set);
1073 objlist.add(image_view);
1074 objlist.add(sampler_state->sampler);
1075 return LogError(objlist, vuids.sampler_implicitLod_dref_proj,
1076 "%s encountered the following validation error at %s time: %s in "
1077 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1078 " is used by %s that uses invalid operator.",
1079 report_data->FormatHandle(set).c_str(), caller,
1080 report_data->FormatHandle(image_view).c_str(), binding, index,
1081 report_data->FormatHandle(sampler_state->sampler).c_str());
1082 }
locke-lunarg654a9052020-10-13 16:28:42 -06001083 }
1084
1085 // sampler must not be used with any of the SPIR-V OpImageSample* or OpImageSparseSample* instructions
1086 // that includes a LOD bias or any offset values
1087 if (reqs & DESCRIPTOR_REQ_SAMPLER_BIAS_OFFSET) {
1088 if (!update_unnormalizedCoordinates_sampler_states) {
1089 update_unnormalizedCoordinates_sampler_states = true;
1090 unnormalizedCoordinates_sampler_states = GetUnnormalizedCoordinatesSamplerStatesFromDescriptorSet(
1091 bind_point, descriptor_class, *descriptor, *cb_node, binding_info, index);
1092 }
1093
1094 for (const auto *sampler_state : unnormalizedCoordinates_sampler_states) {
locke-lunargae2a43c2020-09-22 17:21:57 -06001095 auto set = descriptor_set->GetSet();
1096 LogObjectList objlist(set);
1097 objlist.add(image_view);
1098 objlist.add(sampler_state->sampler);
1099 return LogError(objlist, vuids.sampler_bias_offset,
1100 "%s encountered the following validation error at %s time: %s in "
1101 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1102 " is used by %s that uses invalid bias or offset operator.",
1103 report_data->FormatHandle(set).c_str(), caller,
1104 report_data->FormatHandle(image_view).c_str(), binding, index,
1105 report_data->FormatHandle(sampler_state->sampler).c_str());
1106 }
locke-lunarg36045992020-08-20 16:54:37 -06001107 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -07001108 }
John Zulaufc93c4252019-06-25 09:19:49 -06001109 } else if (descriptor_class == DescriptorClass::TexelBuffer) {
John Zulauf382e1912019-06-10 15:27:44 -06001110 auto texel_buffer = static_cast<const TexelDescriptor *>(descriptor);
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001111 auto buffer_view = texel_buffer->GetBufferView();
1112 auto buffer_view_state = texel_buffer->GetBufferViewState();
Chris Forbese92dd1d2019-01-21 15:58:57 -08001113
Karl Schultz76d16a42020-11-11 05:05:33 -07001114 if ((!buffer_view_state && !enabled_features.robustness2_features.nullDescriptor) ||
1115 (buffer_view_state && buffer_view_state->destroyed)) {
1116 auto set = descriptor_set->GetSet();
1117 return LogError(set, vuids.descriptor_valid,
1118 "%s encountered the following validation error at %s time: Descriptor in "
1119 "binding #%" PRIu32 " index %" PRIu32
1120 " is using bufferView %s that is invalid or has been destroyed.",
1121 report_data->FormatHandle(set).c_str(), caller, binding, index,
1122 report_data->FormatHandle(buffer_view).c_str());
1123 }
Jeff Bolz165818a2020-05-08 11:19:03 -05001124 if (buffer_view) {
Jeff Bolz165818a2020-05-08 11:19:03 -05001125 auto buffer = buffer_view_state->create_info.buffer;
1126 auto buffer_state = buffer_view_state->buffer_state.get();
1127 if (buffer_state->destroyed) {
1128 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -06001129 return LogError(set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -05001130 "%s encountered the following validation error at %s time: Descriptor in "
1131 "binding #%" PRIu32 " index %" PRIu32 " is using buffer %s that has been destroyed.",
1132 report_data->FormatHandle(set).c_str(), caller, binding, index,
1133 report_data->FormatHandle(buffer).c_str());
1134 }
1135 auto format_bits = DescriptorRequirementsBitsFromFormat(buffer_view_state->create_info.format);
Chris Forbese92dd1d2019-01-21 15:58:57 -08001136
Jeff Bolz165818a2020-05-08 11:19:03 -05001137 if (!(reqs & format_bits)) {
1138 // bad component type
1139 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -06001140 return LogError(set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -05001141 "%s encountered the following validation error at %s time: Descriptor in "
1142 "binding #%" PRIu32 " index %" PRIu32
1143 " requires %s component type, but bound descriptor format is %s.",
1144 report_data->FormatHandle(set).c_str(), caller, binding, index,
1145 StringDescriptorReqComponentType(reqs),
1146 string_VkFormat(buffer_view_state->create_info.format));
1147 }
locke-lunarg25b6c352020-08-06 17:44:18 -06001148
1149 // Verify VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT
1150 if ((reqs & DESCRIPTOR_REQ_VIEW_ATOMIC_OPERATION) &&
locke-lunarge4bf18f2020-08-21 10:23:08 -06001151 (descriptor_set->GetTypeFromBinding(binding) == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) &&
locke-lunarg25b6c352020-08-06 17:44:18 -06001152 !(buffer_view_state->format_features & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT)) {
1153 auto set = descriptor_set->GetSet();
1154 LogObjectList objlist(set);
1155 objlist.add(buffer_view);
1156 return LogError(
1157 objlist, "UNASSIGNED-None-MismatchAtomicBufferFeature",
1158 "%s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
1159 " index %" PRIu32
1160 ", %s, format %s, doesn't "
1161 "contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT.",
1162 report_data->FormatHandle(set).c_str(), caller, binding, index,
1163 report_data->FormatHandle(buffer_view).c_str(),
1164 string_VkFormat(buffer_view_state->create_info.format));
1165 }
Chris Forbese92dd1d2019-01-21 15:58:57 -08001166 }
Jeff Bolz95176d02020-04-01 00:36:16 -05001167 } else if (descriptor_class == DescriptorClass::AccelerationStructure) {
1168 // Verify that acceleration structures are valid
1169 auto acc = static_cast<const AccelerationStructureDescriptor *>(descriptor)->GetAccelerationStructure();
1170 auto acc_node =
1171 static_cast<const AccelerationStructureDescriptor *>(descriptor)->GetAccelerationStructureState();
1172 if (!acc_node || acc_node->destroyed) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001173 auto set = descriptor_set->GetSet();
1174 return LogError(
locke-lunarg1328e8e2020-08-20 12:40:08 -06001175 set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -06001176 "%s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
1177 " index %" PRIu32 " is using acceleration structure %s that is invalid or has been destroyed.",
1178 report_data->FormatHandle(set).c_str(), caller, binding, index, report_data->FormatHandle(acc).c_str());
Jeff Bolz95176d02020-04-01 00:36:16 -05001179 } else {
1180 for (auto mem_binding : acc_node->GetBoundMemory()) {
1181 if (mem_binding->destroyed) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001182 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -06001183 return LogError(set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -06001184 "%s encountered the following validation error at %s time: Descriptor in "
1185 "binding #%" PRIu32 " index %" PRIu32
1186 " is using acceleration structure %s that references invalid memory %s.",
1187 report_data->FormatHandle(set).c_str(), caller, binding, index,
1188 report_data->FormatHandle(acc).c_str(),
1189 report_data->FormatHandle(mem_binding->mem).c_str());
Jeff Bolz95176d02020-04-01 00:36:16 -05001190 }
1191 }
1192 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001193 }
John Zulaufc93c4252019-06-25 09:19:49 -06001194 if (descriptor_class == DescriptorClass::ImageSampler || descriptor_class == DescriptorClass::PlainSampler) {
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001195 // Verify Sampler still valid
1196 VkSampler sampler;
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001197 const SAMPLER_STATE *sampler_state;
John Zulaufc93c4252019-06-25 09:19:49 -06001198 if (descriptor_class == DescriptorClass::ImageSampler) {
John Zulauf382e1912019-06-10 15:27:44 -06001199 sampler = static_cast<const ImageSamplerDescriptor *>(descriptor)->GetSampler();
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001200 sampler_state = static_cast<const ImageSamplerDescriptor *>(descriptor)->GetSamplerState();
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001201 } else {
John Zulauf382e1912019-06-10 15:27:44 -06001202 sampler = static_cast<const SamplerDescriptor *>(descriptor)->GetSampler();
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001203 sampler_state = static_cast<const SamplerDescriptor *>(descriptor)->GetSamplerState();
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001204 }
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001205 if (!sampler_state || sampler_state->destroyed) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001206 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -06001207 return LogError(set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -06001208 "%s encountered the following validation error at %s time: Descriptor in "
1209 "binding #%" PRIu32 " index %" PRIu32
1210 " is using sampler %s that is invalid or has been destroyed.",
1211 report_data->FormatHandle(set).c_str(), caller, binding, index,
1212 report_data->FormatHandle(sampler).c_str());
Lockea223c102019-04-05 00:38:24 -06001213 } else {
John Zulauf382e1912019-06-10 15:27:44 -06001214 if (sampler_state->samplerConversion && !descriptor->IsImmutableSampler()) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001215 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -06001216 return LogError(set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -06001217 "%s encountered the following validation error at %s time: sampler (%s) "
1218 "in the descriptor set (%s) caontains a YCBCR conversion (%s), then the sampler MUST "
1219 "also exist as an immutable sampler.",
1220 report_data->FormatHandle(set).c_str(), caller,
1221 report_data->FormatHandle(sampler).c_str(),
1222 report_data->FormatHandle(descriptor_set->GetSet()).c_str(),
1223 report_data->FormatHandle(sampler_state->samplerConversion).c_str());
Lockea223c102019-04-05 00:38:24 -06001224 }
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001225 }
Tony-LunarG7337b312020-04-15 16:40:25 -06001226 // TODO: Validate 04015 for DescriptorClass::PlainSampler
1227 if (descriptor_class == DescriptorClass::ImageSampler) {
Jeremy Kniagere6827432020-04-01 09:05:56 -06001228 const IMAGE_VIEW_STATE *image_view_state;
1229 image_view_state = static_cast<const ImageSamplerDescriptor *>(descriptor)->GetImageViewState();
Tony-LunarG9f0de792020-09-29 10:56:50 -06001230 if (image_view_state) {
1231 if ((sampler_state->createInfo.borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT ||
1232 sampler_state->createInfo.borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT) &&
1233 (sampler_state->customCreateInfo.format == VK_FORMAT_UNDEFINED)) {
1234 if (image_view_state->create_info.format == VK_FORMAT_B4G4R4A4_UNORM_PACK16 ||
1235 image_view_state->create_info.format == VK_FORMAT_B5G6R5_UNORM_PACK16 ||
1236 image_view_state->create_info.format == VK_FORMAT_B5G5R5A1_UNORM_PACK16) {
1237 auto set = descriptor_set->GetSet();
1238 LogObjectList objlist(set);
1239 objlist.add(sampler);
1240 objlist.add(image_view_state->image_view);
1241 return LogError(objlist, "VUID-VkSamplerCustomBorderColorCreateInfoEXT-format-04015",
1242 "%s encountered the following validation error at %s time: Sampler %s in "
1243 "binding #%" PRIu32 " index %" PRIu32
1244 " has a custom border color with format = VK_FORMAT_UNDEFINED and is used to "
1245 "sample an image view %s with format %s",
1246 report_data->FormatHandle(set).c_str(), caller,
1247 report_data->FormatHandle(sampler).c_str(), binding, index,
1248 report_data->FormatHandle(image_view_state->image_view).c_str(),
1249 string_VkFormat(image_view_state->create_info.format));
1250 }
1251 }
1252 VkFilter sampler_mag_filter = sampler_state->createInfo.magFilter;
1253 VkFilter sampler_min_filter = sampler_state->createInfo.minFilter;
Shannon McPhersonf673b4e2020-10-28 18:26:47 -06001254 VkBool32 sampler_compare_enable = sampler_state->createInfo.compareEnable;
Tony-LunarG9f0de792020-09-29 10:56:50 -06001255 if ((sampler_mag_filter == VK_FILTER_LINEAR || sampler_min_filter == VK_FILTER_LINEAR) &&
Shannon McPhersonf673b4e2020-10-28 18:26:47 -06001256 (sampler_compare_enable == VK_FALSE) &&
Tony-LunarG9f0de792020-09-29 10:56:50 -06001257 !(image_view_state->format_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
Tony-LunarG7337b312020-04-15 16:40:25 -06001258 auto set = descriptor_set->GetSet();
1259 LogObjectList objlist(set);
1260 objlist.add(sampler);
1261 objlist.add(image_view_state->image_view);
Tony-LunarG9f0de792020-09-29 10:56:50 -06001262 return LogError(objlist, vuids.linear_sampler,
1263 "sampler (%s) in descriptor set (%s) "
1264 "is set to use VK_FILTER_LINEAR, then image view's (%s"
1265 ") format (%s) MUST "
1266 "contain VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT in its format features.",
1267 report_data->FormatHandle(sampler).c_str(), report_data->FormatHandle(set).c_str(),
Tony-LunarG02982142020-06-22 13:58:32 -06001268 report_data->FormatHandle(image_view_state->image_view).c_str(),
1269 string_VkFormat(image_view_state->create_info.format));
Tony-LunarG7337b312020-04-15 16:40:25 -06001270 }
Tony-LunarG9f0de792020-09-29 10:56:50 -06001271 if ((sampler_mag_filter == VK_FILTER_CUBIC_EXT || sampler_min_filter == VK_FILTER_CUBIC_EXT) &&
1272 !(image_view_state->format_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) {
1273 auto set = descriptor_set->GetSet();
1274 LogObjectList objlist(set);
1275 objlist.add(sampler);
1276 objlist.add(image_view_state->image_view);
1277 return LogError(
1278 objlist, vuids.cubic_sampler,
1279 "sampler (%s) in descriptor set (%s) "
1280 "is set to use VK_FILTER_CUBIC_EXT, then image view's (%s"
1281 ") format (%s) MUST "
1282 "contain VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT in its format features.",
1283 report_data->FormatHandle(sampler).c_str(), report_data->FormatHandle(set).c_str(),
1284 report_data->FormatHandle(image_view_state->image_view).c_str(),
1285 string_VkFormat(image_view_state->create_info.format));
1286 }
Jeremy Kniager95ffacb2020-06-19 11:32:05 -06001287
Tony-LunarG9f0de792020-09-29 10:56:50 -06001288 const IMAGE_STATE *image_state;
1289 image_state = GetImageState(image_view_state->create_info.image);
1290 if ((image_state->createInfo.flags & VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV) &&
1291 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ||
1292 sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ||
1293 sampler_state->createInfo.addressModeW != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)) {
1294 std::string address_mode_letter =
1295 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1296 ? "U"
1297 : (sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE) ? "V"
1298 : "W";
1299 VkSamplerAddressMode address_mode =
1300 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1301 ? sampler_state->createInfo.addressModeU
1302 : (sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1303 ? sampler_state->createInfo.addressModeV
1304 : sampler_state->createInfo.addressModeW;
1305 auto set = descriptor_set->GetSet();
1306 LogObjectList objlist(set);
1307 objlist.add(sampler);
1308 objlist.add(image_state->image);
1309 objlist.add(image_view_state->image_view);
1310 return LogError(
1311 objlist, vuids.corner_sampled_address_mode,
1312 "image (%s) in image view (%s) in descriptor set (%s) is created with flag "
1313 "VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV and can only be sampled using "
1314 "VK_SAMPLER_ADDRESS_MODE_CLAMP_EDGE, but sampler (%s) has createInfo.addressMode%s set to %s.",
1315 report_data->FormatHandle(image_state->image).c_str(),
1316 report_data->FormatHandle(image_view_state->image_view).c_str(),
1317 report_data->FormatHandle(set).c_str(), report_data->FormatHandle(sampler).c_str(),
1318 address_mode_letter.c_str(), string_VkSamplerAddressMode(address_mode));
1319 }
Jeremy Kniager95ffacb2020-06-19 11:32:05 -06001320 }
Tony-LunarG7337b312020-04-15 16:40:25 -06001321 }
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001322 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001323 }
1324 }
1325 }
Tony-LunarGace473a2020-05-06 12:48:04 -06001326 return false;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001327}
Chris Forbes57989132016-07-26 17:06:10 +12001328
Tobin Ehlis9906d9d2016-05-17 14:23:46 -06001329// Set is being deleted or updates so invalidate all bound cmd buffers
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001330void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers(ValidationStateTracker *state_data) {
1331 state_data->InvalidateCommandBuffers(cb_bindings, VulkanTypedHandle(set_, kVulkanObjectTypeDescriptorSet), /*unlink*/ false);
Tobin Ehlis9906d9d2016-05-17 14:23:46 -06001332}
John Zulauf1d27e0a2018-11-05 10:12:48 -07001333
1334// Loop through the write updates to do for a push descriptor set, ignoring dstSet
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001335void cvdescriptorset::DescriptorSet::PerformPushDescriptorsUpdate(ValidationStateTracker *dev_data, uint32_t write_count,
1336 const VkWriteDescriptorSet *p_wds) {
John Zulauf1d27e0a2018-11-05 10:12:48 -07001337 assert(IsPushDescriptor());
1338 for (uint32_t i = 0; i < write_count; i++) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001339 PerformWriteUpdate(dev_data, &p_wds[i]);
John Zulauf1d27e0a2018-11-05 10:12:48 -07001340 }
Jason Macnak83cfd582019-07-31 10:14:24 -07001341
1342 push_descriptor_set_writes.clear();
1343 push_descriptor_set_writes.reserve(static_cast<std::size_t>(write_count));
1344 for (uint32_t i = 0; i < write_count; i++) {
1345 push_descriptor_set_writes.push_back(safe_VkWriteDescriptorSet(&p_wds[i]));
1346 }
John Zulauf1d27e0a2018-11-05 10:12:48 -07001347}
1348
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001349// Perform write update in given update struct
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001350void cvdescriptorset::DescriptorSet::PerformWriteUpdate(ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update) {
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001351 // Perform update on a per-binding basis as consecutive updates roll over to next binding
1352 auto descriptors_remaining = update->descriptorCount;
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001353 auto offset = update->dstArrayElement;
locke-lunarge46b7782019-09-10 01:44:20 -06001354 auto orig_binding = DescriptorSetLayout::ConstBindingIterator(p_layout_.get(), update->dstBinding);
1355 auto current_binding = orig_binding;
1356
Tobin Ehlise16805c2017-08-09 09:10:37 -06001357 uint32_t update_index = 0;
locke-lunarge46b7782019-09-10 01:44:20 -06001358 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
1359 while (descriptors_remaining && orig_binding.IsConsistent(current_binding)) {
1360 const auto &index_range = current_binding.GetGlobalIndexRange();
1361 auto global_idx = index_range.start + offset;
1362 // global_idx is which descriptor is needed to update. If global_idx > index_range.end, it means the descriptor isn't in
1363 // this binding, maybe in next binding.
1364 if (global_idx >= index_range.end) {
1365 offset -= current_binding.GetDescriptorCount();
1366 ++current_binding;
1367 continue;
1368 }
1369
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001370 // Loop over the updates for a single binding at a time
locke-lunarge46b7782019-09-10 01:44:20 -06001371 uint32_t update_count = std::min(descriptors_remaining, current_binding.GetDescriptorCount() - offset);
Tobin Ehlise16805c2017-08-09 09:10:37 -06001372 for (uint32_t di = 0; di < update_count; ++di, ++update_index) {
John Zulaufd2c3dae2019-12-12 11:02:17 -07001373 descriptors_[global_idx + di]->WriteUpdate(state_data_, update, update_index);
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001374 }
1375 // Roll over to next binding in case of consecutive update
1376 descriptors_remaining -= update_count;
locke-lunarge46b7782019-09-10 01:44:20 -06001377 if (descriptors_remaining) {
1378 // Starting offset is beyond the current binding. Check consistency, update counters and advance to the next binding,
1379 // looking for the start point. All bindings (even those skipped) must be consistent with the update and with the
1380 // original binding.
1381 offset = 0;
1382 ++current_binding;
1383 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001384 }
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05001385 if (update->descriptorCount) {
1386 some_update_ = true;
1387 change_count_++;
1388 }
Tobin Ehlis56a30942016-05-19 08:00:00 -06001389
Jeff Bolzfdf96072018-04-10 14:32:18 -05001390 if (!(p_layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
1391 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001392 InvalidateBoundCmdBuffers(dev_data);
Jeff Bolzfdf96072018-04-10 14:32:18 -05001393 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001394}
Tobin Ehlis300888c2016-05-18 13:43:26 -06001395// Validate Copy update
John Zulaufc93c4252019-06-25 09:19:49 -06001396bool CoreChecks::ValidateCopyUpdate(const VkCopyDescriptorSet *update, const DescriptorSet *dst_set, const DescriptorSet *src_set,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05001397 const char *func_name, std::string *error_code, std::string *error_msg) const {
Jeff Bolz6aad1742019-10-16 11:10:09 -05001398 auto dst_layout = dst_set->GetLayout().get();
1399 auto src_layout = src_set->GetLayout().get();
John Zulaufd9435c32019-06-05 15:55:36 -06001400
John Zulauf5dfd45c2018-01-17 11:06:34 -07001401 // Verify dst layout still valid
Jeff Bolz6ae39612019-10-11 20:57:36 -05001402 if (dst_layout->destroyed) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001403 *error_code = "VUID-VkCopyDescriptorSet-dstSet-parameter";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06001404 std::ostringstream str;
1405 str << "Cannot call " << func_name << " to perform copy update on dstSet " << report_data->FormatHandle(dst_set->GetSet())
1406 << " created with destroyed " << report_data->FormatHandle(dst_layout->GetDescriptorSetLayout()) << ".";
1407 *error_msg = str.str();
John Zulauf5dfd45c2018-01-17 11:06:34 -07001408 return false;
1409 }
1410
1411 // Verify src layout still valid
Jeff Bolz6ae39612019-10-11 20:57:36 -05001412 if (src_layout->destroyed) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001413 *error_code = "VUID-VkCopyDescriptorSet-srcSet-parameter";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06001414 std::ostringstream str;
1415 str << "Cannot call " << func_name << " to perform copy update on dstSet " << report_data->FormatHandle(dst_set->GetSet())
1416 << " from srcSet " << report_data->FormatHandle(src_set->GetSet()) << " created with destroyed "
1417 << report_data->FormatHandle(src_layout->GetDescriptorSetLayout()) << ".";
1418 *error_msg = str.str();
John Zulauf5dfd45c2018-01-17 11:06:34 -07001419 return false;
1420 }
1421
John Zulaufd9435c32019-06-05 15:55:36 -06001422 if (!dst_layout->HasBinding(update->dstBinding)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001423 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-00347";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001424 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001425 error_str << "DescriptorSet " << report_data->FormatHandle(dst_set->GetSet())
1426 << " does not have copy update dest binding of " << update->dstBinding;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001427 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001428 return false;
1429 }
1430 if (!src_set->HasBinding(update->srcBinding)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001431 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-00345";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001432 std::stringstream error_str;
sourav parmarf4a78252020-04-10 13:04:21 -07001433 error_str << "DescriptorSet " << report_data->FormatHandle(src_set->GetSet())
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001434 << " does not have copy update src binding of " << update->srcBinding;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001435 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001436 return false;
1437 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001438 // Verify idle ds
John Zulaufd9435c32019-06-05 15:55:36 -06001439 if (dst_set->in_use.load() &&
1440 !(dst_layout->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Jeff Bolzfdf96072018-04-10 14:32:18 -05001441 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) {
1442 // TODO : Re-using Free Idle error code, need copy update idle error code
Dave Houlton00c154e2018-05-24 13:20:50 -06001443 *error_code = "VUID-vkFreeDescriptorSets-pDescriptorSets-00309";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001444 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001445 error_str << "Cannot call " << func_name << " to perform copy update on descriptor set "
1446 << report_data->FormatHandle(dst_set->GetSet()) << " that is in use by a command buffer";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001447 *error_msg = error_str.str();
1448 return false;
1449 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001450 // src & dst set bindings are valid
1451 // Check bounds of src & dst
John Zulaufc483f442017-12-15 14:02:06 -07001452 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001453 if ((src_start_idx + update->descriptorCount) > src_set->GetTotalDescriptorCount()) {
1454 // SRC update out of bounds
Dave Houlton00c154e2018-05-24 13:20:50 -06001455 *error_code = "VUID-VkCopyDescriptorSet-srcArrayElement-00346";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001456 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001457 error_str << "Attempting copy update from descriptorSet " << report_data->FormatHandle(update->srcSet) << " binding#"
1458 << update->srcBinding << " with offset index of "
1459 << src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start << " plus update array offset of "
1460 << update->srcArrayElement << " and update of " << update->descriptorCount
Tobin Ehlis1d81edd2016-11-21 09:50:49 -07001461 << " descriptors oversteps total number of descriptors in set: " << src_set->GetTotalDescriptorCount();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001462 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001463 return false;
1464 }
John Zulaufd9435c32019-06-05 15:55:36 -06001465 auto dst_start_idx = dst_layout->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
1466 if ((dst_start_idx + update->descriptorCount) > dst_layout->GetTotalDescriptorCount()) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001467 // DST update out of bounds
Dave Houlton00c154e2018-05-24 13:20:50 -06001468 *error_code = "VUID-VkCopyDescriptorSet-dstArrayElement-00348";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001469 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001470 error_str << "Attempting copy update to descriptorSet " << report_data->FormatHandle(dst_set->GetSet()) << " binding#"
1471 << update->dstBinding << " with offset index of "
1472 << dst_layout->GetGlobalIndexRangeFromBinding(update->dstBinding).start << " plus update array offset of "
1473 << update->dstArrayElement << " and update of " << update->descriptorCount
John Zulaufd9435c32019-06-05 15:55:36 -06001474 << " descriptors oversteps total number of descriptors in set: " << dst_layout->GetTotalDescriptorCount();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001475 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001476 return false;
1477 }
1478 // Check that types match
Shannon McPhersonafe55122020-05-25 16:20:19 -06001479 // TODO : Base default error case going from here is "VUID-VkAcquireNextImageInfoKHR-semaphore-parameter" 2ba which covers all
Dave Houltond8ed0212018-05-16 17:18:24 -06001480 // consistency issues, need more fine-grained error codes
Dave Houlton00c154e2018-05-24 13:20:50 -06001481 *error_code = "VUID-VkCopyDescriptorSet-srcSet-00349";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001482 auto src_type = src_set->GetTypeFromBinding(update->srcBinding);
John Zulaufd9435c32019-06-05 15:55:36 -06001483 auto dst_type = dst_layout->GetTypeFromBinding(update->dstBinding);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001484 if (src_type != dst_type) {
sourav parmarf4a78252020-04-10 13:04:21 -07001485 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02632";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001486 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001487 error_str << "Attempting copy update to descriptorSet " << report_data->FormatHandle(dst_set->GetSet()) << " binding #"
1488 << update->dstBinding << " with type " << string_VkDescriptorType(dst_type) << " from descriptorSet "
1489 << report_data->FormatHandle(src_set->GetSet()) << " binding #" << update->srcBinding << " with type "
1490 << string_VkDescriptorType(src_type) << ". Types do not match";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001491 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001492 return false;
1493 }
1494 // Verify consistency of src & dst bindings if update crosses binding boundaries
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001495 if ((!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(src_layout, update->srcBinding),
John Zulauf4a015c92019-06-04 09:50:05 -06001496 update->srcArrayElement, update->descriptorCount, "copy update from", src_set->GetSet(),
1497 error_msg)) ||
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001498 (!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(dst_layout, update->dstBinding),
John Zulaufd9435c32019-06-05 15:55:36 -06001499 update->dstArrayElement, update->descriptorCount, "copy update to", dst_set->GetSet(),
1500 error_msg))) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001501 return false;
1502 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001503
John Zulaufd9435c32019-06-05 15:55:36 -06001504 if ((src_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT) &&
1505 !(dst_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001506 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01918";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001507 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001508 error_str << "If pname:srcSet's (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001509 << ") layout was created with the "
1510 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag "
1511 "set, then pname:dstSet's ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001512 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001513 << ") layout must: also have been created with the "
1514 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set";
1515 *error_msg = error_str.str();
1516 return false;
1517 }
1518
John Zulaufd9435c32019-06-05 15:55:36 -06001519 if (!(src_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT) &&
1520 (dst_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001521 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01919";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001522 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001523 error_str << "If pname:srcSet's (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001524 << ") layout was created without the "
1525 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag "
1526 "set, then pname:dstSet's ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001527 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001528 << ") layout must: also have been created without the "
1529 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set";
1530 *error_msg = error_str.str();
1531 return false;
1532 }
1533
1534 if ((src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT) &&
John Zulaufd9435c32019-06-05 15:55:36 -06001535 !(dst_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001536 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01920";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001537 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001538 error_str << "If the descriptor pool from which pname:srcSet (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001539 << ") was allocated was created "
1540 "with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag "
1541 "set, then the descriptor pool from which pname:dstSet ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001542 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001543 << ") was allocated must: "
1544 "also have been created with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set";
1545 *error_msg = error_str.str();
1546 return false;
1547 }
1548
1549 if (!(src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT) &&
John Zulaufd9435c32019-06-05 15:55:36 -06001550 (dst_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001551 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01921";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001552 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001553 error_str << "If the descriptor pool from which pname:srcSet (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001554 << ") was allocated was created "
1555 "without the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag "
1556 "set, then the descriptor pool from which pname:dstSet ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001557 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001558 << ") was allocated must: "
1559 "also have been created without the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set";
1560 *error_msg = error_str.str();
1561 return false;
1562 }
1563
Jeff Bolze54ae892018-09-08 12:16:29 -05001564 if (src_type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
1565 if ((update->srcArrayElement % 4) != 0) {
1566 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-02223";
1567 std::stringstream error_str;
1568 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1569 << "srcArrayElement " << update->srcArrayElement << " not a multiple of 4";
1570 *error_msg = error_str.str();
1571 return false;
1572 }
1573 if ((update->dstArrayElement % 4) != 0) {
1574 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02224";
1575 std::stringstream error_str;
1576 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1577 << "dstArrayElement " << update->dstArrayElement << " not a multiple of 4";
1578 *error_msg = error_str.str();
1579 return false;
1580 }
1581 if ((update->descriptorCount % 4) != 0) {
1582 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-02225";
1583 std::stringstream error_str;
1584 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1585 << "descriptorCount " << update->descriptorCount << " not a multiple of 4";
1586 *error_msg = error_str.str();
1587 return false;
1588 }
1589 }
1590
Tobin Ehlisd41e7b62016-05-19 07:56:18 -06001591 // Update parameters all look good and descriptor updated so verify update contents
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07001592 if (!VerifyCopyUpdateContents(update, src_set, src_type, src_start_idx, dst_set, dst_type, dst_start_idx, func_name, error_code,
1593 error_msg))
1594 return false;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001595
1596 // All checks passed so update is good
1597 return true;
1598}
1599// Perform Copy update
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001600void cvdescriptorset::DescriptorSet::PerformCopyUpdate(ValidationStateTracker *dev_data, const VkCopyDescriptorSet *update,
1601 const DescriptorSet *src_set) {
John Zulaufc483f442017-12-15 14:02:06 -07001602 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
1603 auto dst_start_idx = p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001604 // Update parameters all look good so perform update
1605 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Józef Kucia5297e372017-10-13 22:31:34 +02001606 auto src = src_set->descriptors_[src_start_idx + di].get();
1607 auto dst = descriptors_[dst_start_idx + di].get();
1608 if (src->updated) {
John Zulaufd2c3dae2019-12-12 11:02:17 -07001609 dst->CopyUpdate(state_data_, src);
Józef Kucia5297e372017-10-13 22:31:34 +02001610 some_update_ = true;
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05001611 change_count_++;
Józef Kucia5297e372017-10-13 22:31:34 +02001612 } else {
1613 dst->updated = false;
1614 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001615 }
Tobin Ehlis56a30942016-05-19 08:00:00 -06001616
Jeff Bolzfdf96072018-04-10 14:32:18 -05001617 if (!(p_layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
1618 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001619 InvalidateBoundCmdBuffers(dev_data);
Jeff Bolzfdf96072018-04-10 14:32:18 -05001620 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001621}
Tobin Ehlis56a30942016-05-19 08:00:00 -06001622
John Zulauf6f3d2bd2018-10-29 17:08:42 -06001623// Update the drawing state for the affected descriptors.
1624// Set cb_node to this set and this set to cb_node.
1625// Add the bindings of the descriptor
1626// Set the layout based on the current descriptor layout (will mask subsequent layer mismatch errors)
1627// TODO: Modify the UpdateDrawState virtural functions to *only* set initial layout and not change layouts
Tobin Ehlisf9519102016-08-17 09:49:13 -06001628// Prereq: This should be called for a set that has been confirmed to be active for the given cb_node, meaning it's going
1629// to be used in a draw by the given cb_node
Jeremy Kniagere6827432020-04-01 09:05:56 -06001630void cvdescriptorset::DescriptorSet::UpdateDrawState(ValidationStateTracker *device_data, CMD_BUFFER_STATE *cb_node,
1631 CMD_TYPE cmd_type, const PIPELINE_STATE *pipe,
Karl Schultz7090a052020-11-10 08:54:21 -07001632 const BindingReqMap &binding_req_map, const char *function) {
Tony-LunarG77822802020-05-28 16:35:46 -06001633 if (!device_data->disabled[command_buffer_state] && !IsPushDescriptor()) {
Jeff Bolzafa429a2019-08-14 09:59:22 -05001634 // bind cb to this descriptor set
1635 // Add bindings for descriptor set, the set's pool, and individual objects in the set
Jeff Bolzadbfa852019-10-04 13:53:30 -05001636 if (device_data->AddCommandBufferBinding(cb_bindings, VulkanTypedHandle(set_, kVulkanObjectTypeDescriptorSet, this),
1637 cb_node)) {
1638 device_data->AddCommandBufferBinding(pool_state_->cb_bindings,
1639 VulkanTypedHandle(pool_state_->pool, kVulkanObjectTypeDescriptorPool, pool_state_),
1640 cb_node);
Jeff Bolzafa429a2019-08-14 09:59:22 -05001641 }
1642 }
Jeff Bolze18e7242019-08-12 20:55:22 -05001643
1644 // Descriptor UpdateDrawState functions do two things - associate resources to the command buffer,
1645 // and call image layout validation callbacks. If both are disabled, skip the entire loop.
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -06001646 if (device_data->disabled[command_buffer_state] && device_data->disabled[image_layout_validation]) {
Jeff Bolze18e7242019-08-12 20:55:22 -05001647 return;
1648 }
1649
Tobin Ehlisf9519102016-08-17 09:49:13 -06001650 // For the active slots, use set# to look up descriptorSet from boundDescriptorSets, and bind all of that descriptor set's
1651 // resources
locke-lunarg540b2252020-08-03 13:23:36 -06001652 CMD_BUFFER_STATE::CmdDrawDispatchInfo cmd_info = {};
locke-lunarg654a9052020-10-13 16:28:42 -06001653 if (pipe->graphicsPipelineCI.sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO) {
1654 cmd_info.bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
1655 } else if (pipe->computePipelineCI.sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO) {
1656 cmd_info.bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
1657 } else if (pipe->raytracingPipelineCI.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR ||
1658 pipe->raytracingPipelineCI.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV) {
1659 cmd_info.bind_point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
1660 }
locke-lunarg540b2252020-08-03 13:23:36 -06001661
Tobin Ehlis022528b2016-12-29 12:22:32 -07001662 for (auto binding_req_pair : binding_req_map) {
locke-gb3ce08f2019-09-30 12:30:56 -06001663 auto index = p_layout_->GetIndexFromBinding(binding_req_pair.first);
1664
Tony-LunarG62c5dba2018-12-20 14:27:23 -07001665 // We aren't validating descriptors created with PARTIALLY_BOUND or UPDATE_AFTER_BIND, so don't record state
locke-gb3ce08f2019-09-30 12:30:56 -06001666 auto flags = p_layout_->GetDescriptorBindingFlagsFromIndex(index);
1667 if (flags & (VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT)) {
locke-lunargdec975d2019-12-18 16:15:25 -07001668 if (!(flags & VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT)) {
locke-lunarg36045992020-08-20 16:54:37 -06001669 cmd_info.binding_infos.emplace_back(binding_req_pair);
locke-gb3ce08f2019-09-30 12:30:56 -06001670 }
Tony-LunarG62c5dba2018-12-20 14:27:23 -07001671 continue;
1672 }
locke-gb3ce08f2019-09-30 12:30:56 -06001673 auto range = p_layout_->GetGlobalIndexRangeFromIndex(index);
John Zulaufc483f442017-12-15 14:02:06 -07001674 for (uint32_t i = range.start; i < range.end; ++i) {
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07001675 descriptors_[i]->UpdateDrawState(device_data, cb_node);
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06001676 }
1677 }
locke-lunarg540b2252020-08-03 13:23:36 -06001678
1679 if (cmd_info.binding_infos.size() > 0) {
1680 cmd_info.cmd_type = cmd_type;
1681 cmd_info.function = function;
1682 if (cb_node->activeFramebuffer) {
1683 cmd_info.framebuffer = cb_node->activeFramebuffer->framebuffer;
locke-lunargcac25742020-08-25 16:15:40 -06001684 cmd_info.attachment_views = cb_node->activeFramebuffer->GetUsedAttachments(
1685 *cb_node->activeRenderPass->createInfo.pSubpasses, cb_node->imagelessFramebufferAttachments);
locke-lunarg540b2252020-08-03 13:23:36 -06001686 }
1687 cb_node->validate_descriptorsets_in_queuesubmit[set_].emplace_back(cmd_info);
1688 }
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06001689}
1690
John Zulauffbf3c202019-07-17 14:57:14 -06001691void cvdescriptorset::DescriptorSet::FilterOneBindingReq(const BindingReqMap::value_type &binding_req_pair, BindingReqMap *out_req,
1692 const TrackedBindings &bindings, uint32_t limit) {
1693 if (bindings.size() < limit) {
1694 const auto it = bindings.find(binding_req_pair.first);
1695 if (it == bindings.cend()) out_req->emplace(binding_req_pair);
John Zulauf48a6a702017-12-22 17:14:54 -07001696 }
1697}
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06001698
John Zulauffbf3c202019-07-17 14:57:14 -06001699void cvdescriptorset::DescriptorSet::FilterBindingReqs(const CMD_BUFFER_STATE &cb_state, const PIPELINE_STATE &pipeline,
1700 const BindingReqMap &in_req, BindingReqMap *out_req) const {
1701 // For const cleanliness we have to find in the maps...
1702 const auto validated_it = cached_validation_.find(&cb_state);
1703 if (validated_it == cached_validation_.cend()) {
1704 // We have nothing validated, copy in to out
1705 for (const auto &binding_req_pair : in_req) {
1706 out_req->emplace(binding_req_pair);
John Zulauf48a6a702017-12-22 17:14:54 -07001707 }
John Zulauffbf3c202019-07-17 14:57:14 -06001708 return;
John Zulauf48a6a702017-12-22 17:14:54 -07001709 }
John Zulauffbf3c202019-07-17 14:57:14 -06001710 const auto &validated = validated_it->second;
John Zulauf48a6a702017-12-22 17:14:54 -07001711
John Zulauffbf3c202019-07-17 14:57:14 -06001712 const auto image_sample_version_it = validated.image_samplers.find(&pipeline);
1713 const VersionedBindings *image_sample_version = nullptr;
1714 if (image_sample_version_it != validated.image_samplers.cend()) {
1715 image_sample_version = &(image_sample_version_it->second);
1716 }
1717 const auto &dynamic_buffers = validated.dynamic_buffers;
1718 const auto &non_dynamic_buffers = validated.non_dynamic_buffers;
John Zulauf48a6a702017-12-22 17:14:54 -07001719 const auto &stats = p_layout_->GetBindingTypeStats();
1720 for (const auto &binding_req_pair : in_req) {
1721 auto binding = binding_req_pair.first;
1722 VkDescriptorSetLayoutBinding const *layout_binding = p_layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
1723 if (!layout_binding) {
1724 continue;
1725 }
1726 // Caching criteria differs per type.
1727 // If image_layout have changed , the image descriptors need to be validated against them.
1728 if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
1729 (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
John Zulauffbf3c202019-07-17 14:57:14 -06001730 FilterOneBindingReq(binding_req_pair, out_req, dynamic_buffers, stats.dynamic_buffer_count);
John Zulauf48a6a702017-12-22 17:14:54 -07001731 } else if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
1732 (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)) {
John Zulauffbf3c202019-07-17 14:57:14 -06001733 FilterOneBindingReq(binding_req_pair, out_req, non_dynamic_buffers, stats.non_dynamic_buffer_count);
John Zulauf48a6a702017-12-22 17:14:54 -07001734 } else {
1735 // This is rather crude, as the changed layouts may not impact the bound descriptors,
1736 // but the simple "versioning" is a simple "dirt" test.
John Zulauffbf3c202019-07-17 14:57:14 -06001737 bool stale = true;
1738 if (image_sample_version) {
1739 const auto version_it = image_sample_version->find(binding);
1740 if (version_it != image_sample_version->cend() && (version_it->second == cb_state.image_layout_change_count)) {
1741 stale = false;
1742 }
1743 }
1744 if (stale) {
John Zulauf48a6a702017-12-22 17:14:54 -07001745 out_req->emplace(binding_req_pair);
1746 }
1747 }
1748 }
1749}
Tobin Ehlis9252c2b2016-07-21 14:40:22 -06001750
John Zulauffbf3c202019-07-17 14:57:14 -06001751void cvdescriptorset::DescriptorSet::UpdateValidationCache(const CMD_BUFFER_STATE &cb_state, const PIPELINE_STATE &pipeline,
1752 const BindingReqMap &updated_bindings) {
1753 // For const cleanliness we have to find in the maps...
1754 auto &validated = cached_validation_[&cb_state];
1755
1756 auto &image_sample_version = validated.image_samplers[&pipeline];
1757 auto &dynamic_buffers = validated.dynamic_buffers;
1758 auto &non_dynamic_buffers = validated.non_dynamic_buffers;
1759 for (const auto &binding_req_pair : updated_bindings) {
1760 auto binding = binding_req_pair.first;
1761 VkDescriptorSetLayoutBinding const *layout_binding = p_layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
1762 if (!layout_binding) {
1763 continue;
1764 }
1765 // Caching criteria differs per type.
1766 if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
1767 (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
1768 dynamic_buffers.emplace(binding);
1769 } else if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
1770 (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)) {
1771 non_dynamic_buffers.emplace(binding);
1772 } else {
1773 // Save the layout change version...
1774 image_sample_version[binding] = cb_state.image_layout_change_count;
1775 }
1776 }
1777}
1778
John Zulaufd2c3dae2019-12-12 11:02:17 -07001779cvdescriptorset::SamplerDescriptor::SamplerDescriptor(const ValidationStateTracker *dev_data, const VkSampler *immut)
Karl Schultz76d16a42020-11-11 05:05:33 -07001780 : immutable_(false) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001781 updated = false;
1782 descriptor_class = PlainSampler;
1783 if (immut) {
Karl Schultz76d16a42020-11-11 05:05:33 -07001784 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(*immut);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001785 immutable_ = true;
1786 updated = true;
1787 }
1788}
Tobin Ehlise2f80292016-06-02 10:08:53 -06001789// Validate given sampler. Currently this only checks to make sure it exists in the samplerMap
John Zulaufc93c4252019-06-25 09:19:49 -06001790bool CoreChecks::ValidateSampler(const VkSampler sampler) const { return (GetSamplerState(sampler) != nullptr); }
Tobin Ehlis56a30942016-05-19 08:00:00 -06001791
John Zulaufc93c4252019-06-25 09:19:49 -06001792bool CoreChecks::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type,
John Zulaufbd9b3412019-08-22 17:16:11 -06001793 const char *func_name, std::string *error_code, std::string *error_msg) const {
John Zulaufc93c4252019-06-25 09:19:49 -06001794 auto iv_state = GetImageViewState(image_view);
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001795 assert(iv_state);
1796
Tobin Ehlis81280962016-07-20 14:04:20 -06001797 // 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 -06001798 // Validate that imageLayout is compatible with aspect_mask and image format
1799 // and validate that image usage bits are correct for given usage
Tobin Ehlis8b26a382016-09-14 08:02:49 -06001800 VkImageAspectFlags aspect_mask = iv_state->create_info.subresourceRange.aspectMask;
1801 VkImage image = iv_state->create_info.image;
Tobin Ehlis1809f912016-05-25 09:24:36 -06001802 VkFormat format = VK_FORMAT_MAX_ENUM;
1803 VkImageUsageFlags usage = 0;
John Zulaufc93c4252019-06-25 09:19:49 -06001804 auto image_node = GetImageState(image);
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001805 assert(image_node);
Chris Forbes67757ff2017-07-21 13:59:01 -07001806
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001807 format = image_node->createInfo.format;
1808 usage = image_node->createInfo.usage;
Ricardo Garcia3f5984c2020-04-09 10:56:34 +02001809 const auto stencil_usage_info = lvl_find_in_chain<VkImageStencilUsageCreateInfo>(image_node->createInfo.pNext);
1810 if (stencil_usage_info) {
1811 usage |= stencil_usage_info->stencilUsage;
1812 }
Mark Lobodzinski03d00062020-06-15 14:35:45 -06001813
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001814 // Validate that memory is bound to image
Mark Lobodzinski03d00062020-06-15 14:35:45 -06001815 if (ValidateMemoryIsBoundToImage(image_node, func_name, "UNASSIGNED-CoreValidation-BoundResourceFreedMemoryAccess")) {
1816 *error_code = "UNASSIGNED-CoreValidation-BoundResourceFreedMemoryAccess";
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001817 *error_msg = "No memory bound to image.";
Tobin Ehlis1809f912016-05-25 09:24:36 -06001818 return false;
1819 }
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001820
1821 // KHR_maintenance1 allows rendering into 2D or 2DArray views which slice a 3D image,
1822 // but not binding them to descriptor sets.
1823 if (image_node->createInfo.imageType == VK_IMAGE_TYPE_3D && (iv_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_2D ||
1824 iv_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)) {
1825 *error_code = "VUID-VkDescriptorImageInfo-imageView-00343";
1826 *error_msg = "ImageView must not be a 2D or 2DArray view of a 3D image";
1827 return false;
1828 }
1829
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001830 // TODO : The various image aspect and format checks here are based on general spec language in 11.5 Image Views section under
1831 // vkCreateImageView(). What's the best way to create unique id for these cases?
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001832 *error_code = "UNASSIGNED-CoreValidation-DrawState-InvalidImageView";
Dave Houlton1d2022c2017-03-29 11:43:58 -06001833 bool ds = FormatIsDepthOrStencil(format);
Tobin Ehlis1809f912016-05-25 09:24:36 -06001834 switch (image_layout) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001835 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
1836 // Only Color bit must be set
1837 if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
Tobin Ehlis1809f912016-05-25 09:24:36 -06001838 std::stringstream error_str;
Dave Houltona9df0ce2018-02-07 10:51:23 -07001839 error_str
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001840 << "ImageView (" << report_data->FormatHandle(image_view)
Dave Houltona9df0ce2018-02-07 10:51:23 -07001841 << ") 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 -06001842 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -06001843 return false;
1844 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001845 // format must NOT be DS
1846 if (ds) {
1847 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001848 error_str << "ImageView (" << report_data->FormatHandle(image_view)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001849 << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but the image format is "
1850 << string_VkFormat(format) << " which is not a color format.";
1851 *error_msg = error_str.str();
1852 return false;
1853 }
1854 break;
1855 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
1856 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
1857 // Depth or stencil bit must be set, but both must NOT be set
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06001858 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
1859 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
1860 // both must NOT be set
1861 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001862 error_str << "ImageView (" << report_data->FormatHandle(image_view)
Mark Lobodzinski6b042922019-06-21 14:46:42 -06001863 << ") has both STENCIL and DEPTH aspects set";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001864 *error_msg = error_str.str();
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06001865 return false;
1866 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001867 } else if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
1868 // Neither were set
1869 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001870 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06001871 << string_VkImageLayout(image_layout) << " but does not have STENCIL or DEPTH aspects set";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001872 *error_msg = error_str.str();
1873 return false;
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06001874 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001875 // format must be DS
1876 if (!ds) {
1877 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001878 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06001879 << string_VkImageLayout(image_layout) << " but the image format is " << string_VkFormat(format)
1880 << " which is not a depth/stencil format.";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001881 *error_msg = error_str.str();
1882 return false;
1883 }
1884 break;
1885 default:
1886 // For other layouts if the source is depth/stencil image, both aspect bits must not be set
1887 if (ds) {
1888 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
1889 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
1890 // both must NOT be set
1891 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001892 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06001893 << string_VkImageLayout(image_layout) << " and is using depth/stencil image of format "
1894 << string_VkFormat(format)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001895 << " but it has both STENCIL and DEPTH aspects set, which is illegal. When using a depth/stencil "
1896 "image in a descriptor set, please only set either VK_IMAGE_ASPECT_DEPTH_BIT or "
1897 "VK_IMAGE_ASPECT_STENCIL_BIT depending on whether it will be used for depth reads or stencil "
1898 "reads respectively.";
Mark Lobodzinski4d05d7a2019-06-25 09:12:06 -06001899 *error_code = "VUID-VkDescriptorImageInfo-imageView-01976";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001900 *error_msg = error_str.str();
1901 return false;
1902 }
1903 }
1904 }
1905 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06001906 }
1907 // Now validate that usage flags are correctly set for given type of update
Tobin Ehlisfb4cf712016-10-10 14:02:48 -06001908 // 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 -06001909 // TODO : The various image usage bit requirements are in general spec language for VkImageUsageFlags bit block in 11.3 Images
1910 // under vkCreateImage()
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06001911 const char *error_usage_bit = nullptr;
Tobin Ehlis1809f912016-05-25 09:24:36 -06001912 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001913 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
sfricke-samsung088f1242020-06-06 02:15:35 -07001914 if (iv_state->samplerConversion != VK_NULL_HANDLE) {
1915 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-01946";
1916 std::stringstream error_str;
1917 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ")"
1918 << "used as a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE can't be created with VkSamplerYcbcrConversion";
1919 *error_msg = error_str.str();
1920 return false;
1921 }
1922 // drop through
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001923 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
1924 if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
1925 error_usage_bit = "VK_IMAGE_USAGE_SAMPLED_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08001926 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00337";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001927 }
1928 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06001929 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001930 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
1931 if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
1932 error_usage_bit = "VK_IMAGE_USAGE_STORAGE_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08001933 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00339";
sfricke-samsungada55a12020-08-15 03:39:41 -07001934 } else if ((VK_IMAGE_LAYOUT_GENERAL != image_layout) || ((VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR != image_layout) &&
1935 (device_extensions.vk_khr_shared_presentable_image))) {
sfricke-samsungf1058982020-09-10 22:36:49 -07001936 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04152";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001937 std::stringstream error_str;
sfricke-samsungada55a12020-08-15 03:39:41 -07001938 error_str << "Descriptor update with descriptorType VK_DESCRIPTOR_TYPE_STORAGE_IMAGE"
1939 << " is being updated with invalid imageLayout " << string_VkImageLayout(image_layout) << " for image "
1940 << report_data->FormatHandle(image) << " in imageView " << report_data->FormatHandle(image_view)
1941 << ". Allowed layouts are: VK_IMAGE_LAYOUT_GENERAL";
1942 if (device_extensions.vk_khr_shared_presentable_image) {
1943 error_str << " or VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR";
Tobin Ehlisbb03e5f2017-05-11 08:52:51 -06001944 }
sfricke-samsungada55a12020-08-15 03:39:41 -07001945 *error_msg = error_str.str();
1946 return false;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001947 }
1948 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06001949 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001950 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
1951 if (!(usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
1952 error_usage_bit = "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08001953 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00338";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001954 }
1955 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06001956 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001957 default:
1958 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06001959 }
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06001960 if (error_usage_bit) {
Tobin Ehlis1809f912016-05-25 09:24:36 -06001961 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001962 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") with usage mask " << std::hex << std::showbase
1963 << usage << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have "
1964 << error_usage_bit << " set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001965 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -06001966 return false;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001967 }
John Zulauff4c07882019-01-24 14:03:36 -07001968
sfricke-samsungada55a12020-08-15 03:39:41 -07001969 // All the following types share the same image layouts
1970 // checkf or Storage Images above
1971 if ((type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) || (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
1972 (type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
John Zulauff4c07882019-01-24 14:03:36 -07001973 // Test that the layout is compatible with the descriptorType for the two sampled image types
1974 const static std::array<VkImageLayout, 3> valid_layouts = {
Jeremy Hayesd0549f62019-06-05 10:15:36 -06001975 {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 -07001976
1977 struct ExtensionLayout {
1978 VkImageLayout layout;
Tony-LunarG2ec96bb2019-11-26 13:43:02 -07001979 ExtEnabled DeviceExtensions::*extension;
John Zulauff4c07882019-01-24 14:03:36 -07001980 };
1981
1982 const static std::array<ExtensionLayout, 3> extended_layouts{
1983 {// Note double brace req'd for aggregate initialization
1984 {VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR, &DeviceExtensions::vk_khr_shared_presentable_image},
1985 {VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, &DeviceExtensions::vk_khr_maintenance2},
1986 {VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, &DeviceExtensions::vk_khr_maintenance2}}};
John Zulaufc93c4252019-06-25 09:19:49 -06001987 auto is_layout = [image_layout, this](const ExtensionLayout &ext_layout) {
1988 return device_extensions.*(ext_layout.extension) && (ext_layout.layout == image_layout);
John Zulauff4c07882019-01-24 14:03:36 -07001989 };
1990
1991 bool valid_layout = (std::find(valid_layouts.cbegin(), valid_layouts.cend(), image_layout) != valid_layouts.cend()) ||
1992 std::any_of(extended_layouts.cbegin(), extended_layouts.cend(), is_layout);
1993
1994 if (!valid_layout) {
sfricke-samsungf1058982020-09-10 22:36:49 -07001995 // The following works as currently all 3 descriptor types share the same set of valid layouts
sfricke-samsungada55a12020-08-15 03:39:41 -07001996 switch (type) {
1997 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
Shannon McPherson2c793ba2020-08-28 12:13:24 -06001998 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04149";
sfricke-samsungada55a12020-08-15 03:39:41 -07001999 break;
2000 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
Shannon McPherson2c793ba2020-08-28 12:13:24 -06002001 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04150";
sfricke-samsungada55a12020-08-15 03:39:41 -07002002 break;
2003 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
sfricke-samsungf1058982020-09-10 22:36:49 -07002004 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04151";
sfricke-samsungada55a12020-08-15 03:39:41 -07002005 break;
2006 default:
2007 break;
2008 }
John Zulauff4c07882019-01-24 14:03:36 -07002009 std::stringstream error_str;
2010 error_str << "Descriptor update with descriptorType " << string_VkDescriptorType(type)
Mark Lobodzinski74eddba2019-06-21 14:16:33 -06002011 << " is being updated with invalid imageLayout " << string_VkImageLayout(image_layout) << " for image "
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002012 << report_data->FormatHandle(image) << " in imageView " << report_data->FormatHandle(image_view)
John Zulauff4c07882019-01-24 14:03:36 -07002013 << ". Allowed layouts are: VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "
2014 << "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL";
2015 for (auto &ext_layout : extended_layouts) {
John Zulaufc93c4252019-06-25 09:19:49 -06002016 if (device_extensions.*(ext_layout.extension)) {
John Zulauff4c07882019-01-24 14:03:36 -07002017 error_str << ", " << string_VkImageLayout(ext_layout.layout);
2018 }
2019 }
2020 *error_msg = error_str.str();
2021 return false;
2022 }
2023 }
2024
sfricke-samsungbd0e8052020-06-06 01:36:39 -07002025 if ((type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) || (type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
2026 const VkComponentMapping components = iv_state->create_info.components;
2027 if (IsIdentitySwizzle(components) == false) {
2028 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00336";
2029 std::stringstream error_str;
2030 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has a non-identiy swizzle component, "
2031 << " r swizzle = " << string_VkComponentSwizzle(components.r) << ","
2032 << " g swizzle = " << string_VkComponentSwizzle(components.g) << ","
2033 << " b swizzle = " << string_VkComponentSwizzle(components.b) << ","
2034 << " a swizzle = " << string_VkComponentSwizzle(components.a) << ".";
2035 *error_msg = error_str.str();
2036 return false;
2037 }
2038 }
2039
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002040 return true;
2041}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002042
John Zulaufd2c3dae2019-12-12 11:02:17 -07002043void cvdescriptorset::SamplerDescriptor::WriteUpdate(const ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update,
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002044 const uint32_t index) {
Chris Forbesfea2c542018-04-13 09:34:15 -07002045 if (!immutable_) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002046 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(update->pImageInfo[index].sampler);
Chris Forbesfea2c542018-04-13 09:34:15 -07002047 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002048 updated = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002049}
2050
John Zulaufd2c3dae2019-12-12 11:02:17 -07002051void cvdescriptorset::SamplerDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002052 if (!immutable_) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002053 sampler_state_ = static_cast<const SamplerDescriptor *>(src)->sampler_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002054 }
2055 updated = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002056}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002057
John Zulauffbf3c202019-07-17 14:57:14 -06002058void cvdescriptorset::SamplerDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002059 if (!immutable_) {
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002060 auto sampler_state = GetSamplerState();
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07002061 if (sampler_state) dev_data->AddCommandBufferBindingSampler(cb_node, sampler_state);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002062 }
2063}
2064
John Zulaufd2c3dae2019-12-12 11:02:17 -07002065cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(const ValidationStateTracker *dev_data, const VkSampler *immut)
Karl Schultz76d16a42020-11-11 05:05:33 -07002066 : immutable_(false), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002067 updated = false;
2068 descriptor_class = ImageSampler;
2069 if (immut) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002070 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(*immut);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002071 immutable_ = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002072 }
2073}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002074
John Zulaufd2c3dae2019-12-12 11:02:17 -07002075void cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(const ValidationStateTracker *dev_data,
2076 const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002077 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002078 const auto &image_info = update->pImageInfo[index];
Chris Forbesfea2c542018-04-13 09:34:15 -07002079 if (!immutable_) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002080 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(image_info.sampler);
Chris Forbesfea2c542018-04-13 09:34:15 -07002081 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002082 image_layout_ = image_info.imageLayout;
Karl Schultz76d16a42020-11-11 05:05:33 -07002083 image_view_state_ = dev_data->GetConstCastShared<IMAGE_VIEW_STATE>(image_info.imageView);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002084}
2085
John Zulaufd2c3dae2019-12-12 11:02:17 -07002086void cvdescriptorset::ImageSamplerDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002087 if (!immutable_) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002088 sampler_state_ = static_cast<const ImageSamplerDescriptor *>(src)->sampler_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002089 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002090 updated = true;
Karl Schultz76d16a42020-11-11 05:05:33 -07002091 image_layout_ = static_cast<const ImageSamplerDescriptor *>(src)->image_layout_;
2092 image_view_state_ = static_cast<const ImageSamplerDescriptor *>(src)->image_view_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002093}
2094
John Zulauffbf3c202019-07-17 14:57:14 -06002095void cvdescriptorset::ImageSamplerDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Tobin Ehlis81e46372016-08-17 13:33:44 -06002096 // First add binding for any non-immutable sampler
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002097 if (!immutable_) {
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002098 auto sampler_state = GetSamplerState();
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07002099 if (sampler_state) dev_data->AddCommandBufferBindingSampler(cb_node, sampler_state);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002100 }
Tobin Ehlis81e46372016-08-17 13:33:44 -06002101 // Add binding for image
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002102 auto iv_state = GetImageViewState();
Tobin Ehlis8b26a382016-09-14 08:02:49 -06002103 if (iv_state) {
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07002104 dev_data->AddCommandBufferBindingImageView(cb_node, iv_state);
John Zulauffbf3c202019-07-17 14:57:14 -06002105 dev_data->CallSetImageViewInitialLayoutCallback(cb_node, *iv_state, image_layout_);
Jeff Bolz148d94e2018-12-13 21:25:56 -06002106 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002107}
2108
Tobin Ehlis300888c2016-05-18 13:43:26 -06002109cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type)
Karl Schultz76d16a42020-11-11 05:05:33 -07002110 : storage_(false), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002111 updated = false;
2112 descriptor_class = Image;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002113 if (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE == type) storage_ = true;
Petr Kraus13c98a62017-12-09 00:22:39 +01002114}
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002115
John Zulaufd2c3dae2019-12-12 11:02:17 -07002116void cvdescriptorset::ImageDescriptor::WriteUpdate(const ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update,
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002117 const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002118 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002119 const auto &image_info = update->pImageInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06002120 image_layout_ = image_info.imageLayout;
Karl Schultz76d16a42020-11-11 05:05:33 -07002121 image_view_state_ = dev_data->GetConstCastShared<IMAGE_VIEW_STATE>(image_info.imageView);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002122}
2123
John Zulaufd2c3dae2019-12-12 11:02:17 -07002124void cvdescriptorset::ImageDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002125 updated = true;
Karl Schultz76d16a42020-11-11 05:05:33 -07002126 image_layout_ = static_cast<const ImageDescriptor *>(src)->image_layout_;
2127 image_view_state_ = static_cast<const ImageDescriptor *>(src)->image_view_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002128}
2129
John Zulauffbf3c202019-07-17 14:57:14 -06002130void cvdescriptorset::ImageDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Tobin Ehlis81e46372016-08-17 13:33:44 -06002131 // Add binding for image
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002132 auto iv_state = GetImageViewState();
Tobin Ehlis8b26a382016-09-14 08:02:49 -06002133 if (iv_state) {
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07002134 dev_data->AddCommandBufferBindingImageView(cb_node, iv_state);
John Zulauffbf3c202019-07-17 14:57:14 -06002135 dev_data->CallSetImageViewInitialLayoutCallback(cb_node, *iv_state, image_layout_);
Jeff Bolz148d94e2018-12-13 21:25:56 -06002136 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002137}
2138
Tobin Ehlis300888c2016-05-18 13:43:26 -06002139cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type)
Karl Schultz76d16a42020-11-11 05:05:33 -07002140 : storage_(false), dynamic_(false), offset_(0), range_(0) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002141 updated = false;
2142 descriptor_class = GeneralBuffer;
2143 if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) {
2144 dynamic_ = true;
2145 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type) {
2146 storage_ = true;
2147 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) {
2148 dynamic_ = true;
2149 storage_ = true;
2150 }
2151}
John Zulaufd2c3dae2019-12-12 11:02:17 -07002152void cvdescriptorset::BufferDescriptor::WriteUpdate(const ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update,
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002153 const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002154 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002155 const auto &buffer_info = update->pBufferInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06002156 offset_ = buffer_info.offset;
2157 range_ = buffer_info.range;
Karl Schultz76d16a42020-11-11 05:05:33 -07002158 buffer_state_ = dev_data->GetConstCastShared<BUFFER_STATE>(buffer_info.buffer);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002159}
2160
John Zulaufd2c3dae2019-12-12 11:02:17 -07002161void cvdescriptorset::BufferDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002162 updated = true;
Karl Schultz76d16a42020-11-11 05:05:33 -07002163 const auto buff_desc = static_cast<const BufferDescriptor *>(src);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002164 offset_ = buff_desc->offset_;
2165 range_ = buff_desc->range_;
Karl Schultz76d16a42020-11-11 05:05:33 -07002166 buffer_state_ = buff_desc->buffer_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002167}
2168
John Zulauffbf3c202019-07-17 14:57:14 -06002169void cvdescriptorset::BufferDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002170 auto buffer_node = GetBufferState();
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07002171 if (buffer_node) dev_data->AddCommandBufferBindingBuffer(cb_node, buffer_node);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002172}
2173
Karl Schultz76d16a42020-11-11 05:05:33 -07002174cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type) : storage_(false) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002175 updated = false;
2176 descriptor_class = TexelBuffer;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002177 if (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER == type) storage_ = true;
Petr Kraus13c98a62017-12-09 00:22:39 +01002178}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002179
John Zulaufd2c3dae2019-12-12 11:02:17 -07002180void cvdescriptorset::TexelDescriptor::WriteUpdate(const ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update,
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002181 const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002182 updated = true;
Karl Schultz76d16a42020-11-11 05:05:33 -07002183 buffer_view_state_ = dev_data->GetConstCastShared<BUFFER_VIEW_STATE>(update->pTexelBufferView[index]);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002184}
2185
John Zulaufd2c3dae2019-12-12 11:02:17 -07002186void cvdescriptorset::TexelDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002187 updated = true;
Karl Schultz76d16a42020-11-11 05:05:33 -07002188 buffer_view_state_ = static_cast<const TexelDescriptor *>(src)->buffer_view_state_;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002189}
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002190
John Zulauffbf3c202019-07-17 14:57:14 -06002191void cvdescriptorset::TexelDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002192 auto bv_state = GetBufferViewState();
Tobin Ehlis8b872462016-09-14 08:12:08 -06002193 if (bv_state) {
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07002194 dev_data->AddCommandBufferBindingBufferView(cb_node, bv_state);
Tobin Ehlis81e46372016-08-17 13:33:44 -06002195 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002196}
2197
Jeff Bolz95176d02020-04-01 00:36:16 -05002198cvdescriptorset::AccelerationStructureDescriptor::AccelerationStructureDescriptor(const VkDescriptorType type)
2199 : acc_(VK_NULL_HANDLE) {
2200 updated = false;
2201 descriptor_class = AccelerationStructure;
2202}
2203void cvdescriptorset::AccelerationStructureDescriptor::WriteUpdate(const ValidationStateTracker *dev_data,
2204 const VkWriteDescriptorSet *update, const uint32_t index) {
2205 const auto *accInfo = lvl_find_in_chain<VkWriteDescriptorSetAccelerationStructureKHR>(update->pNext);
2206
2207 updated = true;
2208 acc_ = accInfo->pAccelerationStructures[index];
2209 acc_state_ = dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE>(acc_);
2210}
2211
2212void cvdescriptorset::AccelerationStructureDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
2213 auto acc_desc = static_cast<const AccelerationStructureDescriptor *>(src);
2214 updated = true;
2215 acc_ = acc_desc->acc_;
2216 acc_state_ = dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE>(acc_);
2217}
2218
2219void cvdescriptorset::AccelerationStructureDescriptor::UpdateDrawState(ValidationStateTracker *dev_data,
2220 CMD_BUFFER_STATE *cb_node) {
2221 auto acc_node = GetAccelerationStructureState();
2222 if (acc_node) dev_data->AddCommandBufferBindingAccelerationStructure(cb_node, acc_node);
2223}
2224
Tobin Ehlis300888c2016-05-18 13:43:26 -06002225// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
2226// sets, and then calls their respective Validate[Write|Copy]Update functions.
2227// If the update hits an issue for which the callback returns "true", meaning that the call down the chain should
2228// be skipped, then true is returned.
2229// If there is no issue with the update, then false is returned.
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002230bool CoreChecks::ValidateUpdateDescriptorSets(uint32_t write_count, const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05002231 const VkCopyDescriptorSet *p_cds, const char *func_name) const {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002232 bool skip = false;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002233 // Validate Write updates
Tobin Ehlis56a30942016-05-19 08:00:00 -06002234 for (uint32_t i = 0; i < write_count; i++) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002235 auto dest_set = p_wds[i].dstSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002236 auto set_node = GetSetNode(dest_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002237 if (!set_node) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002238 skip |=
2239 LogError(dest_set, kVUID_Core_DrawState_InvalidDescriptorSet, "Cannot call %s on %s that has not been allocated.",
2240 func_name, report_data->FormatHandle(dest_set).c_str());
Tobin Ehlis300888c2016-05-18 13:43:26 -06002241 } else {
Dave Houltond8ed0212018-05-16 17:18:24 -06002242 std::string error_code;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002243 std::string error_str;
John Zulaufc93c4252019-06-25 09:19:49 -06002244 if (!ValidateWriteUpdate(set_node, &p_wds[i], func_name, &error_code, &error_str)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002245 skip |= LogError(dest_set, error_code, "%s failed write update validation for %s with error: %s.", func_name,
2246 report_data->FormatHandle(dest_set).c_str(), error_str.c_str());
Tobin Ehlis300888c2016-05-18 13:43:26 -06002247 }
2248 }
sourav parmara24fb7b2020-05-26 10:50:04 -07002249 if (p_wds[i].pNext) {
Mark Lobodzinski17dc4602020-05-29 07:48:40 -06002250 const auto *pnext_struct = lvl_find_in_chain<VkWriteDescriptorSetAccelerationStructureKHR>(p_wds[i].pNext);
2251 if (pnext_struct) {
2252 for (uint32_t j = 0; j < pnext_struct->accelerationStructureCount; ++j) {
sourav parmara24fb7b2020-05-26 10:50:04 -07002253 const ACCELERATION_STRUCTURE_STATE *as_state =
Mark Lobodzinski17dc4602020-05-29 07:48:40 -06002254 GetAccelerationStructureState(pnext_struct->pAccelerationStructures[j]);
Tony-LunarG3feec122020-06-17 10:05:15 -06002255 if (as_state && as_state->is_khr &&
2256 (as_state->create_infoKHR.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR &&
2257 as_state->create_infoKHR.type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR)) {
sourav parmara24fb7b2020-05-26 10:50:04 -07002258 skip |=
2259 LogError(dest_set, "VUID-VkWriteDescriptorSetAccelerationStructureKHR-pAccelerationStructures-02764",
2260 "%s: Each acceleration structure in pAccelerationStructures must have been"
2261 "created with VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR.",
2262 func_name);
2263 }
2264 }
2265 }
2266 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002267 }
2268 // Now validate copy updates
Tobin Ehlis56a30942016-05-19 08:00:00 -06002269 for (uint32_t i = 0; i < copy_count; ++i) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002270 auto dst_set = p_cds[i].dstSet;
2271 auto src_set = p_cds[i].srcSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002272 auto src_node = GetSetNode(src_set);
2273 auto dst_node = GetSetNode(dst_set);
Tobin Ehlisa1712752017-01-04 09:41:47 -07002274 // Object_tracker verifies that src & dest descriptor set are valid
2275 assert(src_node);
2276 assert(dst_node);
Dave Houltond8ed0212018-05-16 17:18:24 -06002277 std::string error_code;
Tobin Ehlisa1712752017-01-04 09:41:47 -07002278 std::string error_str;
John Zulaufc93c4252019-06-25 09:19:49 -06002279 if (!ValidateCopyUpdate(&p_cds[i], dst_node, src_node, func_name, &error_code, &error_str)) {
Mark Lobodzinski9d38ea22020-03-16 18:22:16 -06002280 LogObjectList objlist(dst_set);
2281 objlist.add(src_set);
locke-lunarg9edc2812019-06-17 23:18:52 -06002282 skip |=
Mark Lobodzinski9d38ea22020-03-16 18:22:16 -06002283 LogError(objlist, error_code, "%s failed copy update from %s to %s with error: %s.", func_name,
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002284 report_data->FormatHandle(src_set).c_str(), report_data->FormatHandle(dst_set).c_str(), error_str.c_str());
Tobin Ehlis300888c2016-05-18 13:43:26 -06002285 }
2286 }
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002287 return skip;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002288}
2289// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
2290// sets, and then calls their respective Perform[Write|Copy]Update functions.
2291// Prerequisite : ValidateUpdateDescriptorSets() should be called and return "false" prior to calling PerformUpdateDescriptorSets()
2292// with the same set of updates.
2293// This is split from the validate code to allow validation prior to calling down the chain, and then update after
2294// calling down the chain.
John Zulaufe3b35f32019-06-25 14:21:21 -06002295void cvdescriptorset::PerformUpdateDescriptorSets(ValidationStateTracker *dev_data, uint32_t write_count,
2296 const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
2297 const VkCopyDescriptorSet *p_cds) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002298 // Write updates first
2299 uint32_t i = 0;
2300 for (i = 0; i < write_count; ++i) {
2301 auto dest_set = p_wds[i].dstSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002302 auto set_node = dev_data->GetSetNode(dest_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002303 if (set_node) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05002304 set_node->PerformWriteUpdate(dev_data, &p_wds[i]);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002305 }
2306 }
2307 // Now copy updates
2308 for (i = 0; i < copy_count; ++i) {
2309 auto dst_set = p_cds[i].dstSet;
2310 auto src_set = p_cds[i].srcSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002311 auto src_node = dev_data->GetSetNode(src_set);
2312 auto dst_node = dev_data->GetSetNode(dst_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002313 if (src_node && dst_node) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05002314 dst_node->PerformCopyUpdate(dev_data, &p_cds[i], src_node);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002315 }
2316 }
2317}
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002318
John Zulaufe3b35f32019-06-25 14:21:21 -06002319cvdescriptorset::DecodedTemplateUpdate::DecodedTemplateUpdate(const ValidationStateTracker *device_data,
2320 VkDescriptorSet descriptorSet, const TEMPLATE_STATE *template_state,
2321 const void *pData, VkDescriptorSetLayout push_layout) {
John Zulaufb845eb22018-10-12 11:41:06 -06002322 auto const &create_info = template_state->create_info;
2323 inline_infos.resize(create_info.descriptorUpdateEntryCount); // Make sure we have one if we need it
2324 desc_writes.reserve(create_info.descriptorUpdateEntryCount); // emplaced, so reserved without initialization
John Zulauf1d27e0a2018-11-05 10:12:48 -07002325 VkDescriptorSetLayout effective_dsl = create_info.templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
2326 ? create_info.descriptorSetLayout
2327 : push_layout;
Jeff Bolz6ae39612019-10-11 20:57:36 -05002328 auto layout_obj = device_data->GetDescriptorSetLayoutShared(effective_dsl);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002329
2330 // Create a WriteDescriptorSet struct for each template update entry
2331 for (uint32_t i = 0; i < create_info.descriptorUpdateEntryCount; i++) {
2332 auto binding_count = layout_obj->GetDescriptorCountFromBinding(create_info.pDescriptorUpdateEntries[i].dstBinding);
2333 auto binding_being_updated = create_info.pDescriptorUpdateEntries[i].dstBinding;
2334 auto dst_array_element = create_info.pDescriptorUpdateEntries[i].dstArrayElement;
2335
John Zulaufb6d71202017-12-22 16:47:09 -07002336 desc_writes.reserve(desc_writes.size() + create_info.pDescriptorUpdateEntries[i].descriptorCount);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002337 for (uint32_t j = 0; j < create_info.pDescriptorUpdateEntries[i].descriptorCount; j++) {
2338 desc_writes.emplace_back();
2339 auto &write_entry = desc_writes.back();
2340
2341 size_t offset = create_info.pDescriptorUpdateEntries[i].offset + j * create_info.pDescriptorUpdateEntries[i].stride;
2342 char *update_entry = (char *)(pData) + offset;
2343
2344 if (dst_array_element >= binding_count) {
2345 dst_array_element = 0;
Mark Lobodzinski4aa479d2017-03-10 09:14:00 -07002346 binding_being_updated = layout_obj->GetNextValidBinding(binding_being_updated);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002347 }
2348
2349 write_entry.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2350 write_entry.pNext = NULL;
2351 write_entry.dstSet = descriptorSet;
2352 write_entry.dstBinding = binding_being_updated;
2353 write_entry.dstArrayElement = dst_array_element;
2354 write_entry.descriptorCount = 1;
2355 write_entry.descriptorType = create_info.pDescriptorUpdateEntries[i].descriptorType;
2356
2357 switch (create_info.pDescriptorUpdateEntries[i].descriptorType) {
2358 case VK_DESCRIPTOR_TYPE_SAMPLER:
2359 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2360 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2361 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2362 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2363 write_entry.pImageInfo = reinterpret_cast<VkDescriptorImageInfo *>(update_entry);
2364 break;
2365
2366 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2367 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2368 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2369 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2370 write_entry.pBufferInfo = reinterpret_cast<VkDescriptorBufferInfo *>(update_entry);
2371 break;
2372
2373 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2374 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2375 write_entry.pTexelBufferView = reinterpret_cast<VkBufferView *>(update_entry);
2376 break;
Dave Houlton142c4cb2018-10-17 15:04:41 -06002377 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: {
2378 VkWriteDescriptorSetInlineUniformBlockEXT *inline_info = &inline_infos[i];
2379 inline_info->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT;
2380 inline_info->pNext = nullptr;
2381 inline_info->dataSize = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2382 inline_info->pData = update_entry;
2383 write_entry.pNext = inline_info;
Ricardo Garciafee15732019-05-28 11:13:31 +02002384 // descriptorCount must match the dataSize member of the VkWriteDescriptorSetInlineUniformBlockEXT structure
2385 write_entry.descriptorCount = inline_info->dataSize;
Dave Houlton142c4cb2018-10-17 15:04:41 -06002386 // skip the rest of the array, they just represent bytes in the update
2387 j = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2388 break;
2389 }
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002390 default:
2391 assert(0);
2392 break;
2393 }
2394 dst_array_element++;
2395 }
2396 }
John Zulaufb845eb22018-10-12 11:41:06 -06002397}
John Zulaufb45fdc32018-10-12 15:14:17 -06002398// These helper functions carry out the validate and record descriptor updates peformed via update templates. They decode
2399// the templatized data and leverage the non-template UpdateDescriptor helper functions.
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002400bool CoreChecks::ValidateUpdateDescriptorSetsWithTemplateKHR(VkDescriptorSet descriptorSet, const TEMPLATE_STATE *template_state,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05002401 const void *pData) const {
John Zulaufb45fdc32018-10-12 15:14:17 -06002402 // Translate the templated update into a normal update for validation...
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002403 cvdescriptorset::DecodedTemplateUpdate decoded_update(this, descriptorSet, template_state, pData);
2404 return ValidateUpdateDescriptorSets(static_cast<uint32_t>(decoded_update.desc_writes.size()), decoded_update.desc_writes.data(),
2405 0, NULL, "vkUpdateDescriptorSetWithTemplate()");
John Zulaufb45fdc32018-10-12 15:14:17 -06002406}
John Zulaufb845eb22018-10-12 11:41:06 -06002407
John Zulauf4e7bcb52018-11-02 10:46:30 -06002408std::string cvdescriptorset::DescriptorSet::StringifySetAndLayout() const {
2409 std::string out;
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002410 auto layout_handle = p_layout_->GetDescriptorSetLayout();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002411 if (IsPushDescriptor()) {
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002412 std::ostringstream str;
Tony-LunarG1d3ee2d2020-10-27 15:54:52 -06002413 str << "Push Descriptors defined with " << state_data_->report_data->FormatHandle(layout_handle);
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002414 out = str.str();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002415 } else {
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002416 std::ostringstream str;
Tony-LunarG1d3ee2d2020-10-27 15:54:52 -06002417 str << state_data_->report_data->FormatHandle(set_) << " allocated with "
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002418 << state_data_->report_data->FormatHandle(layout_handle);
2419 out = str.str();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002420 }
2421 return out;
2422};
2423
John Zulauf1d27e0a2018-11-05 10:12:48 -07002424// Loop through the write updates to validate for a push descriptor set, ignoring dstSet
John Zulaufc93c4252019-06-25 09:19:49 -06002425bool CoreChecks::ValidatePushDescriptorsUpdate(const DescriptorSet *push_set, uint32_t write_count,
John Zulaufbd9b3412019-08-22 17:16:11 -06002426 const VkWriteDescriptorSet *p_wds, const char *func_name) const {
John Zulaufd9435c32019-06-05 15:55:36 -06002427 assert(push_set->IsPushDescriptor());
John Zulauf1d27e0a2018-11-05 10:12:48 -07002428 bool skip = false;
2429 for (uint32_t i = 0; i < write_count; i++) {
2430 std::string error_code;
2431 std::string error_str;
John Zulaufc93c4252019-06-25 09:19:49 -06002432 if (!ValidateWriteUpdate(push_set, &p_wds[i], func_name, &error_code, &error_str)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002433 skip |= LogError(push_set->GetDescriptorSetLayout(), error_code, "%s failed update validation: %s.", func_name,
2434 error_str.c_str());
John Zulauf1d27e0a2018-11-05 10:12:48 -07002435 }
2436 }
2437 return skip;
2438}
2439
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002440// For the given buffer, verify that its creation parameters are appropriate for the given type
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002441// 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 -06002442bool cvdescriptorset::ValidateBufferUsage(debug_report_data *report_data, BUFFER_STATE const *buffer_node, VkDescriptorType type,
2443 std::string *error_code, std::string *error_msg) {
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002444 // Verify that usage bits set correctly for given type
Tobin Ehlis94bc5d22016-06-02 07:46:52 -06002445 auto usage = buffer_node->createInfo.usage;
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002446 const char *error_usage_bit = nullptr;
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002447 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002448 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2449 if (!(usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002450 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00334";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002451 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT";
2452 }
2453 break;
2454 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2455 if (!(usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002456 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00335";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002457 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT";
2458 }
2459 break;
2460 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2461 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2462 if (!(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002463 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00330";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002464 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT";
2465 }
2466 break;
2467 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2468 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2469 if (!(usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002470 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00331";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002471 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT";
2472 }
2473 break;
2474 default:
2475 break;
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002476 }
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002477 if (error_usage_bit) {
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002478 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002479 error_str << "Buffer (" << report_data->FormatHandle(buffer_node->buffer) << ") with usage mask " << std::hex
2480 << std::showbase << usage << " being used for a descriptor update of type " << string_VkDescriptorType(type)
2481 << " does not have " << error_usage_bit << " set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002482 *error_msg = error_str.str();
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002483 return false;
2484 }
2485 return true;
2486}
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002487// For buffer descriptor updates, verify the buffer usage and VkDescriptorBufferInfo struct which includes:
2488// 1. buffer is valid
2489// 2. buffer was created with correct usage flags
2490// 3. offset is less than buffer size
2491// 4. range is either VK_WHOLE_SIZE or falls in (0, (buffer size - offset)]
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002492// 5. range and offset are within the device's limits
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002493// 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 -06002494bool CoreChecks::ValidateBufferUpdate(VkDescriptorBufferInfo const *buffer_info, VkDescriptorType type, const char *func_name,
John Zulaufbd9b3412019-08-22 17:16:11 -06002495 std::string *error_code, std::string *error_msg) const {
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002496 // First make sure that buffer is valid
John Zulaufc93c4252019-06-25 09:19:49 -06002497 auto buffer_node = GetBufferState(buffer_info->buffer);
Tobin Ehlisfa8b6182016-12-22 13:40:45 -07002498 // Any invalid buffer should already be caught by object_tracker
2499 assert(buffer_node);
John Zulaufc93c4252019-06-25 09:19:49 -06002500 if (ValidateMemoryIsBoundToBuffer(buffer_node, func_name, "VUID-VkWriteDescriptorSet-descriptorType-00329")) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002501 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00329";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002502 *error_msg = "No memory bound to buffer.";
Tobin Ehlis81280962016-07-20 14:04:20 -06002503 return false;
Tobin Ehlisfed999f2016-09-21 15:09:45 -06002504 }
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002505 // Verify usage bits
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002506 if (!cvdescriptorset::ValidateBufferUsage(report_data, buffer_node, type, error_code, error_msg)) {
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002507 // error_msg will have been updated by ValidateBufferUsage()
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002508 return false;
2509 }
2510 // offset must be less than buffer size
Jeremy Hayesd1a6a822017-03-09 14:39:45 -07002511 if (buffer_info->offset >= buffer_node->createInfo.size) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002512 *error_code = "VUID-VkDescriptorBufferInfo-offset-00340";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002513 std::stringstream error_str;
Jeremy Hayesd1a6a822017-03-09 14:39:45 -07002514 error_str << "VkDescriptorBufferInfo offset of " << buffer_info->offset << " is greater than or equal to buffer "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002515 << report_data->FormatHandle(buffer_node->buffer) << " size of " << buffer_node->createInfo.size;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002516 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002517 return false;
2518 }
2519 if (buffer_info->range != VK_WHOLE_SIZE) {
2520 // Range must be VK_WHOLE_SIZE or > 0
2521 if (!buffer_info->range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002522 *error_code = "VUID-VkDescriptorBufferInfo-range-00341";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002523 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002524 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer)
2525 << " VkDescriptorBufferInfo range is not VK_WHOLE_SIZE and is zero, which is not allowed.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002526 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002527 return false;
2528 }
2529 // Range must be VK_WHOLE_SIZE or <= (buffer size - offset)
2530 if (buffer_info->range > (buffer_node->createInfo.size - buffer_info->offset)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002531 *error_code = "VUID-VkDescriptorBufferInfo-range-00342";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002532 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002533 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer) << " VkDescriptorBufferInfo range is "
2534 << buffer_info->range << " which is greater than buffer size (" << buffer_node->createInfo.size
2535 << ") minus requested offset of " << buffer_info->offset;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002536 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002537 return false;
2538 }
2539 }
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002540 // Check buffer update sizes against device limits
John Zulaufc93c4252019-06-25 09:19:49 -06002541 const auto &limits = phys_dev_props.limits;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002542 if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == type || VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) {
John Zulaufd9435c32019-06-05 15:55:36 -06002543 auto max_ub_range = limits.maxUniformBufferRange;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002544 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_ub_range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002545 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00332";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002546 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002547 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer) << " VkDescriptorBufferInfo range is "
2548 << buffer_info->range << " which is greater than this device's maxUniformBufferRange (" << max_ub_range
2549 << ")";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002550 *error_msg = error_str.str();
2551 return false;
Peter Kohaut2794a292018-07-13 11:13:47 +02002552 } else if (buffer_info->range == VK_WHOLE_SIZE && (buffer_node->createInfo.size - buffer_info->offset) > max_ub_range) {
2553 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00332";
2554 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002555 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer)
2556 << " VkDescriptorBufferInfo range is VK_WHOLE_SIZE but effective range "
Peter Kohaut18f413d2018-07-16 13:15:42 +02002557 << "(" << (buffer_node->createInfo.size - buffer_info->offset) << ") is greater than this device's "
Peter Kohaut2794a292018-07-13 11:13:47 +02002558 << "maxUniformBufferRange (" << max_ub_range << ")";
2559 *error_msg = error_str.str();
2560 return false;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002561 }
2562 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type || VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) {
John Zulaufd9435c32019-06-05 15:55:36 -06002563 auto max_sb_range = limits.maxStorageBufferRange;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002564 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_sb_range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002565 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00333";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002566 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002567 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer) << " VkDescriptorBufferInfo range is "
2568 << buffer_info->range << " which is greater than this device's maxStorageBufferRange (" << max_sb_range
2569 << ")";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002570 *error_msg = error_str.str();
2571 return false;
Peter Kohaut2794a292018-07-13 11:13:47 +02002572 } else if (buffer_info->range == VK_WHOLE_SIZE && (buffer_node->createInfo.size - buffer_info->offset) > max_sb_range) {
2573 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00333";
2574 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002575 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer)
2576 << " VkDescriptorBufferInfo range is VK_WHOLE_SIZE but effective range "
Peter Kohaut18f413d2018-07-16 13:15:42 +02002577 << "(" << (buffer_node->createInfo.size - buffer_info->offset) << ") is greater than this device's "
Peter Kohaut2794a292018-07-13 11:13:47 +02002578 << "maxStorageBufferRange (" << max_sb_range << ")";
2579 *error_msg = error_str.str();
2580 return false;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002581 }
2582 }
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002583 return true;
2584}
Jeff Bolz95176d02020-04-01 00:36:16 -05002585
2586bool CoreChecks::ValidateAccelerationStructureUpdate(VkAccelerationStructureKHR acc, const char *func_name, std::string *error_code,
2587 std::string *error_msg) const {
2588 // First make sure that acceleration structure is valid
2589 auto acc_node = GetAccelerationStructureState(acc);
2590 // Any invalid acc struct should already be caught by object_tracker
2591 assert(acc_node);
2592 if (ValidateMemoryIsBoundToAccelerationStructure(acc_node, func_name, kVUIDUndefined)) {
2593 *error_code = kVUIDUndefined;
2594 *error_msg = "No memory bound to acceleration structure.";
2595 return false;
2596 }
2597 return true;
2598}
2599
Tobin Ehlis300888c2016-05-18 13:43:26 -06002600// Verify that the contents of the update are ok, but don't perform actual update
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002601bool CoreChecks::VerifyCopyUpdateContents(const VkCopyDescriptorSet *update, const DescriptorSet *src_set,
2602 VkDescriptorType src_type, uint32_t src_index, const DescriptorSet *dst_set,
2603 VkDescriptorType dst_type, uint32_t dst_index, const char *func_name,
2604 std::string *error_code, std::string *error_msg) const {
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002605 // Note : Repurposing some Write update error codes here as specific details aren't called out for copy updates like they are
2606 // for write updates
John Zulaufc93c4252019-06-25 09:19:49 -06002607 using DescriptorClass = cvdescriptorset::DescriptorClass;
2608 using BufferDescriptor = cvdescriptorset::BufferDescriptor;
2609 using ImageDescriptor = cvdescriptorset::ImageDescriptor;
2610 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
2611 using SamplerDescriptor = cvdescriptorset::SamplerDescriptor;
2612 using TexelDescriptor = cvdescriptorset::TexelDescriptor;
2613
2614 auto device_data = this;
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002615
2616 if (dst_type == VK_DESCRIPTOR_TYPE_SAMPLER) {
2617 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
2618 const auto dst_desc = dst_set->GetDescriptorFromGlobalIndex(dst_index + di);
2619 if (!dst_desc->updated) continue;
2620 if (dst_desc->IsImmutableSampler()) {
2621 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02753";
2622 std::stringstream error_str;
2623 error_str << "Attempted copy update to an immutable sampler descriptor.";
2624 *error_msg = error_str.str();
2625 return false;
2626 }
2627 }
2628 }
2629
2630 switch (src_set->GetDescriptorFromGlobalIndex(src_index)->descriptor_class) {
John Zulaufc93c4252019-06-25 09:19:49 -06002631 case DescriptorClass::PlainSampler: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002632 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002633 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002634 if (!src_desc->updated) continue;
2635 if (!src_desc->IsImmutableSampler()) {
John Zulaufd9435c32019-06-05 15:55:36 -06002636 auto update_sampler = static_cast<const SamplerDescriptor *>(src_desc)->GetSampler();
John Zulaufc93c4252019-06-25 09:19:49 -06002637 if (!ValidateSampler(update_sampler)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002638 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002639 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002640 error_str << "Attempted copy update to sampler descriptor with invalid sampler: "
2641 << report_data->FormatHandle(update_sampler) << ".";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002642 *error_msg = error_str.str();
2643 return false;
2644 }
2645 } else {
2646 // TODO : Warn here
2647 }
2648 }
2649 break;
2650 }
John Zulaufc93c4252019-06-25 09:19:49 -06002651 case DescriptorClass::ImageSampler: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002652 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002653 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002654 if (!src_desc->updated) continue;
2655 auto img_samp_desc = static_cast<const ImageSamplerDescriptor *>(src_desc);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002656 // First validate sampler
2657 if (!img_samp_desc->IsImmutableSampler()) {
2658 auto update_sampler = img_samp_desc->GetSampler();
John Zulaufc93c4252019-06-25 09:19:49 -06002659 if (!ValidateSampler(update_sampler)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002660 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002661 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002662 error_str << "Attempted copy update to sampler descriptor with invalid sampler: "
2663 << report_data->FormatHandle(update_sampler) << ".";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002664 *error_msg = error_str.str();
2665 return false;
2666 }
2667 } else {
2668 // TODO : Warn here
2669 }
2670 // Validate image
2671 auto image_view = img_samp_desc->GetImageView();
2672 auto image_layout = img_samp_desc->GetImageLayout();
Jeff Bolz165818a2020-05-08 11:19:03 -05002673 if (image_view) {
2674 if (!ValidateImageUpdate(image_view, image_layout, src_type, func_name, error_code, error_msg)) {
2675 std::stringstream error_str;
2676 error_str << "Attempted copy update to combined image sampler descriptor failed due to: "
2677 << error_msg->c_str();
2678 *error_msg = error_str.str();
2679 return false;
2680 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002681 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002682 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002683 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002684 }
John Zulaufc93c4252019-06-25 09:19:49 -06002685 case DescriptorClass::Image: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002686 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002687 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002688 if (!src_desc->updated) continue;
2689 auto img_desc = static_cast<const ImageDescriptor *>(src_desc);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002690 auto image_view = img_desc->GetImageView();
2691 auto image_layout = img_desc->GetImageLayout();
Jeff Bolz165818a2020-05-08 11:19:03 -05002692 if (image_view) {
2693 if (!ValidateImageUpdate(image_view, image_layout, src_type, func_name, error_code, error_msg)) {
2694 std::stringstream error_str;
2695 error_str << "Attempted copy update to image descriptor failed due to: " << error_msg->c_str();
2696 *error_msg = error_str.str();
2697 return false;
2698 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002699 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002700 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002701 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002702 }
John Zulaufc93c4252019-06-25 09:19:49 -06002703 case DescriptorClass::TexelBuffer: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002704 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002705 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002706 if (!src_desc->updated) continue;
John Zulaufd9435c32019-06-05 15:55:36 -06002707 auto buffer_view = static_cast<const TexelDescriptor *>(src_desc)->GetBufferView();
Jeff Bolz165818a2020-05-08 11:19:03 -05002708 if (buffer_view) {
2709 auto bv_state = device_data->GetBufferViewState(buffer_view);
2710 if (!bv_state) {
2711 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
2712 std::stringstream error_str;
2713 error_str << "Attempted copy update to texel buffer descriptor with invalid buffer view: "
2714 << report_data->FormatHandle(buffer_view);
2715 *error_msg = error_str.str();
2716 return false;
2717 }
2718 auto buffer = bv_state->create_info.buffer;
2719 if (!cvdescriptorset::ValidateBufferUsage(report_data, GetBufferState(buffer), src_type, error_code,
2720 error_msg)) {
2721 std::stringstream error_str;
2722 error_str << "Attempted copy update to texel buffer descriptor failed due to: " << error_msg->c_str();
2723 *error_msg = error_str.str();
2724 return false;
2725 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002726 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002727 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002728 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002729 }
John Zulaufc93c4252019-06-25 09:19:49 -06002730 case DescriptorClass::GeneralBuffer: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002731 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002732 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002733 if (!src_desc->updated) continue;
John Zulaufd9435c32019-06-05 15:55:36 -06002734 auto buffer = static_cast<const BufferDescriptor *>(src_desc)->GetBuffer();
Jeff Bolz165818a2020-05-08 11:19:03 -05002735 if (buffer) {
2736 if (!cvdescriptorset::ValidateBufferUsage(report_data, GetBufferState(buffer), src_type, error_code,
2737 error_msg)) {
2738 std::stringstream error_str;
2739 error_str << "Attempted copy update to buffer descriptor failed due to: " << error_msg->c_str();
2740 *error_msg = error_str.str();
2741 return false;
2742 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002743 }
Tobin Ehliscbcf2342016-05-24 13:07:12 -06002744 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002745 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002746 }
John Zulaufc93c4252019-06-25 09:19:49 -06002747 case DescriptorClass::InlineUniform:
2748 case DescriptorClass::AccelerationStructure:
Jeff Bolze54ae892018-09-08 12:16:29 -05002749 break;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002750 default:
2751 assert(0); // We've already verified update type so should never get here
2752 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002753 }
2754 // All checks passed so update contents are good
2755 return true;
Chris Forbesb4e0bdb2016-05-31 16:34:40 +12002756}
Tobin Ehlisee471462016-05-26 11:21:59 -06002757// Verify that the state at allocate time is correct, but don't actually allocate the sets yet
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002758bool CoreChecks::ValidateAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *p_alloc_info,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05002759 const cvdescriptorset::AllocateDescriptorSetsData *ds_data) const {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002760 bool skip = false;
Mark Lobodzinski7804bd42019-03-06 11:28:48 -07002761 auto pool_state = GetDescriptorPoolState(p_alloc_info->descriptorPool);
Tobin Ehlisee471462016-05-26 11:21:59 -06002762
2763 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
Jeff Bolz6ae39612019-10-11 20:57:36 -05002764 auto layout = GetDescriptorSetLayoutShared(p_alloc_info->pSetLayouts[i]);
John Zulauf5562d062018-01-24 11:54:05 -07002765 if (layout) { // nullptr layout indicates no valid layout handle for this device, validated/logged in object_tracker
John Zulauf1d27e0a2018-11-05 10:12:48 -07002766 if (layout->IsPushDescriptor()) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002767 skip |= LogError(p_alloc_info->pSetLayouts[i], "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-00308",
2768 "%s specified at pSetLayouts[%" PRIu32
2769 "] in vkAllocateDescriptorSets() was created with invalid flag %s set.",
2770 report_data->FormatHandle(p_alloc_info->pSetLayouts[i]).c_str(), i,
2771 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR");
John Zulauf5562d062018-01-24 11:54:05 -07002772 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05002773 if (layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT &&
2774 !(pool_state->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002775 skip |= LogError(device, "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-03044",
2776 "Descriptor set layout create flags and pool create flags mismatch for index (%d)", i);
Jeff Bolzfdf96072018-04-10 14:32:18 -05002777 }
Tobin Ehlisee471462016-05-26 11:21:59 -06002778 }
2779 }
Mark Lobodzinskif45e45f2019-04-19 14:15:39 -06002780 if (!device_extensions.vk_khr_maintenance1) {
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06002781 // Track number of descriptorSets allowable in this pool
2782 if (pool_state->availableSets < p_alloc_info->descriptorSetCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002783 skip |= LogError(pool_state->pool, "VUID-VkDescriptorSetAllocateInfo-descriptorSetCount-00306",
2784 "Unable to allocate %u descriptorSets from %s"
2785 ". This pool only has %d descriptorSets remaining.",
2786 p_alloc_info->descriptorSetCount, report_data->FormatHandle(pool_state->pool).c_str(),
2787 pool_state->availableSets);
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06002788 }
2789 // Determine whether descriptor counts are satisfiable
Jeff Bolze54ae892018-09-08 12:16:29 -05002790 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 -05002791 auto count_iter = pool_state->availableDescriptorTypeCount.find(it->first);
2792 uint32_t availableCount = (count_iter != pool_state->availableDescriptorTypeCount.end()) ? count_iter->second : 0;
2793
2794 if (ds_data->required_descriptors_by_type.at(it->first) > availableCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002795 skip |= LogError(pool_state->pool, "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307",
2796 "Unable to allocate %u descriptors of type %s from %s"
2797 ". This pool only has %d descriptors of this type remaining.",
2798 ds_data->required_descriptors_by_type.at(it->first),
2799 string_VkDescriptorType(VkDescriptorType(it->first)),
2800 report_data->FormatHandle(pool_state->pool).c_str(), availableCount);
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06002801 }
Tobin Ehlisee471462016-05-26 11:21:59 -06002802 }
2803 }
Tobin Ehlis5d749ea2016-07-18 13:14:01 -06002804
Jeff Bolzfdf96072018-04-10 14:32:18 -05002805 const auto *count_allocate_info = lvl_find_in_chain<VkDescriptorSetVariableDescriptorCountAllocateInfoEXT>(p_alloc_info->pNext);
2806
2807 if (count_allocate_info) {
2808 if (count_allocate_info->descriptorSetCount != 0 &&
2809 count_allocate_info->descriptorSetCount != p_alloc_info->descriptorSetCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002810 skip |= LogError(device, "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfo-descriptorSetCount-03045",
2811 "VkDescriptorSetAllocateInfo::descriptorSetCount (%d) != "
2812 "VkDescriptorSetVariableDescriptorCountAllocateInfoEXT::descriptorSetCount (%d)",
2813 p_alloc_info->descriptorSetCount, count_allocate_info->descriptorSetCount);
Jeff Bolzfdf96072018-04-10 14:32:18 -05002814 }
2815 if (count_allocate_info->descriptorSetCount == p_alloc_info->descriptorSetCount) {
2816 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
Jeff Bolz6ae39612019-10-11 20:57:36 -05002817 auto layout = GetDescriptorSetLayoutShared(p_alloc_info->pSetLayouts[i]);
Jeff Bolzfdf96072018-04-10 14:32:18 -05002818 if (count_allocate_info->pDescriptorCounts[i] > layout->GetDescriptorCountFromBinding(layout->GetMaxBinding())) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002819 skip |= LogError(device, "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfo-pSetLayouts-03046",
2820 "pDescriptorCounts[%d] = (%d), binding's descriptorCount = (%d)", i,
2821 count_allocate_info->pDescriptorCounts[i],
2822 layout->GetDescriptorCountFromBinding(layout->GetMaxBinding()));
Jeff Bolzfdf96072018-04-10 14:32:18 -05002823 }
2824 }
2825 }
2826 }
2827
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002828 return skip;
Tobin Ehlisee471462016-05-26 11:21:59 -06002829}
John Zulauf48a6a702017-12-22 17:14:54 -07002830
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05002831const BindingReqMap &cvdescriptorset::PrefilterBindRequestMap::FilteredMap(const CMD_BUFFER_STATE &cb_state,
2832 const PIPELINE_STATE &pipeline) {
John Zulauffbf3c202019-07-17 14:57:14 -06002833 if (IsManyDescriptors()) {
Karl Schultz7090a052020-11-10 08:54:21 -07002834 filtered_map_.reset(new BindingReqMap);
John Zulauffbf3c202019-07-17 14:57:14 -06002835 descriptor_set_.FilterBindingReqs(cb_state, pipeline, orig_map_, filtered_map_.get());
2836 return *filtered_map_;
John Zulauf48a6a702017-12-22 17:14:54 -07002837 }
John Zulauffbf3c202019-07-17 14:57:14 -06002838 return orig_map_;
Artem Kharytoniuk2456f992018-01-12 14:17:41 +01002839}
John Zulauf4a015c92019-06-04 09:50:05 -06002840
2841// Starting at offset descriptor of given binding, parse over update_count
2842// descriptor updates and verify that for any binding boundaries that are crossed, the next binding(s) are all consistent
2843// Consistency means that their type, stage flags, and whether or not they use immutable samplers matches
2844// If so, return true. If not, fill in error_msg and return false
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002845bool cvdescriptorset::VerifyUpdateConsistency(debug_report_data *report_data,
2846 DescriptorSetLayout::ConstBindingIterator current_binding, uint32_t offset,
John Zulauf4a015c92019-06-04 09:50:05 -06002847 uint32_t update_count, const char *type, const VkDescriptorSet set,
2848 std::string *error_msg) {
locke-lunarge46b7782019-09-10 01:44:20 -06002849 bool pass = true;
John Zulauf4a015c92019-06-04 09:50:05 -06002850 // Verify consecutive bindings match (if needed)
2851 auto orig_binding = current_binding;
locke-lunarge46b7782019-09-10 01:44:20 -06002852
2853 while (pass && update_count) {
2854 // First, it's legal to offset beyond your own binding so handle that case
2855 if (offset > 0) {
2856 const auto &index_range = current_binding.GetGlobalIndexRange();
2857 // index_range.start + offset is which descriptor is needed to update. If it > index_range.end, it means the descriptor
2858 // isn't in this binding, maybe in next binding.
2859 if ((index_range.start + offset) >= index_range.end) {
2860 // Advance to next binding, decrement offset by binding size
2861 offset -= current_binding.GetDescriptorCount();
2862 ++current_binding;
2863 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
2864 if (!orig_binding.IsConsistent(current_binding)) {
2865 pass = false;
2866 }
2867 continue;
John Zulauf4a015c92019-06-04 09:50:05 -06002868 }
John Zulauf4a015c92019-06-04 09:50:05 -06002869 }
locke-lunarge46b7782019-09-10 01:44:20 -06002870
2871 update_count -= std::min(update_count, current_binding.GetDescriptorCount() - offset);
2872 if (update_count) {
2873 // Starting offset is beyond the current binding. Check consistency, update counters and advance to the next binding,
2874 // looking for the start point. All bindings (even those skipped) must be consistent with the update and with the
2875 // original binding.
2876 offset = 0;
2877 ++current_binding;
2878 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
2879 if (!orig_binding.IsConsistent(current_binding)) {
2880 pass = false;
2881 }
2882 }
John Zulauf4a015c92019-06-04 09:50:05 -06002883 }
locke-lunarge46b7782019-09-10 01:44:20 -06002884
2885 if (!pass) {
2886 std::stringstream error_str;
2887 error_str << "Attempting " << type;
2888 if (current_binding.Layout()->IsPushDescriptor()) {
2889 error_str << " push descriptors";
2890 } else {
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002891 error_str << " descriptor set " << report_data->FormatHandle(set);
locke-lunarge46b7782019-09-10 01:44:20 -06002892 }
2893 error_str << " binding #" << orig_binding.Binding() << " with #" << update_count
2894 << " descriptors being updated but this update oversteps the bounds of this binding and the next binding is "
2895 "not consistent with current binding so this update is invalid.";
2896 *error_msg = error_str.str();
2897 }
2898 return pass;
John Zulauf4a015c92019-06-04 09:50:05 -06002899}
John Zulauf4956fff2019-06-04 16:54:38 -06002900
2901// Validate the state for a given write update but don't actually perform the update
2902// 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 -06002903bool CoreChecks::ValidateWriteUpdate(const DescriptorSet *dest_set, const VkWriteDescriptorSet *update, const char *func_name,
John Zulaufbd9b3412019-08-22 17:16:11 -06002904 std::string *error_code, std::string *error_msg) const {
Jeff Bolz6aad1742019-10-16 11:10:09 -05002905 const auto dest_layout = dest_set->GetLayout().get();
John Zulauf4956fff2019-06-04 16:54:38 -06002906
2907 // Verify dst layout still valid
Jeff Bolz6ae39612019-10-11 20:57:36 -05002908 if (dest_layout->destroyed) {
John Zulauf4956fff2019-06-04 16:54:38 -06002909 *error_code = "VUID-VkWriteDescriptorSet-dstSet-00320";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002910 std::ostringstream str;
2911 str << "Cannot call " << func_name << " to perform write update on " << dest_set->StringifySetAndLayout()
2912 << " which has been destroyed";
2913 *error_msg = str.str();
John Zulauf4956fff2019-06-04 16:54:38 -06002914 return false;
2915 }
2916 // Verify dst binding exists
2917 if (!dest_layout->HasBinding(update->dstBinding)) {
2918 *error_code = "VUID-VkWriteDescriptorSet-dstBinding-00315";
2919 std::stringstream error_str;
2920 error_str << dest_set->StringifySetAndLayout() << " does not have binding " << update->dstBinding;
2921 *error_msg = error_str.str();
2922 return false;
2923 }
2924
Jeff Bolz6aad1742019-10-16 11:10:09 -05002925 DescriptorSetLayout::ConstBindingIterator dest(dest_layout, update->dstBinding);
John Zulauf4956fff2019-06-04 16:54:38 -06002926 // Make sure binding isn't empty
2927 if (0 == dest.GetDescriptorCount()) {
2928 *error_code = "VUID-VkWriteDescriptorSet-dstBinding-00316";
2929 std::stringstream error_str;
2930 error_str << dest_set->StringifySetAndLayout() << " cannot updated binding " << update->dstBinding
2931 << " that has 0 descriptors";
2932 *error_msg = error_str.str();
2933 return false;
2934 }
2935
2936 // Verify idle ds
2937 if (dest_set->in_use.load() && !(dest.GetDescriptorBindingFlags() & (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT |
2938 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) {
2939 // TODO : Re-using Free Idle error code, need write update idle error code
2940 *error_code = "VUID-vkFreeDescriptorSets-pDescriptorSets-00309";
2941 std::stringstream error_str;
2942 error_str << "Cannot call " << func_name << " to perform write update on " << dest_set->StringifySetAndLayout()
2943 << " that is in use by a command buffer";
2944 *error_msg = error_str.str();
2945 return false;
2946 }
2947 // We know that binding is valid, verify update and do update on each descriptor
2948 auto start_idx = dest.GetGlobalIndexRange().start + update->dstArrayElement;
2949 auto type = dest.GetType();
2950 if (type != update->descriptorType) {
2951 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00319";
2952 std::stringstream error_str;
2953 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
2954 << " with type " << string_VkDescriptorType(type) << " but update type is "
2955 << string_VkDescriptorType(update->descriptorType);
2956 *error_msg = error_str.str();
2957 return false;
2958 }
John Zulauf4956fff2019-06-04 16:54:38 -06002959 if (type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
2960 if ((update->dstArrayElement % 4) != 0) {
2961 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02219";
2962 std::stringstream error_str;
2963 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
2964 << " with "
2965 << "dstArrayElement " << update->dstArrayElement << " not a multiple of 4";
2966 *error_msg = error_str.str();
2967 return false;
2968 }
2969 if ((update->descriptorCount % 4) != 0) {
2970 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02220";
2971 std::stringstream error_str;
2972 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
2973 << " with "
2974 << "descriptorCount " << update->descriptorCount << " not a multiple of 4";
2975 *error_msg = error_str.str();
2976 return false;
2977 }
2978 const auto *write_inline_info = lvl_find_in_chain<VkWriteDescriptorSetInlineUniformBlockEXT>(update->pNext);
2979 if (!write_inline_info || write_inline_info->dataSize != update->descriptorCount) {
2980 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02221";
2981 std::stringstream error_str;
2982 if (!write_inline_info) {
2983 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #"
2984 << update->dstBinding << " with "
2985 << "VkWriteDescriptorSetInlineUniformBlockEXT missing";
2986 } else {
2987 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #"
2988 << update->dstBinding << " with "
2989 << "VkWriteDescriptorSetInlineUniformBlockEXT dataSize " << write_inline_info->dataSize
2990 << " not equal to "
2991 << "VkWriteDescriptorSet descriptorCount " << update->descriptorCount;
2992 }
2993 *error_msg = error_str.str();
2994 return false;
2995 }
2996 // This error is probably unreachable due to the previous two errors
2997 if (write_inline_info && (write_inline_info->dataSize % 4) != 0) {
2998 *error_code = "VUID-VkWriteDescriptorSetInlineUniformBlockEXT-dataSize-02222";
2999 std::stringstream error_str;
3000 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3001 << " with "
3002 << "VkWriteDescriptorSetInlineUniformBlockEXT dataSize " << write_inline_info->dataSize
3003 << " not a multiple of 4";
3004 *error_msg = error_str.str();
3005 return false;
3006 }
3007 }
sfricke-samsung941d48b2020-02-10 00:20:01 -08003008 // Verify all bindings update share identical properties across all items
3009 if (update->descriptorCount > 0) {
3010 // Save first binding information and error if something different is found
3011 DescriptorSetLayout::ConstBindingIterator current_binding(dest_layout, update->dstBinding);
3012 VkShaderStageFlags stageFlags = current_binding.GetStageFlags();
3013 VkDescriptorType descriptorType = current_binding.GetType();
3014 bool immutableSamplers = (current_binding.GetImmutableSamplerPtr() == nullptr);
Jeff Bolz9198e882020-03-18 13:03:30 -05003015 uint32_t dstArrayElement = update->dstArrayElement;
sfricke-samsung941d48b2020-02-10 00:20:01 -08003016
Jeff Bolz9198e882020-03-18 13:03:30 -05003017 for (uint32_t i = 0; i < update->descriptorCount;) {
sfricke-samsung941d48b2020-02-10 00:20:01 -08003018 if (current_binding.AtEnd() == true) {
3019 break; // prevents setting error here if bindings don't exist
3020 }
3021
3022 // Check for consistent stageFlags and descriptorType
3023 if ((current_binding.GetStageFlags() != stageFlags) || (current_binding.GetType() != descriptorType)) {
3024 *error_code = "VUID-VkWriteDescriptorSet-descriptorCount-00317";
3025 std::stringstream error_str;
3026 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3027 << current_binding.GetIndex() << " (" << i << " from dstBinding offset)"
3028 << " with a different stageFlag and/or descriptorType from previous bindings."
3029 << " All bindings must have consecutive stageFlag and/or descriptorType across a VkWriteDescriptorSet";
3030 *error_msg = error_str.str();
3031 return false;
3032 }
3033 // Check if all immutableSamplers or not
3034 if ((current_binding.GetImmutableSamplerPtr() == nullptr) != immutableSamplers) {
3035 *error_code = "VUID-VkWriteDescriptorSet-descriptorCount-00318";
3036 std::stringstream error_str;
3037 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3038 << current_binding.GetIndex() << " (" << i << " from dstBinding offset)"
3039 << " with a different usage of immutable samplers from previous bindings."
3040 << " All bindings must have all or none usage of immutable samplers across a VkWriteDescriptorSet";
3041 *error_msg = error_str.str();
3042 return false;
3043 }
Jeff Bolz9198e882020-03-18 13:03:30 -05003044
3045 // Skip the remaining descriptors for this binding, and move to the next binding
3046 i += (current_binding.GetDescriptorCount() - dstArrayElement);
3047 dstArrayElement = 0;
sfricke-samsung941d48b2020-02-10 00:20:01 -08003048 ++current_binding;
3049 }
3050 }
3051
John Zulauf4956fff2019-06-04 16:54:38 -06003052 // Verify consecutive bindings match (if needed)
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003053 if (!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(dest_layout, update->dstBinding),
John Zulauf4956fff2019-06-04 16:54:38 -06003054 update->dstArrayElement, update->descriptorCount, "write update to", dest_set->GetSet(),
3055 error_msg)) {
3056 // TODO : Should break out "consecutive binding updates" language into valid usage statements
3057 *error_code = "VUID-VkWriteDescriptorSet-dstArrayElement-00321";
3058 return false;
3059 }
Tony-LunarG1f79c952020-10-27 15:55:51 -06003060 // Verify write to variable descriptor
3061 if (dest_set->IsVariableDescriptorCount(update->dstBinding)) {
3062 if ((update->dstArrayElement + update->descriptorCount) > dest_set->GetVariableDescriptorCount()) {
3063 std::stringstream error_str;
3064 *error_code = "VUID-VkWriteDescriptorSet-dstArrayElement-00321";
3065 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3066 << update->dstBinding << " array element " << update->dstArrayElement << " with " << update->descriptorCount
3067 << " writes but variable descriptor size is " << dest_set->GetVariableDescriptorCount();
3068 *error_msg = error_str.str();
3069 return false;
3070 }
3071 }
John Zulauf4956fff2019-06-04 16:54:38 -06003072 // Update is within bounds and consistent so last step is to validate update contents
John Zulauf459939f2019-06-04 16:49:35 -06003073 if (!VerifyWriteUpdateContents(dest_set, update, start_idx, func_name, error_code, error_msg)) {
John Zulauf4956fff2019-06-04 16:54:38 -06003074 std::stringstream error_str;
3075 error_str << "Write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3076 << " failed with error message: " << error_msg->c_str();
3077 *error_msg = error_str.str();
3078 return false;
3079 }
3080 // All checks passed, update is clean
3081 return true;
3082}
John Zulaufadb3f542019-06-04 17:01:00 -06003083
3084// Verify that the contents of the update are ok, but don't perform actual update
John Zulaufc93c4252019-06-25 09:19:49 -06003085bool CoreChecks::VerifyWriteUpdateContents(const DescriptorSet *dest_set, const VkWriteDescriptorSet *update, const uint32_t index,
John Zulaufbd9b3412019-08-22 17:16:11 -06003086 const char *func_name, std::string *error_code, std::string *error_msg) const {
John Zulaufc93c4252019-06-25 09:19:49 -06003087 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
3088 using SamplerDescriptor = cvdescriptorset::SamplerDescriptor;
3089
John Zulaufadb3f542019-06-04 17:01:00 -06003090 switch (update->descriptorType) {
3091 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
3092 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3093 // Validate image
3094 auto image_view = update->pImageInfo[di].imageView;
3095 auto image_layout = update->pImageInfo[di].imageLayout;
Mark Lobodzinski3ca937b2020-02-14 14:56:06 -07003096 auto sampler = update->pImageInfo[di].sampler;
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003097 auto iv_state = GetImageViewState(image_view);
Raul Tambre9115c252020-02-05 15:02:48 +02003098 ImageSamplerDescriptor *desc = (ImageSamplerDescriptor *)dest_set->GetDescriptorFromGlobalIndex(index + di);
Jeff Bolz165818a2020-05-08 11:19:03 -05003099 if (image_view) {
3100 auto image_state = iv_state->image_state.get();
3101 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, func_name, error_code, error_msg)) {
3102 std::stringstream error_str;
3103 error_str << "Attempted write update to combined image sampler descriptor failed due to: "
3104 << error_msg->c_str();
3105 *error_msg = error_str.str();
3106 return false;
3107 }
3108 if (device_extensions.vk_khr_sampler_ycbcr_conversion) {
3109 if (desc->IsImmutableSampler()) {
3110 auto sampler_state = GetSamplerState(desc->GetSampler());
3111 if (iv_state && sampler_state) {
3112 if (iv_state->samplerConversion != sampler_state->samplerConversion) {
3113 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-01948";
3114 std::stringstream error_str;
3115 error_str
3116 << "Attempted write update to combined image sampler and image view and sampler ycbcr "
3117 "conversions are not identical, sampler: "
3118 << report_data->FormatHandle(desc->GetSampler())
3119 << " image view: " << report_data->FormatHandle(iv_state->image_view) << ".";
3120 *error_msg = error_str.str();
3121 return false;
3122 }
3123 }
3124 } else {
3125 if (iv_state && (iv_state->samplerConversion != VK_NULL_HANDLE)) {
3126 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02738";
John Zulaufadb3f542019-06-04 17:01:00 -06003127 std::stringstream error_str;
Jeff Bolz165818a2020-05-08 11:19:03 -05003128 error_str << "Because dstSet (" << report_data->FormatHandle(update->dstSet)
3129 << ") is bound to image view (" << report_data->FormatHandle(iv_state->image_view)
3130 << ") that includes a YCBCR conversion, it must have been allocated with a layout that "
3131 "includes an immutable sampler.";
John Zulaufadb3f542019-06-04 17:01:00 -06003132 *error_msg = error_str.str();
3133 return false;
3134 }
3135 }
Jeff Bolz165818a2020-05-08 11:19:03 -05003136 }
John Baumanda8abff2020-10-19 21:25:21 +00003137 // If there is an immutable sampler then |sampler| isn't used, so the following VU does not apply.
3138 if (sampler && !desc->IsImmutableSampler() && FormatIsMultiplane(image_state->createInfo.format)) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003139 // multiplane formats must be created with mutable format bit
3140 if (0 == (image_state->createInfo.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) {
3141 *error_code = "VUID-VkDescriptorImageInfo-sampler-01564";
John Zulaufadb3f542019-06-04 17:01:00 -06003142 std::stringstream error_str;
Jeff Bolz165818a2020-05-08 11:19:03 -05003143 error_str << "image " << report_data->FormatHandle(image_state->image)
3144 << " combined image sampler is a multi-planar "
3145 << "format and was not was not created with the VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT";
John Zulaufadb3f542019-06-04 17:01:00 -06003146 *error_msg = error_str.str();
3147 return false;
3148 }
Jeff Bolz165818a2020-05-08 11:19:03 -05003149 // image view need aspect mask for only the planes supported of format
3150 VkImageAspectFlags legal_aspect_flags = (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT);
3151 legal_aspect_flags |=
3152 (FormatPlaneCount(image_state->createInfo.format) == 3) ? VK_IMAGE_ASPECT_PLANE_2_BIT : 0;
3153 if (0 != (iv_state->create_info.subresourceRange.aspectMask & (~legal_aspect_flags))) {
3154 *error_code = "VUID-VkDescriptorImageInfo-sampler-01564";
3155 std::stringstream error_str;
3156 error_str << "image " << report_data->FormatHandle(image_state->image)
3157 << " combined image sampler is a multi-planar "
3158 << "format and " << report_data->FormatHandle(iv_state->image_view)
3159 << " aspectMask must only include " << string_VkImageAspectFlags(legal_aspect_flags);
3160 *error_msg = error_str.str();
3161 return false;
3162 }
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003163 }
3164 }
John Zulaufadb3f542019-06-04 17:01:00 -06003165 }
3166 }
Mark Lobodzinskiac727772020-01-08 10:47:30 -07003167 // Fall through
John Zulaufadb3f542019-06-04 17:01:00 -06003168 case VK_DESCRIPTOR_TYPE_SAMPLER: {
3169 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3170 SamplerDescriptor *desc = (SamplerDescriptor *)dest_set->GetDescriptorFromGlobalIndex(index + di);
3171 if (!desc->IsImmutableSampler()) {
John Zulaufc93c4252019-06-25 09:19:49 -06003172 if (!ValidateSampler(update->pImageInfo[di].sampler)) {
John Zulaufadb3f542019-06-04 17:01:00 -06003173 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
3174 std::stringstream error_str;
3175 error_str << "Attempted write update to sampler descriptor with invalid sampler: "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003176 << report_data->FormatHandle(update->pImageInfo[di].sampler) << ".";
John Zulaufadb3f542019-06-04 17:01:00 -06003177 *error_msg = error_str.str();
3178 return false;
3179 }
Mark Lobodzinskiac727772020-01-08 10:47:30 -07003180 } else if (update->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003181 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02752";
3182 std::stringstream error_str;
3183 error_str << "Attempted write update to an immutable sampler descriptor.";
3184 *error_msg = error_str.str();
3185 return false;
John Zulaufadb3f542019-06-04 17:01:00 -06003186 }
3187 }
3188 break;
3189 }
3190 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
3191 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
3192 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
3193 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3194 auto image_view = update->pImageInfo[di].imageView;
3195 auto image_layout = update->pImageInfo[di].imageLayout;
Jeff Bolz165818a2020-05-08 11:19:03 -05003196 if (image_view) {
3197 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, func_name, error_code, error_msg)) {
3198 std::stringstream error_str;
3199 error_str << "Attempted write update to image descriptor failed due to: " << error_msg->c_str();
3200 *error_msg = error_str.str();
3201 return false;
3202 }
John Zulaufadb3f542019-06-04 17:01:00 -06003203 }
3204 }
3205 break;
3206 }
3207 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
3208 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
3209 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3210 auto buffer_view = update->pTexelBufferView[di];
Jeff Bolz165818a2020-05-08 11:19:03 -05003211 if (buffer_view) {
3212 auto bv_state = GetBufferViewState(buffer_view);
3213 if (!bv_state) {
3214 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
3215 std::stringstream error_str;
3216 error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: "
3217 << report_data->FormatHandle(buffer_view);
3218 *error_msg = error_str.str();
3219 return false;
3220 }
3221 auto buffer = bv_state->create_info.buffer;
3222 auto buffer_state = GetBufferState(buffer);
3223 // Verify that buffer underlying the view hasn't been destroyed prematurely
3224 if (!buffer_state) {
3225 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
3226 std::stringstream error_str;
3227 error_str << "Attempted write update to texel buffer descriptor failed because underlying buffer ("
3228 << report_data->FormatHandle(buffer) << ") has been destroyed: " << error_msg->c_str();
3229 *error_msg = error_str.str();
3230 return false;
3231 } else if (!cvdescriptorset::ValidateBufferUsage(report_data, buffer_state, update->descriptorType, error_code,
3232 error_msg)) {
3233 std::stringstream error_str;
3234 error_str << "Attempted write update to texel buffer descriptor failed due to: " << error_msg->c_str();
3235 *error_msg = error_str.str();
3236 return false;
3237 }
John Zulaufadb3f542019-06-04 17:01:00 -06003238 }
3239 }
3240 break;
3241 }
3242 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
3243 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
3244 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
3245 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
3246 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003247 if (update->pBufferInfo[di].buffer) {
3248 if (!ValidateBufferUpdate(update->pBufferInfo + di, update->descriptorType, func_name, error_code, error_msg)) {
3249 std::stringstream error_str;
3250 error_str << "Attempted write update to buffer descriptor failed due to: " << error_msg->c_str();
3251 *error_msg = error_str.str();
3252 return false;
3253 }
John Zulaufadb3f542019-06-04 17:01:00 -06003254 }
3255 }
3256 break;
3257 }
3258 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
3259 break;
Jeff Bolz95176d02020-04-01 00:36:16 -05003260 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: {
3261 const auto *accInfo = lvl_find_in_chain<VkWriteDescriptorSetAccelerationStructureKHR>(update->pNext);
3262 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3263 if (!ValidateAccelerationStructureUpdate(accInfo->pAccelerationStructures[di], func_name, error_code, error_msg)) {
3264 std::stringstream error_str;
3265 error_str << "Attempted write update to acceleration structure descriptor failed due to: "
3266 << error_msg->c_str();
3267 *error_msg = error_str.str();
3268 return false;
3269 }
3270 }
3271
3272 } break;
John Zulaufadb3f542019-06-04 17:01:00 -06003273 default:
3274 assert(0); // We've already verified update type so should never get here
3275 break;
3276 }
3277 // All checks passed so update contents are good
3278 return true;
3279}