blob: 28be871252436aa4a6c1082c6c1476cec42b7603 [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 {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700182 const static IndexRange k_invalid_range = {0xFFFFFFFF, 0xFFFFFFFF};
183 if (index >= binding_flags_.size()) return k_invalid_range;
John Zulauf7705bfc2019-06-10 09:52:04 -0600184 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),
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700593 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
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700598 descriptors_.reserve(layout_->GetTotalDescriptorCount());
599 descriptor_store_.resize(layout_->GetTotalDescriptorCount());
John Zulaufe4850d42019-12-30 16:10:55 -0700600 auto free_descriptor = descriptor_store_.data();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700601 for (uint32_t i = 0; i < layout_->GetBindingCount(); ++i) {
602 auto type = 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: {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700605 auto immut_sampler = layout_->GetImmutableSamplerPtrFromIndex(i);
606 for (uint32_t di = 0; di < 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
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700611 } else {
John Zulaufe4850d42019-12-30 16:10:55 -0700612 descriptors_.emplace_back(new ((free_descriptor++)->Sampler()) SamplerDescriptor(state_data, nullptr));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700613 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700614 }
615 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600616 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700617 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700618 auto immut = layout_->GetImmutableSamplerPtrFromIndex(i);
619 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
Tobin Ehlis082c7512017-05-08 11:24:57 -0600620 if (immut) {
John Zulaufe4850d42019-12-30 16:10:55 -0700621 descriptors_.emplace_back(new ((free_descriptor++)->ImageSampler())
622 ImageSamplerDescriptor(state_data, immut + di));
Tobin Ehlis082c7512017-05-08 11:24:57 -0600623 some_update_ = true; // Immutable samplers are updated at creation
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700624 } else {
John Zulaufe4850d42019-12-30 16:10:55 -0700625 descriptors_.emplace_back(new ((free_descriptor++)->ImageSampler())
626 ImageSamplerDescriptor(state_data, nullptr));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700627 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700628 }
629 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600630 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700631 // ImageDescriptors
632 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
633 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
634 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700635 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700636 descriptors_.emplace_back(new ((free_descriptor++)->Image()) ImageDescriptor(type));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700637 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700638 break;
639 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
640 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700641 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700642 descriptors_.emplace_back(new ((free_descriptor++)->Texel()) TexelDescriptor(type));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700643 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700644 break;
645 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
646 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
647 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
648 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700649 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700650 descriptors_.emplace_back(new ((free_descriptor++)->Buffer()) BufferDescriptor(type));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700651 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700652 break;
Jeff Bolze54ae892018-09-08 12:16:29 -0500653 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700654 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700655 descriptors_.emplace_back(new ((free_descriptor++)->InlineUniform()) InlineUniformDescriptor(type));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700656 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500657 break;
Eric Werness30127fd2018-10-31 21:01:03 -0700658 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
sourav parmarcd5fb182020-07-17 12:58:44 -0700659 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700660 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700661 descriptors_.emplace_back(new ((free_descriptor++)->AccelerationStructure())
662 AccelerationStructureDescriptor(type));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700663 }
Jeff Bolzfbe51582018-09-13 10:01:35 -0500664 break;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700665 default:
666 assert(0); // Bad descriptor type specified
667 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600668 }
669 }
670}
Tobin Ehlis56a30942016-05-19 08:00:00 -0600671
Jeff Bolz41a1ced2019-10-11 11:40:49 -0500672cvdescriptorset::DescriptorSet::~DescriptorSet() {}
Chris Forbes57989132016-07-26 17:06:10 +1200673
Shannon McPhersonc06c33d2018-06-28 17:21:12 -0600674static std::string StringDescriptorReqViewType(descriptor_req req) {
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700675 std::string result("");
Mark Lobodzinski29f451a2020-02-10 16:15:30 -0700676 for (unsigned i = 0; i <= VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; i++) {
Chris Forbes57989132016-07-26 17:06:10 +1200677 if (req & (1 << i)) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700678 if (result.size()) result += ", ";
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700679 result += string_VkImageViewType(VkImageViewType(i));
Chris Forbes57989132016-07-26 17:06:10 +1200680 }
681 }
682
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700683 if (!result.size()) result = "(none)";
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700684
685 return result;
Chris Forbes57989132016-07-26 17:06:10 +1200686}
687
Chris Forbesda01e8d2018-08-27 15:36:57 -0700688static char const *StringDescriptorReqComponentType(descriptor_req req) {
689 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_SINT) return "SINT";
690 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_UINT) return "UINT";
691 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT) return "FLOAT";
692 return "(none)";
693}
694
Jeff Bolz6cede832019-08-09 23:30:39 -0500695unsigned DescriptorRequirementsBitsFromFormat(VkFormat fmt) {
Chris Forbesda01e8d2018-08-27 15:36:57 -0700696 if (FormatIsSInt(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_SINT;
697 if (FormatIsUInt(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_UINT;
698 if (FormatIsDepthAndStencil(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT | DESCRIPTOR_REQ_COMPONENT_TYPE_UINT;
699 if (fmt == VK_FORMAT_UNDEFINED) return 0;
700 // everything else -- UNORM/SNORM/FLOAT/USCALED/SSCALED is all float in the shader.
701 return DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT;
702}
703
Tobin Ehlis3066db62016-08-22 08:12:23 -0600704// 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 -0600705// This includes validating that all descriptors in the given bindings are updated,
706// that any update buffers are valid, and that any dynamic offsets are within the bounds of their buffers.
707// Return true if state is acceptable, or false and write an error message into error string
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600708bool CoreChecks::ValidateDrawState(const DescriptorSet *descriptor_set, const BindingReqMap &bindings,
709 const std::vector<uint32_t> &dynamic_offsets, const CMD_BUFFER_STATE *cb_node,
locke-lunargfc78e932020-11-19 17:06:24 -0700710 const std::vector<IMAGE_VIEW_STATE *> *attachments, const std::vector<SUBPASS_INFO> &subpasses,
711 const char *caller, const DrawDispatchVuid &vuids) const {
Tony-LunarGace473a2020-05-06 12:48:04 -0600712 bool result = false;
locke-lunarg540b2252020-08-03 13:23:36 -0600713 VkFramebuffer framebuffer = cb_node->activeFramebuffer ? cb_node->activeFramebuffer->framebuffer : VK_NULL_HANDLE;
Chris Forbesc7090a82016-07-25 18:10:41 +1200714 for (auto binding_pair : bindings) {
715 auto binding = binding_pair.first;
John Zulauf382e1912019-06-10 15:27:44 -0600716 DescriptorSetLayout::ConstBindingIterator binding_it(descriptor_set->GetLayout().get(), binding);
717 if (binding_it.AtEnd()) { // End at construction is the condition for an invalid binding.
Tony-LunarGace473a2020-05-06 12:48:04 -0600718 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600719 result |= LogError(set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -0600720 "%s encountered the following validation error at %s time: Attempting to "
721 "validate DrawState for binding #%u which is an invalid binding for this descriptor set.",
722 report_data->FormatHandle(set).c_str(), caller, binding);
723 return result;
Tobin Ehlis58c59582016-06-21 12:34:33 -0600724 }
Jeff Bolz6cede832019-08-09 23:30:39 -0500725
726 if (binding_it.GetDescriptorBindingFlags() &
727 (VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT)) {
728 // Can't validate the descriptor because it may not have been updated,
729 // or the view could have been destroyed
730 continue;
731 }
locke-lunargfc78e932020-11-19 17:06:24 -0700732 result |= ValidateDescriptorSetBindingData(cb_node, descriptor_set, dynamic_offsets, binding_pair, framebuffer, attachments,
733 subpasses, caller, vuids);
unknown3087a642019-09-26 17:21:05 -0600734 }
Tony-LunarGace473a2020-05-06 12:48:04 -0600735 return result;
unknown3087a642019-09-26 17:21:05 -0600736}
Jeff Bolz6cede832019-08-09 23:30:39 -0500737
locke-lunargb8be8222020-10-20 00:34:37 -0600738bool CoreChecks::ValidateDescriptorSetBindingData(const CMD_BUFFER_STATE *cb_node, const DescriptorSet *descriptor_set,
739 const std::vector<uint32_t> &dynamic_offsets,
Karl Schultz7090a052020-11-10 08:54:21 -0700740 std::pair<const uint32_t, DescriptorRequirement> &binding_info,
Mark Lobodzinski85ebd402020-12-03 12:56:07 -0700741 VkFramebuffer framebuffer, const std::vector<IMAGE_VIEW_STATE *> *attachments,
742 const std::vector<SUBPASS_INFO> &subpasses, const char *caller,
743 const DrawDispatchVuid &vuids) const {
unknown3087a642019-09-26 17:21:05 -0600744 using DescriptorClass = cvdescriptorset::DescriptorClass;
745 using BufferDescriptor = cvdescriptorset::BufferDescriptor;
746 using ImageDescriptor = cvdescriptorset::ImageDescriptor;
747 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
748 using SamplerDescriptor = cvdescriptorset::SamplerDescriptor;
749 using TexelDescriptor = cvdescriptorset::TexelDescriptor;
Jeff Bolz95176d02020-04-01 00:36:16 -0500750 using AccelerationStructureDescriptor = cvdescriptorset::AccelerationStructureDescriptor;
locke-lunarg36045992020-08-20 16:54:37 -0600751 const auto reqs = binding_info.second.reqs;
752 const auto binding = binding_info.first;
unknown3087a642019-09-26 17:21:05 -0600753 DescriptorSetLayout::ConstBindingIterator binding_it(descriptor_set->GetLayout().get(), binding);
754 {
John Zulauf382e1912019-06-10 15:27:44 -0600755 // Copy the range, the end range is subject to update based on variable length descriptor arrays.
756 cvdescriptorset::IndexRange index_range = binding_it.GetGlobalIndexRange();
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700757 auto array_idx = 0; // Track array idx if we're dealing with array descriptors
Jeff Bolzfdf96072018-04-10 14:32:18 -0500758
John Zulauf382e1912019-06-10 15:27:44 -0600759 if (binding_it.IsVariableDescriptorCount()) {
Jeff Bolzfdf96072018-04-10 14:32:18 -0500760 // Only validate the first N descriptors if it uses variable_count
John Zulauf382e1912019-06-10 15:27:44 -0600761 index_range.end = index_range.start + descriptor_set->GetVariableDescriptorCount();
Jeff Bolzfdf96072018-04-10 14:32:18 -0500762 }
763
John Zulaufc483f442017-12-15 14:02:06 -0700764 for (uint32_t i = index_range.start; i < index_range.end; ++i, ++array_idx) {
Lockeb994adf2019-03-29 23:52:31 -0600765 uint32_t index = i - index_range.start;
John Zulauf382e1912019-06-10 15:27:44 -0600766 const auto *descriptor = descriptor_set->GetDescriptorFromGlobalIndex(i);
Lockeb994adf2019-03-29 23:52:31 -0600767
Jeff Bolz6cede832019-08-09 23:30:39 -0500768 if (descriptor->GetClass() == DescriptorClass::InlineUniform) {
769 // Can't validate the descriptor because it may not have been updated.
Jeff Bolzfdf96072018-04-10 14:32:18 -0500770 continue;
John Zulauf382e1912019-06-10 15:27:44 -0600771 } else if (!descriptor->updated) {
Tony-LunarGace473a2020-05-06 12:48:04 -0600772 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600773 return LogError(set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -0600774 "%s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
775 " index %" PRIu32
776 " is being used in draw but has never been updated via vkUpdateDescriptorSets() or a similar call.",
777 report_data->FormatHandle(set).c_str(), caller, binding, index);
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700778 } else {
John Zulauf382e1912019-06-10 15:27:44 -0600779 auto descriptor_class = descriptor->GetClass();
John Zulaufc93c4252019-06-25 09:19:49 -0600780 if (descriptor_class == DescriptorClass::GeneralBuffer) {
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700781 // Verify that buffers are valid
John Zulauf382e1912019-06-10 15:27:44 -0600782 auto buffer = static_cast<const BufferDescriptor *>(descriptor)->GetBuffer();
Jeff Bolzfaffeb32019-10-04 12:47:16 -0500783 auto buffer_node = static_cast<const BufferDescriptor *>(descriptor)->GetBufferState();
Karl Schultz76d16a42020-11-11 05:05:33 -0700784 if ((!buffer_node && !enabled_features.robustness2_features.nullDescriptor) ||
785 (buffer_node && buffer_node->destroyed)) {
786 auto set = descriptor_set->GetSet();
787 return LogError(set, vuids.descriptor_valid,
788 "%s encountered the following validation error at %s time: Descriptor in "
789 "binding #%" PRIu32 " index %" PRIu32
790 " is using buffer %s that is invalid or has been destroyed.",
791 report_data->FormatHandle(set).c_str(), caller, binding, index,
792 report_data->FormatHandle(buffer).c_str());
793 }
Jeff Bolz165818a2020-05-08 11:19:03 -0500794 if (buffer) {
Karl Schultz76d16a42020-11-11 05:05:33 -0700795 if (!buffer_node->sparse) {
Jeff Bolz165818a2020-05-08 11:19:03 -0500796 for (auto mem_binding : buffer_node->GetBoundMemory()) {
797 if (mem_binding->destroyed) {
798 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600799 return LogError(set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500800 "%s encountered the following validation error at %s time: Descriptor in "
801 "binding #%" PRIu32 " index %" PRIu32
802 " is uses buffer %s that references invalid memory %s.",
803 report_data->FormatHandle(set).c_str(), caller, binding, index,
804 report_data->FormatHandle(buffer).c_str(),
805 report_data->FormatHandle(mem_binding->mem).c_str());
806 }
Tobin Ehlisc8266452017-04-07 12:20:30 -0600807 }
808 }
Jeff Bolz165818a2020-05-08 11:19:03 -0500809 if (descriptor->IsDynamic()) {
810 // Validate that dynamic offsets are within the buffer
811 auto buffer_size = buffer_node->createInfo.size;
812 auto range = static_cast<const BufferDescriptor *>(descriptor)->GetRange();
813 auto desc_offset = static_cast<const BufferDescriptor *>(descriptor)->GetOffset();
814 auto dyn_offset = dynamic_offsets[binding_it.GetDynamicOffsetIndex() + array_idx];
815 if (VK_WHOLE_SIZE == range) {
816 if ((dyn_offset + desc_offset) > buffer_size) {
817 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600818 return LogError(set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500819 "%s encountered the following validation error at %s time: Descriptor in "
820 "binding #%" PRIu32 " index %" PRIu32
821 " is using buffer %s with update range of VK_WHOLE_SIZE has dynamic offset "
822 "%" PRIu32 " combined with offset %" PRIu64
823 " that oversteps the buffer size of %" PRIu64 ".",
824 report_data->FormatHandle(set).c_str(), caller, binding, index,
825 report_data->FormatHandle(buffer).c_str(), dyn_offset, desc_offset,
826 buffer_size);
827 }
828 } else {
829 if ((dyn_offset + desc_offset + range) > buffer_size) {
830 auto set = descriptor_set->GetSet();
831 return LogError(
locke-lunarg1328e8e2020-08-20 12:40:08 -0600832 set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500833 "%s encountered the following validation error at %s time: "
834 "Descriptor in binding #%" PRIu32 " index %" PRIu32
835 " is uses buffer %s with dynamic offset %" PRIu32 " combined with offset %" PRIu64
836 " and range %" PRIu64 " that oversteps the buffer size of %" PRIu64 ".",
837 report_data->FormatHandle(set).c_str(), caller, binding, index,
838 report_data->FormatHandle(buffer).c_str(), dyn_offset, desc_offset, range, buffer_size);
839 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700840 }
841 }
locke-lunarg351c9d82020-10-23 14:43:21 -0600842 if (enabled_features.core11.protectedMemory == VK_TRUE) {
843 if (ValidateProtectedBuffer(cb_node, buffer_node, caller, vuids.unprotected_command_buffer,
844 "Buffer is in a descriptorSet")) {
845 return true;
846 }
847 if (binding_info.second.is_writable &&
848 ValidateUnprotectedBuffer(cb_node, buffer_node, caller, vuids.protected_command_buffer,
849 "Buffer is in a descriptorSet")) {
850 return true;
851 }
852 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700853 }
John Zulaufc93c4252019-06-25 09:19:49 -0600854 } else if (descriptor_class == DescriptorClass::ImageSampler || descriptor_class == DescriptorClass::Image) {
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700855 VkImageView image_view;
856 VkImageLayout image_layout;
Jeff Bolzfaffeb32019-10-04 12:47:16 -0500857 const IMAGE_VIEW_STATE *image_view_state;
locke-lunarg4e1e4632020-10-26 01:52:19 -0600858 std::vector<const SAMPLER_STATE *> sampler_states;
locke-lunarg36045992020-08-20 16:54:37 -0600859
John Zulaufc93c4252019-06-25 09:19:49 -0600860 if (descriptor_class == DescriptorClass::ImageSampler) {
locke-lunarg36045992020-08-20 16:54:37 -0600861 const ImageSamplerDescriptor *image_descriptor = static_cast<const ImageSamplerDescriptor *>(descriptor);
862 image_view = image_descriptor->GetImageView();
863 image_view_state = image_descriptor->GetImageViewState();
864 image_layout = image_descriptor->GetImageLayout();
locke-lunarg4e1e4632020-10-26 01:52:19 -0600865 sampler_states.emplace_back(image_descriptor->GetSamplerState());
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700866 } else {
locke-lunarg36045992020-08-20 16:54:37 -0600867 const ImageDescriptor *image_descriptor = static_cast<const ImageDescriptor *>(descriptor);
868 image_view = image_descriptor->GetImageView();
869 image_view_state = image_descriptor->GetImageViewState();
870 image_layout = image_descriptor->GetImageLayout();
locke-lunarg4e1e4632020-10-26 01:52:19 -0600871
872 if (binding_info.second.samplers_used_by_image.size() > index) {
873 for (auto &sampler : binding_info.second.samplers_used_by_image[index]) {
874 if (sampler.second) {
875 const auto *sampler_state =
876 static_cast<const cvdescriptorset::SamplerDescriptor *>(sampler.second)->GetSamplerState();
877 if (sampler_state) sampler_states.emplace_back(sampler_state);
878 }
879 }
880 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700881 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700882
Karl Schultz76d16a42020-11-11 05:05:33 -0700883 if ((!image_view_state && !enabled_features.robustness2_features.nullDescriptor) ||
884 (image_view_state && image_view_state->destroyed)) {
885 // Image view must have been destroyed since initial update. Could potentially flag the descriptor
886 // as "invalid" (updated = false) at DestroyImageView() time and detect this error at bind time
887
888 auto set = descriptor_set->GetSet();
889 return LogError(set, vuids.descriptor_valid,
890 "%s encountered the following validation error at %s time: Descriptor in "
891 "binding #%" PRIu32 " index %" PRIu32
892 " is using imageView %s that is invalid or has been destroyed.",
893 report_data->FormatHandle(set).c_str(), caller, binding, index,
894 report_data->FormatHandle(image_view).c_str());
895 }
Jeff Bolz165818a2020-05-08 11:19:03 -0500896 if (image_view) {
Jeff Bolz165818a2020-05-08 11:19:03 -0500897 const auto &image_view_ci = image_view_state->create_info;
locke-lunarg4e1e4632020-10-26 01:52:19 -0600898 const auto *image_state = image_view_state->image_state.get();
899
Jeff Bolz165818a2020-05-08 11:19:03 -0500900 if (reqs & DESCRIPTOR_REQ_ALL_VIEW_TYPE_BITS) {
901 if (~reqs & (1 << image_view_ci.viewType)) {
902 auto set = descriptor_set->GetSet();
903 return LogError(
locke-lunarg1328e8e2020-08-20 12:40:08 -0600904 set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500905 "%s encountered the following validation error at %s time: Descriptor "
906 "in binding #%" PRIu32 " index %" PRIu32 " requires an image view of type %s but got %s.",
907 report_data->FormatHandle(set).c_str(), caller, binding, index,
908 StringDescriptorReqViewType(reqs).c_str(), string_VkImageViewType(image_view_ci.viewType));
909 }
910
911 if (!(reqs & image_view_state->descriptor_format_bits)) {
912 // bad component type
913 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600914 return LogError(set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500915 "%s encountered the following validation error at %s time: Descriptor in binding "
916 "#%" PRIu32 " index %" PRIu32
917 " requires %s component type, but bound descriptor format is %s.",
918 report_data->FormatHandle(set).c_str(), caller, binding, index,
919 StringDescriptorReqComponentType(reqs), string_VkFormat(image_view_ci.format));
920 }
921 }
922
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -0600923 if (!disabled[image_layout_validation]) {
Jeff Bolz165818a2020-05-08 11:19:03 -0500924 auto image_node = image_view_state->image_state.get();
925 assert(image_node);
926 // Verify Image Layout
927 // No "invalid layout" VUID required for this call, since the optimal_layout parameter is UNDEFINED.
928 bool hit_error = false;
929 VerifyImageLayout(cb_node, image_node, image_view_state->normalized_subresource_range,
930 image_view_ci.subresourceRange.aspectMask, image_layout, VK_IMAGE_LAYOUT_UNDEFINED,
931 caller, kVUIDUndefined, "VUID-VkDescriptorImageInfo-imageLayout-00344", &hit_error);
932 if (hit_error) {
933 auto set = descriptor_set->GetSet();
934 return LogError(
locke-lunarg1328e8e2020-08-20 12:40:08 -0600935 set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500936 "%s encountered the following validation error at %s time: Image layout specified "
937 "at vkUpdateDescriptorSet* or vkCmdPushDescriptorSet* time "
938 "doesn't match actual image layout at time descriptor is used. See previous error callback for "
939 "specific details.",
940 report_data->FormatHandle(set).c_str(), caller);
941 }
942 }
943
944 // Verify Sample counts
945 if ((reqs & DESCRIPTOR_REQ_SINGLE_SAMPLE) && image_view_state->samples != VK_SAMPLE_COUNT_1_BIT) {
946 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600947 return LogError(set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500948 "%s encountered the following validation error at %s time: Descriptor in "
949 "binding #%" PRIu32 " index %" PRIu32
950 " requires bound image to have VK_SAMPLE_COUNT_1_BIT but got %s.",
951 report_data->FormatHandle(set).c_str(), caller, binding, index,
952 string_VkSampleCountFlagBits(image_view_state->samples));
953 }
954 if ((reqs & DESCRIPTOR_REQ_MULTI_SAMPLE) && image_view_state->samples == VK_SAMPLE_COUNT_1_BIT) {
Tony-LunarGace473a2020-05-06 12:48:04 -0600955 auto set = descriptor_set->GetSet();
956 return LogError(
locke-lunarg1328e8e2020-08-20 12:40:08 -0600957 set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -0500958 "%s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
959 " index %" PRIu32 " requires bound image to have multiple samples, but got VK_SAMPLE_COUNT_1_BIT.",
960 report_data->FormatHandle(set).c_str(), caller, binding, index);
Jeff Bolz6cede832019-08-09 23:30:39 -0500961 }
locke-lunarg25b6c352020-08-06 17:44:18 -0600962
locke-lunarge4bf18f2020-08-21 10:23:08 -0600963 const VkDescriptorType descriptor_type = descriptor_set->GetTypeFromBinding(binding);
locke-lunarg540b2252020-08-03 13:23:36 -0600964
locke-lunarg25b6c352020-08-06 17:44:18 -0600965 // Verify VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
966 if ((reqs & DESCRIPTOR_REQ_VIEW_ATOMIC_OPERATION) &&
locke-lunarg540b2252020-08-03 13:23:36 -0600967 (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) &&
locke-lunarg25b6c352020-08-06 17:44:18 -0600968 !(image_view_state->format_features & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)) {
969 auto set = descriptor_set->GetSet();
970 LogObjectList objlist(set);
971 objlist.add(image_view);
972 return LogError(
973 objlist, vuids.imageview_atomic,
974 "%s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
975 " index %" PRIu32
976 ", %s, format %s, doesn't "
977 "contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT.",
978 report_data->FormatHandle(set).c_str(), caller, binding, index,
979 report_data->FormatHandle(image_view).c_str(), string_VkFormat(image_view_ci.format));
980 }
locke-lunarg540b2252020-08-03 13:23:36 -0600981
982 // Verify if attachments are used in DescriptorSet
locke-lunargfc78e932020-11-19 17:06:24 -0700983 if (attachments && attachments->size() > 0 && (descriptor_type != VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
locke-lunarg5e1bdde2020-11-16 17:08:44 -0700984 bool ds_aspect = (image_view_state->create_info.subresourceRange.aspectMask &
985 (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
986 ? true
987 : false;
locke-lunargfc78e932020-11-19 17:06:24 -0700988 uint32_t att_index = 0;
989 for (const auto &view_state : *attachments) {
990 if (!subpasses[att_index].used || !view_state || view_state->destroyed) {
locke-lunarg1ae57d62020-11-18 10:49:19 -0700991 continue;
992 }
locke-lunargfc78e932020-11-19 17:06:24 -0700993 if (ds_aspect && subpasses[att_index].usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
locke-lunarg5e1bdde2020-11-16 17:08:44 -0700994 if ((image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ||
995 image_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
996 image_layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL) &&
locke-lunargfc78e932020-11-19 17:06:24 -0700997 (subpasses[att_index].layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ||
998 subpasses[att_index].layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
999 subpasses[att_index].layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL)) {
locke-lunarg5e1bdde2020-11-16 17:08:44 -07001000 continue;
1001 }
1002 if ((image_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL &&
locke-lunargfc78e932020-11-19 17:06:24 -07001003 subpasses[att_index].layout ==
1004 VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL) ||
1005 (subpasses[att_index].layout ==
1006 VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL &&
locke-lunarg5e1bdde2020-11-16 17:08:44 -07001007 image_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)) {
1008 continue;
1009 }
1010 }
locke-lunargfc78e932020-11-19 17:06:24 -07001011 if (view_state->image_view == image_view) {
locke-lunarg540b2252020-08-03 13:23:36 -06001012 auto set = descriptor_set->GetSet();
1013 LogObjectList objlist(set);
1014 objlist.add(image_view);
1015 objlist.add(framebuffer);
1016 return LogError(objlist, vuids.image_subresources,
1017 "%s encountered the following validation error at %s time: %s is used in "
1018 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1019 " and %s attachment # %" PRIu32 ".",
1020 report_data->FormatHandle(set).c_str(), caller,
1021 report_data->FormatHandle(image_view).c_str(), binding, index,
locke-lunargfc78e932020-11-19 17:06:24 -07001022 report_data->FormatHandle(framebuffer).c_str(), att_index);
1023 } else {
1024 if (image_view_state->OverlapSubresource(*view_state)) {
locke-lunarg540b2252020-08-03 13:23:36 -06001025 auto set = descriptor_set->GetSet();
1026 LogObjectList objlist(set);
1027 objlist.add(image_view);
1028 objlist.add(framebuffer);
locke-lunargfc78e932020-11-19 17:06:24 -07001029 objlist.add(view_state->image_view);
locke-lunarg540b2252020-08-03 13:23:36 -06001030 return LogError(
1031 objlist, vuids.image_subresources,
1032 "%s encountered the following validation error at %s time: Image subresources of %s in "
1033 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1034 " and %s in %s attachment # %" PRIu32 " overlap.",
1035 report_data->FormatHandle(set).c_str(), caller,
1036 report_data->FormatHandle(image_view).c_str(), binding, index,
locke-lunargfc78e932020-11-19 17:06:24 -07001037 report_data->FormatHandle(view_state->image_view).c_str(),
1038 report_data->FormatHandle(framebuffer).c_str(), att_index);
locke-lunarg540b2252020-08-03 13:23:36 -06001039 }
1040 }
locke-lunargfc78e932020-11-19 17:06:24 -07001041 ++att_index;
locke-lunarg540b2252020-08-03 13:23:36 -06001042 }
locke-lunarg351c9d82020-10-23 14:43:21 -06001043 if (enabled_features.core11.protectedMemory == VK_TRUE) {
1044 if (ValidateProtectedImage(cb_node, image_view_state->image_state.get(), caller,
1045 vuids.unprotected_command_buffer, "Image is in a descriptorSet")) {
1046 return true;
1047 }
1048 if (binding_info.second.is_writable &&
1049 ValidateUnprotectedImage(cb_node, image_view_state->image_state.get(), caller,
1050 vuids.protected_command_buffer, "Image is in a descriptorSet")) {
1051 return true;
1052 }
1053 }
locke-lunarg540b2252020-08-03 13:23:36 -06001054 }
locke-lunarg36045992020-08-20 16:54:37 -06001055
locke-lunarg4e1e4632020-10-26 01:52:19 -06001056 for (const auto *sampler_state : sampler_states) {
1057 if (!sampler_state || sampler_state->destroyed) {
1058 continue;
1059 }
locke-lunarg654a9052020-10-13 16:28:42 -06001060
locke-lunarg4e1e4632020-10-26 01:52:19 -06001061 // TODO: Validate 04015 for DescriptorClass::PlainSampler
1062 if ((sampler_state->createInfo.borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT ||
1063 sampler_state->createInfo.borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT) &&
1064 (sampler_state->customCreateInfo.format == VK_FORMAT_UNDEFINED)) {
1065 if (image_view_state->create_info.format == VK_FORMAT_B4G4R4A4_UNORM_PACK16 ||
1066 image_view_state->create_info.format == VK_FORMAT_B5G6R5_UNORM_PACK16 ||
1067 image_view_state->create_info.format == VK_FORMAT_B5G5R5A1_UNORM_PACK16) {
1068 auto set = descriptor_set->GetSet();
1069 LogObjectList objlist(set);
1070 objlist.add(sampler_state->sampler);
1071 objlist.add(image_view_state->image_view);
1072 return LogError(objlist, "VUID-VkSamplerCustomBorderColorCreateInfoEXT-format-04015",
1073 "%s encountered the following validation error at %s time: Sampler %s in "
1074 "binding #%" PRIu32 " index %" PRIu32
1075 " has a custom border color with format = VK_FORMAT_UNDEFINED and is used to "
1076 "sample an image view %s with format %s",
1077 report_data->FormatHandle(set).c_str(), caller,
1078 report_data->FormatHandle(sampler_state->sampler).c_str(), binding, index,
1079 report_data->FormatHandle(image_view_state->image_view).c_str(),
1080 string_VkFormat(image_view_state->create_info.format));
1081 }
1082 }
1083 VkFilter sampler_mag_filter = sampler_state->createInfo.magFilter;
1084 VkFilter sampler_min_filter = sampler_state->createInfo.minFilter;
1085 VkBool32 sampler_compare_enable = sampler_state->createInfo.compareEnable;
1086 if ((sampler_mag_filter == VK_FILTER_LINEAR || sampler_min_filter == VK_FILTER_LINEAR) &&
1087 (sampler_compare_enable == VK_FALSE) &&
1088 !(image_view_state->format_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
locke-lunarg36045992020-08-20 16:54:37 -06001089 auto set = descriptor_set->GetSet();
1090 LogObjectList objlist(set);
locke-lunarg36045992020-08-20 16:54:37 -06001091 objlist.add(sampler_state->sampler);
locke-lunarg4e1e4632020-10-26 01:52:19 -06001092 objlist.add(image_view_state->image_view);
1093 return LogError(objlist, vuids.linear_sampler,
1094 "sampler (%s) in descriptor set (%s) "
1095 "is set to use VK_FILTER_LINEAR, then image view's (%s"
1096 ") format (%s) MUST "
1097 "contain VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT in its format features.",
1098 report_data->FormatHandle(sampler_state->sampler).c_str(),
1099 report_data->FormatHandle(set).c_str(),
1100 report_data->FormatHandle(image_view_state->image_view).c_str(),
1101 string_VkFormat(image_view_state->create_info.format));
locke-lunarg36045992020-08-20 16:54:37 -06001102 }
locke-lunarg9939d4b2020-10-26 20:11:08 -06001103 if (sampler_mag_filter == VK_FILTER_CUBIC_EXT || sampler_min_filter == VK_FILTER_CUBIC_EXT) {
1104 if (!(image_view_state->format_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) {
1105 auto set = descriptor_set->GetSet();
1106 LogObjectList objlist(set);
1107 objlist.add(sampler_state->sampler);
1108 objlist.add(image_view_state->image_view);
1109 return LogError(objlist, vuids.cubic_sampler,
Mark Lobodzinski45034452020-11-30 16:56:48 -07001110 "sampler (%s) in descriptor set (%s) is set to use VK_FILTER_CUBIC_EXT, then "
1111 "image view's (%s) format (%s) MUST contain "
1112 "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT in its format features.",
locke-lunarg9939d4b2020-10-26 20:11:08 -06001113 report_data->FormatHandle(sampler_state->sampler).c_str(),
1114 report_data->FormatHandle(set).c_str(),
1115 report_data->FormatHandle(image_view_state->image_view).c_str(),
1116 string_VkFormat(image_view_state->create_info.format));
1117 }
1118
Mark Lobodzinski45034452020-11-30 16:56:48 -07001119 if (IsExtEnabled(device_extensions.vk_ext_filter_cubic)) {
1120 const auto reduction_mode_info =
1121 lvl_find_in_chain<VkSamplerReductionModeCreateInfo>(sampler_state->createInfo.pNext);
1122 if (reduction_mode_info &&
1123 (reduction_mode_info->reductionMode == VK_SAMPLER_REDUCTION_MODE_MIN ||
1124 reduction_mode_info->reductionMode == VK_SAMPLER_REDUCTION_MODE_MAX) &&
1125 !image_view_state->filter_cubic_props.filterCubicMinmax) {
1126 auto set = descriptor_set->GetSet();
1127 LogObjectList objlist(set);
1128 objlist.add(sampler_state->sampler);
1129 objlist.add(image_view_state->image_view);
1130 return LogError(
1131 objlist, vuids.filter_cubic_min_max,
1132 "sampler (%s) in descriptor set (%s) is set to use VK_FILTER_CUBIC_EXT & %s, "
1133 "but image view (%s) doesn't support filterCubicMinmax.",
1134 report_data->FormatHandle(sampler_state->sampler).c_str(),
1135 string_VkSamplerReductionMode(reduction_mode_info->reductionMode),
1136 report_data->FormatHandle(set).c_str(),
1137 report_data->FormatHandle(image_view_state->image_view).c_str());
1138 }
1139
1140 if (!image_view_state->filter_cubic_props.filterCubic) {
1141 auto set = descriptor_set->GetSet();
1142 LogObjectList objlist(set);
1143 objlist.add(sampler_state->sampler);
1144 objlist.add(image_view_state->image_view);
1145 return LogError(objlist, vuids.filter_cubic,
1146 "sampler (%s) in descriptor set (%s) is set to use VK_FILTER_CUBIC_EXT, "
1147 "but image view (%s) doesn't support filterCubic.",
1148 report_data->FormatHandle(sampler_state->sampler).c_str(),
1149 report_data->FormatHandle(set).c_str(),
1150 report_data->FormatHandle(image_view_state->image_view).c_str());
1151 }
locke-lunarg9939d4b2020-10-26 20:11:08 -06001152 }
1153
Mark Lobodzinski45034452020-11-30 16:56:48 -07001154 if (IsExtEnabled(device_extensions.vk_img_filter_cubic)) {
1155 if (image_view_state->create_info.viewType &
1156 (VK_IMAGE_VIEW_TYPE_3D | VK_IMAGE_VIEW_TYPE_CUBE | VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)) {
1157 auto set = descriptor_set->GetSet();
1158 LogObjectList objlist(set);
1159 objlist.add(sampler_state->sampler);
1160 objlist.add(image_view_state->image_view);
1161 return LogError(objlist, vuids.img_filter_cubic,
1162 "sampler (%s) in descriptor set (%s) "
1163 "is set to use VK_FILTER_CUBIC_EXT while the VK_IMG_filter_cubic extension "
1164 "is enabled, but image view (%s) has an invalid imageViewType (%s).",
1165 report_data->FormatHandle(sampler_state->sampler).c_str(),
1166 report_data->FormatHandle(set).c_str(),
1167 report_data->FormatHandle(image_view_state->image_view).c_str(),
1168 string_VkImageViewType(image_view_state->create_info.viewType));
1169 }
locke-lunarg9939d4b2020-10-26 20:11:08 -06001170 }
locke-lunarg654a9052020-10-13 16:28:42 -06001171 }
1172
locke-lunarg4e1e4632020-10-26 01:52:19 -06001173 if ((image_state->createInfo.flags & VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV) &&
1174 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ||
1175 sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ||
1176 sampler_state->createInfo.addressModeW != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)) {
1177 std::string address_mode_letter =
locke-lunarg9939d4b2020-10-26 20:11:08 -06001178 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1179 ? "U"
1180 : (sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE) ? "V"
1181 : "W";
locke-lunarg4e1e4632020-10-26 01:52:19 -06001182 VkSamplerAddressMode address_mode =
1183 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1184 ? sampler_state->createInfo.addressModeU
locke-lunarg9939d4b2020-10-26 20:11:08 -06001185 : (sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1186 ? sampler_state->createInfo.addressModeV
1187 : sampler_state->createInfo.addressModeW;
locke-lunargae2a43c2020-09-22 17:21:57 -06001188 auto set = descriptor_set->GetSet();
1189 LogObjectList objlist(set);
locke-lunargae2a43c2020-09-22 17:21:57 -06001190 objlist.add(sampler_state->sampler);
locke-lunarg4e1e4632020-10-26 01:52:19 -06001191 objlist.add(image_state->image);
1192 objlist.add(image_view_state->image_view);
1193 return LogError(objlist, vuids.corner_sampled_address_mode,
1194 "image (%s) in image view (%s) in descriptor set (%s) is created with flag "
1195 "VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV and can only be sampled using "
1196 "VK_SAMPLER_ADDRESS_MODE_CLAMP_EDGE, but sampler (%s) has "
1197 "createInfo.addressMode%s set to %s.",
1198 report_data->FormatHandle(image_state->image).c_str(),
1199 report_data->FormatHandle(image_view_state->image_view).c_str(),
1200 report_data->FormatHandle(set).c_str(),
1201 report_data->FormatHandle(sampler_state->sampler).c_str(),
1202 address_mode_letter.c_str(), string_VkSamplerAddressMode(address_mode));
1203 }
1204
1205 // UnnormalizedCoordinates sampler validations
1206 if (sampler_state->createInfo.unnormalizedCoordinates) {
1207 // If ImageView is used by a unnormalizedCoordinates sampler, it needs to check ImageView type
1208 if (image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_3D ||
1209 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
1210 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY ||
1211 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY ||
1212 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
1213 auto set = descriptor_set->GetSet();
1214 LogObjectList objlist(set);
1215 objlist.add(image_view);
1216 objlist.add(sampler_state->sampler);
1217 return LogError(objlist, vuids.sampler_imageview_type,
1218 "%s encountered the following validation error at %s time: %s, type: %s in "
1219 "Descriptor in binding #%" PRIu32 " index %" PRIu32 "is used by %s.",
1220 report_data->FormatHandle(set).c_str(), caller,
1221 report_data->FormatHandle(image_view).c_str(),
1222 string_VkImageViewType(image_view_ci.viewType), binding, index,
1223 report_data->FormatHandle(sampler_state->sampler).c_str());
1224 }
1225
1226 // sampler must not be used with any of the SPIR-V OpImageSample* or OpImageSparseSample*
1227 // instructions with ImplicitLod, Dref or Proj in their name
1228 if (reqs & DESCRIPTOR_REQ_SAMPLER_IMPLICITLOD_DREF_PROJ) {
1229 auto set = descriptor_set->GetSet();
1230 LogObjectList objlist(set);
1231 objlist.add(image_view);
1232 objlist.add(sampler_state->sampler);
1233 return LogError(objlist, vuids.sampler_implicitLod_dref_proj,
1234 "%s encountered the following validation error at %s time: %s in "
1235 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1236 " is used by %s that uses invalid operator.",
1237 report_data->FormatHandle(set).c_str(), caller,
1238 report_data->FormatHandle(image_view).c_str(), binding, index,
1239 report_data->FormatHandle(sampler_state->sampler).c_str());
1240 }
1241
1242 // sampler must not be used with any of the SPIR-V OpImageSample* or OpImageSparseSample*
1243 // instructions that includes a LOD bias or any offset values
1244 if (reqs & DESCRIPTOR_REQ_SAMPLER_BIAS_OFFSET) {
1245 auto set = descriptor_set->GetSet();
1246 LogObjectList objlist(set);
1247 objlist.add(image_view);
1248 objlist.add(sampler_state->sampler);
1249 return LogError(objlist, vuids.sampler_bias_offset,
1250 "%s encountered the following validation error at %s time: %s in "
1251 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1252 " is used by %s that uses invalid bias or offset operator.",
1253 report_data->FormatHandle(set).c_str(), caller,
1254 report_data->FormatHandle(image_view).c_str(), binding, index,
1255 report_data->FormatHandle(sampler_state->sampler).c_str());
1256 }
locke-lunargae2a43c2020-09-22 17:21:57 -06001257 }
locke-lunarg36045992020-08-20 16:54:37 -06001258 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -07001259 }
John Zulaufc93c4252019-06-25 09:19:49 -06001260 } else if (descriptor_class == DescriptorClass::TexelBuffer) {
John Zulauf382e1912019-06-10 15:27:44 -06001261 auto texel_buffer = static_cast<const TexelDescriptor *>(descriptor);
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001262 auto buffer_view = texel_buffer->GetBufferView();
1263 auto buffer_view_state = texel_buffer->GetBufferViewState();
Chris Forbese92dd1d2019-01-21 15:58:57 -08001264
Karl Schultz76d16a42020-11-11 05:05:33 -07001265 if ((!buffer_view_state && !enabled_features.robustness2_features.nullDescriptor) ||
1266 (buffer_view_state && buffer_view_state->destroyed)) {
1267 auto set = descriptor_set->GetSet();
1268 return LogError(set, vuids.descriptor_valid,
1269 "%s encountered the following validation error at %s time: Descriptor in "
1270 "binding #%" PRIu32 " index %" PRIu32
1271 " is using bufferView %s that is invalid or has been destroyed.",
1272 report_data->FormatHandle(set).c_str(), caller, binding, index,
1273 report_data->FormatHandle(buffer_view).c_str());
1274 }
Jeff Bolz165818a2020-05-08 11:19:03 -05001275 if (buffer_view) {
Jeff Bolz165818a2020-05-08 11:19:03 -05001276 auto buffer = buffer_view_state->create_info.buffer;
1277 auto buffer_state = buffer_view_state->buffer_state.get();
1278 if (buffer_state->destroyed) {
1279 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -06001280 return LogError(set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -05001281 "%s encountered the following validation error at %s time: Descriptor in "
1282 "binding #%" PRIu32 " index %" PRIu32 " is using buffer %s that has been destroyed.",
1283 report_data->FormatHandle(set).c_str(), caller, binding, index,
1284 report_data->FormatHandle(buffer).c_str());
1285 }
1286 auto format_bits = DescriptorRequirementsBitsFromFormat(buffer_view_state->create_info.format);
Chris Forbese92dd1d2019-01-21 15:58:57 -08001287
Jeff Bolz165818a2020-05-08 11:19:03 -05001288 if (!(reqs & format_bits)) {
1289 // bad component type
1290 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -06001291 return LogError(set, vuids.descriptor_valid,
Jeff Bolz165818a2020-05-08 11:19:03 -05001292 "%s encountered the following validation error at %s time: Descriptor in "
1293 "binding #%" PRIu32 " index %" PRIu32
1294 " requires %s component type, but bound descriptor format is %s.",
1295 report_data->FormatHandle(set).c_str(), caller, binding, index,
1296 StringDescriptorReqComponentType(reqs),
1297 string_VkFormat(buffer_view_state->create_info.format));
1298 }
locke-lunarg25b6c352020-08-06 17:44:18 -06001299
1300 // Verify VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT
1301 if ((reqs & DESCRIPTOR_REQ_VIEW_ATOMIC_OPERATION) &&
locke-lunarge4bf18f2020-08-21 10:23:08 -06001302 (descriptor_set->GetTypeFromBinding(binding) == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) &&
locke-lunarg25b6c352020-08-06 17:44:18 -06001303 !(buffer_view_state->format_features & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT)) {
1304 auto set = descriptor_set->GetSet();
1305 LogObjectList objlist(set);
1306 objlist.add(buffer_view);
1307 return LogError(
1308 objlist, "UNASSIGNED-None-MismatchAtomicBufferFeature",
1309 "%s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
1310 " index %" PRIu32
1311 ", %s, format %s, doesn't "
1312 "contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT.",
1313 report_data->FormatHandle(set).c_str(), caller, binding, index,
1314 report_data->FormatHandle(buffer_view).c_str(),
1315 string_VkFormat(buffer_view_state->create_info.format));
1316 }
locke-lunarg351c9d82020-10-23 14:43:21 -06001317 if (enabled_features.core11.protectedMemory == VK_TRUE) {
1318 if (ValidateProtectedBuffer(cb_node, buffer_view_state->buffer_state.get(), caller,
1319 vuids.unprotected_command_buffer, "Buffer is in a descriptorSet")) {
1320 return true;
1321 }
1322 if (binding_info.second.is_writable &&
1323 ValidateUnprotectedBuffer(cb_node, buffer_view_state->buffer_state.get(), caller,
1324 vuids.protected_command_buffer, "Buffer is in a descriptorSet")) {
1325 return true;
1326 }
1327 }
Chris Forbese92dd1d2019-01-21 15:58:57 -08001328 }
Jeff Bolz95176d02020-04-01 00:36:16 -05001329 } else if (descriptor_class == DescriptorClass::AccelerationStructure) {
1330 // Verify that acceleration structures are valid
sourav parmarcd51aa82020-11-17 12:04:52 -08001331 bool is_khr = (*((cvdescriptorset::AccelerationStructureDescriptor *)(descriptor))).is_khr();
1332 if (is_khr) {
1333 auto acc = static_cast<const AccelerationStructureDescriptor *>(descriptor)->GetAccelerationStructure();
1334 auto acc_node =
1335 static_cast<const AccelerationStructureDescriptor *>(descriptor)->GetAccelerationStructureStateKHR();
1336 if (!acc_node || acc_node->destroyed) {
1337 if (acc != VK_NULL_HANDLE || !enabled_features.robustness2_features.nullDescriptor) {
1338 auto set = descriptor_set->GetSet();
1339 return LogError(
1340 set, vuids.descriptor_valid,
1341 "%s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
1342 " index %" PRIu32 " is using acceleration structure %s that is invalid or has been destroyed.",
1343 report_data->FormatHandle(set).c_str(), caller, binding, index,
1344 report_data->FormatHandle(acc).c_str());
1345 }
1346 } else {
1347 for (auto mem_binding : acc_node->GetBoundMemory()) {
1348 if (mem_binding->destroyed) {
1349 auto set = descriptor_set->GetSet();
1350 return LogError(set, vuids.descriptor_valid,
1351 "%s encountered the following validation error at %s time: Descriptor in "
1352 "binding #%" PRIu32 " index %" PRIu32
1353 " is using acceleration structure %s that references invalid memory %s.",
1354 report_data->FormatHandle(set).c_str(), caller, binding, index,
1355 report_data->FormatHandle(acc).c_str(),
1356 report_data->FormatHandle(mem_binding->mem).c_str());
1357 }
1358 }
Ricardo Garcia3f145ae2020-10-28 16:53:35 +01001359 }
Jeff Bolz95176d02020-04-01 00:36:16 -05001360 } else {
sourav parmarcd51aa82020-11-17 12:04:52 -08001361 auto acc = static_cast<const AccelerationStructureDescriptor *>(descriptor)->GetAccelerationStructureNV();
1362 auto acc_node =
1363 static_cast<const AccelerationStructureDescriptor *>(descriptor)->GetAccelerationStructureStateNV();
1364 if (!acc_node || acc_node->destroyed) {
1365 if (acc != VK_NULL_HANDLE || !enabled_features.robustness2_features.nullDescriptor) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001366 auto set = descriptor_set->GetSet();
sourav parmarcd51aa82020-11-17 12:04:52 -08001367 return LogError(
1368 set, vuids.descriptor_valid,
1369 "%s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
1370 " index %" PRIu32 " is using acceleration structure %s that is invalid or has been destroyed.",
1371 report_data->FormatHandle(set).c_str(), caller, binding, index,
1372 report_data->FormatHandle(acc).c_str());
1373 }
1374 } else {
1375 for (auto mem_binding : acc_node->GetBoundMemory()) {
1376 if (mem_binding->destroyed) {
1377 auto set = descriptor_set->GetSet();
1378 return LogError(set, vuids.descriptor_valid,
1379 "%s encountered the following validation error at %s time: Descriptor in "
1380 "binding #%" PRIu32 " index %" PRIu32
1381 " is using acceleration structure %s that references invalid memory %s.",
1382 report_data->FormatHandle(set).c_str(), caller, binding, index,
1383 report_data->FormatHandle(acc).c_str(),
1384 report_data->FormatHandle(mem_binding->mem).c_str());
1385 }
Jeff Bolz95176d02020-04-01 00:36:16 -05001386 }
1387 }
1388 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001389 }
locke-lunarg4e1e4632020-10-26 01:52:19 -06001390
1391 // If the validation is related to both of image and sampler,
locke-lunarg9939d4b2020-10-26 20:11:08 -06001392 // please leave it in (descriptor_class == DescriptorClass::ImageSampler || descriptor_class ==
1393 // DescriptorClass::Image) Here is to validate for only sampler.
John Zulaufc93c4252019-06-25 09:19:49 -06001394 if (descriptor_class == DescriptorClass::ImageSampler || descriptor_class == DescriptorClass::PlainSampler) {
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001395 // Verify Sampler still valid
1396 VkSampler sampler;
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001397 const SAMPLER_STATE *sampler_state;
John Zulaufc93c4252019-06-25 09:19:49 -06001398 if (descriptor_class == DescriptorClass::ImageSampler) {
John Zulauf382e1912019-06-10 15:27:44 -06001399 sampler = static_cast<const ImageSamplerDescriptor *>(descriptor)->GetSampler();
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001400 sampler_state = static_cast<const ImageSamplerDescriptor *>(descriptor)->GetSamplerState();
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001401 } else {
John Zulauf382e1912019-06-10 15:27:44 -06001402 sampler = static_cast<const SamplerDescriptor *>(descriptor)->GetSampler();
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001403 sampler_state = static_cast<const SamplerDescriptor *>(descriptor)->GetSamplerState();
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001404 }
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001405 if (!sampler_state || sampler_state->destroyed) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001406 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -06001407 return LogError(set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -06001408 "%s encountered the following validation error at %s time: Descriptor in "
1409 "binding #%" PRIu32 " index %" PRIu32
1410 " is using sampler %s that is invalid or has been destroyed.",
1411 report_data->FormatHandle(set).c_str(), caller, binding, index,
1412 report_data->FormatHandle(sampler).c_str());
Lockea223c102019-04-05 00:38:24 -06001413 } else {
John Zulauf382e1912019-06-10 15:27:44 -06001414 if (sampler_state->samplerConversion && !descriptor->IsImmutableSampler()) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001415 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -06001416 return LogError(set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -06001417 "%s encountered the following validation error at %s time: sampler (%s) "
1418 "in the descriptor set (%s) caontains a YCBCR conversion (%s), then the sampler MUST "
1419 "also exist as an immutable sampler.",
1420 report_data->FormatHandle(set).c_str(), caller,
1421 report_data->FormatHandle(sampler).c_str(),
1422 report_data->FormatHandle(descriptor_set->GetSet()).c_str(),
1423 report_data->FormatHandle(sampler_state->samplerConversion).c_str());
Lockea223c102019-04-05 00:38:24 -06001424 }
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001425 }
1426 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001427 }
1428 }
1429 }
Tony-LunarGace473a2020-05-06 12:48:04 -06001430 return false;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001431}
Chris Forbes57989132016-07-26 17:06:10 +12001432
Tobin Ehlis9906d9d2016-05-17 14:23:46 -06001433// Set is being deleted or updates so invalidate all bound cmd buffers
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001434void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers(ValidationStateTracker *state_data) {
1435 state_data->InvalidateCommandBuffers(cb_bindings, VulkanTypedHandle(set_, kVulkanObjectTypeDescriptorSet), /*unlink*/ false);
Tobin Ehlis9906d9d2016-05-17 14:23:46 -06001436}
John Zulauf1d27e0a2018-11-05 10:12:48 -07001437
1438// Loop through the write updates to do for a push descriptor set, ignoring dstSet
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001439void cvdescriptorset::DescriptorSet::PerformPushDescriptorsUpdate(ValidationStateTracker *dev_data, uint32_t write_count,
1440 const VkWriteDescriptorSet *p_wds) {
John Zulauf1d27e0a2018-11-05 10:12:48 -07001441 assert(IsPushDescriptor());
1442 for (uint32_t i = 0; i < write_count; i++) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001443 PerformWriteUpdate(dev_data, &p_wds[i]);
John Zulauf1d27e0a2018-11-05 10:12:48 -07001444 }
Jason Macnak83cfd582019-07-31 10:14:24 -07001445
1446 push_descriptor_set_writes.clear();
1447 push_descriptor_set_writes.reserve(static_cast<std::size_t>(write_count));
1448 for (uint32_t i = 0; i < write_count; i++) {
1449 push_descriptor_set_writes.push_back(safe_VkWriteDescriptorSet(&p_wds[i]));
1450 }
John Zulauf1d27e0a2018-11-05 10:12:48 -07001451}
1452
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001453// Perform write update in given update struct
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001454void cvdescriptorset::DescriptorSet::PerformWriteUpdate(ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update) {
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001455 // Perform update on a per-binding basis as consecutive updates roll over to next binding
1456 auto descriptors_remaining = update->descriptorCount;
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001457 auto offset = update->dstArrayElement;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001458 auto orig_binding = DescriptorSetLayout::ConstBindingIterator(layout_.get(), update->dstBinding);
locke-lunarge46b7782019-09-10 01:44:20 -06001459 auto current_binding = orig_binding;
1460
Tobin Ehlise16805c2017-08-09 09:10:37 -06001461 uint32_t update_index = 0;
locke-lunarge46b7782019-09-10 01:44:20 -06001462 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
1463 while (descriptors_remaining && orig_binding.IsConsistent(current_binding)) {
1464 const auto &index_range = current_binding.GetGlobalIndexRange();
1465 auto global_idx = index_range.start + offset;
1466 // global_idx is which descriptor is needed to update. If global_idx > index_range.end, it means the descriptor isn't in
1467 // this binding, maybe in next binding.
1468 if (global_idx >= index_range.end) {
1469 offset -= current_binding.GetDescriptorCount();
1470 ++current_binding;
1471 continue;
1472 }
1473
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001474 // Loop over the updates for a single binding at a time
locke-lunarge46b7782019-09-10 01:44:20 -06001475 uint32_t update_count = std::min(descriptors_remaining, current_binding.GetDescriptorCount() - offset);
Tobin Ehlise16805c2017-08-09 09:10:37 -06001476 for (uint32_t di = 0; di < update_count; ++di, ++update_index) {
John Zulaufd2c3dae2019-12-12 11:02:17 -07001477 descriptors_[global_idx + di]->WriteUpdate(state_data_, update, update_index);
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001478 }
1479 // Roll over to next binding in case of consecutive update
1480 descriptors_remaining -= update_count;
locke-lunarge46b7782019-09-10 01:44:20 -06001481 if (descriptors_remaining) {
1482 // Starting offset is beyond the current binding. Check consistency, update counters and advance to the next binding,
1483 // looking for the start point. All bindings (even those skipped) must be consistent with the update and with the
1484 // original binding.
1485 offset = 0;
1486 ++current_binding;
1487 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001488 }
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05001489 if (update->descriptorCount) {
1490 some_update_ = true;
1491 change_count_++;
1492 }
Tobin Ehlis56a30942016-05-19 08:00:00 -06001493
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001494 if (!(layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Jeff Bolzfdf96072018-04-10 14:32:18 -05001495 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001496 InvalidateBoundCmdBuffers(dev_data);
Jeff Bolzfdf96072018-04-10 14:32:18 -05001497 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001498}
Tobin Ehlis300888c2016-05-18 13:43:26 -06001499// Validate Copy update
John Zulaufc93c4252019-06-25 09:19:49 -06001500bool CoreChecks::ValidateCopyUpdate(const VkCopyDescriptorSet *update, const DescriptorSet *dst_set, const DescriptorSet *src_set,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05001501 const char *func_name, std::string *error_code, std::string *error_msg) const {
Jeff Bolz6aad1742019-10-16 11:10:09 -05001502 auto dst_layout = dst_set->GetLayout().get();
1503 auto src_layout = src_set->GetLayout().get();
John Zulaufd9435c32019-06-05 15:55:36 -06001504
John Zulauf5dfd45c2018-01-17 11:06:34 -07001505 // Verify dst layout still valid
Jeff Bolz6ae39612019-10-11 20:57:36 -05001506 if (dst_layout->destroyed) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001507 *error_code = "VUID-VkCopyDescriptorSet-dstSet-parameter";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06001508 std::ostringstream str;
1509 str << "Cannot call " << func_name << " to perform copy update on dstSet " << report_data->FormatHandle(dst_set->GetSet())
1510 << " created with destroyed " << report_data->FormatHandle(dst_layout->GetDescriptorSetLayout()) << ".";
1511 *error_msg = str.str();
John Zulauf5dfd45c2018-01-17 11:06:34 -07001512 return false;
1513 }
1514
1515 // Verify src layout still valid
Jeff Bolz6ae39612019-10-11 20:57:36 -05001516 if (src_layout->destroyed) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001517 *error_code = "VUID-VkCopyDescriptorSet-srcSet-parameter";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06001518 std::ostringstream str;
1519 str << "Cannot call " << func_name << " to perform copy update on dstSet " << report_data->FormatHandle(dst_set->GetSet())
1520 << " from srcSet " << report_data->FormatHandle(src_set->GetSet()) << " created with destroyed "
1521 << report_data->FormatHandle(src_layout->GetDescriptorSetLayout()) << ".";
1522 *error_msg = str.str();
John Zulauf5dfd45c2018-01-17 11:06:34 -07001523 return false;
1524 }
1525
John Zulaufd9435c32019-06-05 15:55:36 -06001526 if (!dst_layout->HasBinding(update->dstBinding)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001527 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-00347";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001528 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001529 error_str << "DescriptorSet " << report_data->FormatHandle(dst_set->GetSet())
1530 << " does not have copy update dest binding of " << update->dstBinding;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001531 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001532 return false;
1533 }
1534 if (!src_set->HasBinding(update->srcBinding)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001535 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-00345";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001536 std::stringstream error_str;
sourav parmarf4a78252020-04-10 13:04:21 -07001537 error_str << "DescriptorSet " << report_data->FormatHandle(src_set->GetSet())
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001538 << " does not have copy update src binding of " << update->srcBinding;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001539 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001540 return false;
1541 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001542 // Verify idle ds
John Zulaufd9435c32019-06-05 15:55:36 -06001543 if (dst_set->in_use.load() &&
1544 !(dst_layout->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Jeff Bolzfdf96072018-04-10 14:32:18 -05001545 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) {
1546 // TODO : Re-using Free Idle error code, need copy update idle error code
Dave Houlton00c154e2018-05-24 13:20:50 -06001547 *error_code = "VUID-vkFreeDescriptorSets-pDescriptorSets-00309";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001548 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001549 error_str << "Cannot call " << func_name << " to perform copy update on descriptor set "
1550 << report_data->FormatHandle(dst_set->GetSet()) << " that is in use by a command buffer";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001551 *error_msg = error_str.str();
1552 return false;
1553 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001554 // src & dst set bindings are valid
1555 // Check bounds of src & dst
John Zulaufc483f442017-12-15 14:02:06 -07001556 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001557 if ((src_start_idx + update->descriptorCount) > src_set->GetTotalDescriptorCount()) {
1558 // SRC update out of bounds
Dave Houlton00c154e2018-05-24 13:20:50 -06001559 *error_code = "VUID-VkCopyDescriptorSet-srcArrayElement-00346";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001560 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001561 error_str << "Attempting copy update from descriptorSet " << report_data->FormatHandle(update->srcSet) << " binding#"
1562 << update->srcBinding << " with offset index of "
1563 << src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start << " plus update array offset of "
1564 << update->srcArrayElement << " and update of " << update->descriptorCount
Tobin Ehlis1d81edd2016-11-21 09:50:49 -07001565 << " descriptors oversteps total number of descriptors in set: " << src_set->GetTotalDescriptorCount();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001566 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001567 return false;
1568 }
John Zulaufd9435c32019-06-05 15:55:36 -06001569 auto dst_start_idx = dst_layout->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
1570 if ((dst_start_idx + update->descriptorCount) > dst_layout->GetTotalDescriptorCount()) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001571 // DST update out of bounds
Dave Houlton00c154e2018-05-24 13:20:50 -06001572 *error_code = "VUID-VkCopyDescriptorSet-dstArrayElement-00348";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001573 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001574 error_str << "Attempting copy update to descriptorSet " << report_data->FormatHandle(dst_set->GetSet()) << " binding#"
1575 << update->dstBinding << " with offset index of "
1576 << dst_layout->GetGlobalIndexRangeFromBinding(update->dstBinding).start << " plus update array offset of "
1577 << update->dstArrayElement << " and update of " << update->descriptorCount
John Zulaufd9435c32019-06-05 15:55:36 -06001578 << " descriptors oversteps total number of descriptors in set: " << dst_layout->GetTotalDescriptorCount();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001579 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001580 return false;
1581 }
1582 // Check that types match
Shannon McPhersonafe55122020-05-25 16:20:19 -06001583 // TODO : Base default error case going from here is "VUID-VkAcquireNextImageInfoKHR-semaphore-parameter" 2ba which covers all
Dave Houltond8ed0212018-05-16 17:18:24 -06001584 // consistency issues, need more fine-grained error codes
Dave Houlton00c154e2018-05-24 13:20:50 -06001585 *error_code = "VUID-VkCopyDescriptorSet-srcSet-00349";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001586 auto src_type = src_set->GetTypeFromBinding(update->srcBinding);
John Zulaufd9435c32019-06-05 15:55:36 -06001587 auto dst_type = dst_layout->GetTypeFromBinding(update->dstBinding);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001588 if (src_type != dst_type) {
sourav parmarf4a78252020-04-10 13:04:21 -07001589 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02632";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001590 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001591 error_str << "Attempting copy update to descriptorSet " << report_data->FormatHandle(dst_set->GetSet()) << " binding #"
1592 << update->dstBinding << " with type " << string_VkDescriptorType(dst_type) << " from descriptorSet "
1593 << report_data->FormatHandle(src_set->GetSet()) << " binding #" << update->srcBinding << " with type "
1594 << string_VkDescriptorType(src_type) << ". Types do not match";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001595 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001596 return false;
1597 }
1598 // Verify consistency of src & dst bindings if update crosses binding boundaries
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001599 if ((!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(src_layout, update->srcBinding),
John Zulauf4a015c92019-06-04 09:50:05 -06001600 update->srcArrayElement, update->descriptorCount, "copy update from", src_set->GetSet(),
1601 error_msg)) ||
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001602 (!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(dst_layout, update->dstBinding),
John Zulaufd9435c32019-06-05 15:55:36 -06001603 update->dstArrayElement, update->descriptorCount, "copy update to", dst_set->GetSet(),
1604 error_msg))) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001605 return false;
1606 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001607
John Zulaufd9435c32019-06-05 15:55:36 -06001608 if ((src_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT) &&
1609 !(dst_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001610 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01918";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001611 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001612 error_str << "If pname:srcSet's (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001613 << ") layout was created with the "
1614 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag "
1615 "set, then pname:dstSet's ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001616 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001617 << ") layout must: also have been created with the "
1618 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set";
1619 *error_msg = error_str.str();
1620 return false;
1621 }
1622
John Zulaufd9435c32019-06-05 15:55:36 -06001623 if (!(src_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT) &&
1624 (dst_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001625 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01919";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001626 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001627 error_str << "If pname:srcSet's (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001628 << ") layout was created without the "
1629 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag "
1630 "set, then pname:dstSet's ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001631 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001632 << ") layout must: also have been created without the "
1633 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set";
1634 *error_msg = error_str.str();
1635 return false;
1636 }
1637
1638 if ((src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT) &&
John Zulaufd9435c32019-06-05 15:55:36 -06001639 !(dst_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001640 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01920";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001641 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001642 error_str << "If the descriptor pool from which pname:srcSet (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001643 << ") was allocated was created "
1644 "with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag "
1645 "set, then the descriptor pool from which pname:dstSet ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001646 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001647 << ") was allocated must: "
1648 "also have been created with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set";
1649 *error_msg = error_str.str();
1650 return false;
1651 }
1652
1653 if (!(src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT) &&
John Zulaufd9435c32019-06-05 15:55:36 -06001654 (dst_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001655 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01921";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001656 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001657 error_str << "If the descriptor pool from which pname:srcSet (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001658 << ") was allocated was created "
1659 "without the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag "
1660 "set, then the descriptor pool from which pname:dstSet ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001661 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001662 << ") was allocated must: "
1663 "also have been created without the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set";
1664 *error_msg = error_str.str();
1665 return false;
1666 }
1667
Jeff Bolze54ae892018-09-08 12:16:29 -05001668 if (src_type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
1669 if ((update->srcArrayElement % 4) != 0) {
1670 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-02223";
1671 std::stringstream error_str;
1672 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1673 << "srcArrayElement " << update->srcArrayElement << " not a multiple of 4";
1674 *error_msg = error_str.str();
1675 return false;
1676 }
1677 if ((update->dstArrayElement % 4) != 0) {
1678 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02224";
1679 std::stringstream error_str;
1680 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1681 << "dstArrayElement " << update->dstArrayElement << " not a multiple of 4";
1682 *error_msg = error_str.str();
1683 return false;
1684 }
1685 if ((update->descriptorCount % 4) != 0) {
1686 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-02225";
1687 std::stringstream error_str;
1688 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1689 << "descriptorCount " << update->descriptorCount << " not a multiple of 4";
1690 *error_msg = error_str.str();
1691 return false;
1692 }
1693 }
1694
Tobin Ehlisd41e7b62016-05-19 07:56:18 -06001695 // Update parameters all look good and descriptor updated so verify update contents
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07001696 if (!VerifyCopyUpdateContents(update, src_set, src_type, src_start_idx, dst_set, dst_type, dst_start_idx, func_name, error_code,
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001697 error_msg)) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07001698 return false;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001699 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06001700
1701 // All checks passed so update is good
1702 return true;
1703}
1704// Perform Copy update
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001705void cvdescriptorset::DescriptorSet::PerformCopyUpdate(ValidationStateTracker *dev_data, const VkCopyDescriptorSet *update,
1706 const DescriptorSet *src_set) {
John Zulaufc483f442017-12-15 14:02:06 -07001707 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001708 auto dst_start_idx = layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001709 // Update parameters all look good so perform update
1710 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Józef Kucia5297e372017-10-13 22:31:34 +02001711 auto src = src_set->descriptors_[src_start_idx + di].get();
1712 auto dst = descriptors_[dst_start_idx + di].get();
1713 if (src->updated) {
John Zulaufd2c3dae2019-12-12 11:02:17 -07001714 dst->CopyUpdate(state_data_, src);
Józef Kucia5297e372017-10-13 22:31:34 +02001715 some_update_ = true;
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05001716 change_count_++;
Józef Kucia5297e372017-10-13 22:31:34 +02001717 } else {
1718 dst->updated = false;
1719 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001720 }
Tobin Ehlis56a30942016-05-19 08:00:00 -06001721
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001722 if (!(layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Jeff Bolzfdf96072018-04-10 14:32:18 -05001723 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001724 InvalidateBoundCmdBuffers(dev_data);
Jeff Bolzfdf96072018-04-10 14:32:18 -05001725 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001726}
Tobin Ehlis56a30942016-05-19 08:00:00 -06001727
John Zulauf6f3d2bd2018-10-29 17:08:42 -06001728// Update the drawing state for the affected descriptors.
1729// Set cb_node to this set and this set to cb_node.
1730// Add the bindings of the descriptor
1731// Set the layout based on the current descriptor layout (will mask subsequent layer mismatch errors)
1732// TODO: Modify the UpdateDrawState virtural functions to *only* set initial layout and not change layouts
Tobin Ehlisf9519102016-08-17 09:49:13 -06001733// Prereq: This should be called for a set that has been confirmed to be active for the given cb_node, meaning it's going
1734// to be used in a draw by the given cb_node
Jeremy Kniagere6827432020-04-01 09:05:56 -06001735void cvdescriptorset::DescriptorSet::UpdateDrawState(ValidationStateTracker *device_data, CMD_BUFFER_STATE *cb_node,
1736 CMD_TYPE cmd_type, const PIPELINE_STATE *pipe,
Karl Schultz7090a052020-11-10 08:54:21 -07001737 const BindingReqMap &binding_req_map, const char *function) {
Tony-LunarG77822802020-05-28 16:35:46 -06001738 if (!device_data->disabled[command_buffer_state] && !IsPushDescriptor()) {
Jeff Bolzafa429a2019-08-14 09:59:22 -05001739 // bind cb to this descriptor set
1740 // Add bindings for descriptor set, the set's pool, and individual objects in the set
Jeff Bolzadbfa852019-10-04 13:53:30 -05001741 if (device_data->AddCommandBufferBinding(cb_bindings, VulkanTypedHandle(set_, kVulkanObjectTypeDescriptorSet, this),
1742 cb_node)) {
1743 device_data->AddCommandBufferBinding(pool_state_->cb_bindings,
1744 VulkanTypedHandle(pool_state_->pool, kVulkanObjectTypeDescriptorPool, pool_state_),
1745 cb_node);
Jeff Bolzafa429a2019-08-14 09:59:22 -05001746 }
1747 }
Jeff Bolze18e7242019-08-12 20:55:22 -05001748
1749 // Descriptor UpdateDrawState functions do two things - associate resources to the command buffer,
1750 // and call image layout validation callbacks. If both are disabled, skip the entire loop.
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -06001751 if (device_data->disabled[command_buffer_state] && device_data->disabled[image_layout_validation]) {
Jeff Bolze18e7242019-08-12 20:55:22 -05001752 return;
1753 }
1754
Tobin Ehlisf9519102016-08-17 09:49:13 -06001755 // For the active slots, use set# to look up descriptorSet from boundDescriptorSets, and bind all of that descriptor set's
1756 // resources
locke-lunarg540b2252020-08-03 13:23:36 -06001757 CMD_BUFFER_STATE::CmdDrawDispatchInfo cmd_info = {};
Tobin Ehlis022528b2016-12-29 12:22:32 -07001758 for (auto binding_req_pair : binding_req_map) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001759 auto index = layout_->GetIndexFromBinding(binding_req_pair.first);
locke-gb3ce08f2019-09-30 12:30:56 -06001760
Tony-LunarG62c5dba2018-12-20 14:27:23 -07001761 // We aren't validating descriptors created with PARTIALLY_BOUND or UPDATE_AFTER_BIND, so don't record state
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001762 auto flags = layout_->GetDescriptorBindingFlagsFromIndex(index);
locke-gb3ce08f2019-09-30 12:30:56 -06001763 if (flags & (VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT)) {
locke-lunargdec975d2019-12-18 16:15:25 -07001764 if (!(flags & VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT)) {
locke-lunarg36045992020-08-20 16:54:37 -06001765 cmd_info.binding_infos.emplace_back(binding_req_pair);
locke-gb3ce08f2019-09-30 12:30:56 -06001766 }
Tony-LunarG62c5dba2018-12-20 14:27:23 -07001767 continue;
1768 }
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001769 auto range = layout_->GetGlobalIndexRangeFromIndex(index);
John Zulaufc483f442017-12-15 14:02:06 -07001770 for (uint32_t i = range.start; i < range.end; ++i) {
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07001771 descriptors_[i]->UpdateDrawState(device_data, cb_node);
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06001772 }
1773 }
locke-lunarg540b2252020-08-03 13:23:36 -06001774
1775 if (cmd_info.binding_infos.size() > 0) {
1776 cmd_info.cmd_type = cmd_type;
1777 cmd_info.function = function;
1778 if (cb_node->activeFramebuffer) {
1779 cmd_info.framebuffer = cb_node->activeFramebuffer->framebuffer;
locke-lunargfc78e932020-11-19 17:06:24 -07001780 cmd_info.attachments = cb_node->active_attachments;
1781 cmd_info.subpasses = cb_node->active_subpasses;
locke-lunarg540b2252020-08-03 13:23:36 -06001782 }
1783 cb_node->validate_descriptorsets_in_queuesubmit[set_].emplace_back(cmd_info);
1784 }
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06001785}
1786
John Zulauffbf3c202019-07-17 14:57:14 -06001787void cvdescriptorset::DescriptorSet::FilterOneBindingReq(const BindingReqMap::value_type &binding_req_pair, BindingReqMap *out_req,
1788 const TrackedBindings &bindings, uint32_t limit) {
1789 if (bindings.size() < limit) {
1790 const auto it = bindings.find(binding_req_pair.first);
1791 if (it == bindings.cend()) out_req->emplace(binding_req_pair);
John Zulauf48a6a702017-12-22 17:14:54 -07001792 }
1793}
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06001794
John Zulauffbf3c202019-07-17 14:57:14 -06001795void cvdescriptorset::DescriptorSet::FilterBindingReqs(const CMD_BUFFER_STATE &cb_state, const PIPELINE_STATE &pipeline,
1796 const BindingReqMap &in_req, BindingReqMap *out_req) const {
1797 // For const cleanliness we have to find in the maps...
1798 const auto validated_it = cached_validation_.find(&cb_state);
1799 if (validated_it == cached_validation_.cend()) {
1800 // We have nothing validated, copy in to out
1801 for (const auto &binding_req_pair : in_req) {
1802 out_req->emplace(binding_req_pair);
John Zulauf48a6a702017-12-22 17:14:54 -07001803 }
John Zulauffbf3c202019-07-17 14:57:14 -06001804 return;
John Zulauf48a6a702017-12-22 17:14:54 -07001805 }
John Zulauffbf3c202019-07-17 14:57:14 -06001806 const auto &validated = validated_it->second;
John Zulauf48a6a702017-12-22 17:14:54 -07001807
John Zulauffbf3c202019-07-17 14:57:14 -06001808 const auto image_sample_version_it = validated.image_samplers.find(&pipeline);
1809 const VersionedBindings *image_sample_version = nullptr;
1810 if (image_sample_version_it != validated.image_samplers.cend()) {
1811 image_sample_version = &(image_sample_version_it->second);
1812 }
1813 const auto &dynamic_buffers = validated.dynamic_buffers;
1814 const auto &non_dynamic_buffers = validated.non_dynamic_buffers;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001815 const auto &stats = layout_->GetBindingTypeStats();
John Zulauf48a6a702017-12-22 17:14:54 -07001816 for (const auto &binding_req_pair : in_req) {
1817 auto binding = binding_req_pair.first;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001818 VkDescriptorSetLayoutBinding const *layout_binding = layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
John Zulauf48a6a702017-12-22 17:14:54 -07001819 if (!layout_binding) {
1820 continue;
1821 }
1822 // Caching criteria differs per type.
1823 // If image_layout have changed , the image descriptors need to be validated against them.
1824 if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
1825 (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
John Zulauffbf3c202019-07-17 14:57:14 -06001826 FilterOneBindingReq(binding_req_pair, out_req, dynamic_buffers, stats.dynamic_buffer_count);
John Zulauf48a6a702017-12-22 17:14:54 -07001827 } else if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
1828 (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)) {
John Zulauffbf3c202019-07-17 14:57:14 -06001829 FilterOneBindingReq(binding_req_pair, out_req, non_dynamic_buffers, stats.non_dynamic_buffer_count);
John Zulauf48a6a702017-12-22 17:14:54 -07001830 } else {
1831 // This is rather crude, as the changed layouts may not impact the bound descriptors,
1832 // but the simple "versioning" is a simple "dirt" test.
John Zulauffbf3c202019-07-17 14:57:14 -06001833 bool stale = true;
1834 if (image_sample_version) {
1835 const auto version_it = image_sample_version->find(binding);
1836 if (version_it != image_sample_version->cend() && (version_it->second == cb_state.image_layout_change_count)) {
1837 stale = false;
1838 }
1839 }
1840 if (stale) {
John Zulauf48a6a702017-12-22 17:14:54 -07001841 out_req->emplace(binding_req_pair);
1842 }
1843 }
1844 }
1845}
Tobin Ehlis9252c2b2016-07-21 14:40:22 -06001846
John Zulauffbf3c202019-07-17 14:57:14 -06001847void cvdescriptorset::DescriptorSet::UpdateValidationCache(const CMD_BUFFER_STATE &cb_state, const PIPELINE_STATE &pipeline,
1848 const BindingReqMap &updated_bindings) {
1849 // For const cleanliness we have to find in the maps...
1850 auto &validated = cached_validation_[&cb_state];
1851
1852 auto &image_sample_version = validated.image_samplers[&pipeline];
1853 auto &dynamic_buffers = validated.dynamic_buffers;
1854 auto &non_dynamic_buffers = validated.non_dynamic_buffers;
1855 for (const auto &binding_req_pair : updated_bindings) {
1856 auto binding = binding_req_pair.first;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001857 VkDescriptorSetLayoutBinding const *layout_binding = layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
John Zulauffbf3c202019-07-17 14:57:14 -06001858 if (!layout_binding) {
1859 continue;
1860 }
1861 // Caching criteria differs per type.
1862 if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
1863 (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
1864 dynamic_buffers.emplace(binding);
1865 } else if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
1866 (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)) {
1867 non_dynamic_buffers.emplace(binding);
1868 } else {
1869 // Save the layout change version...
1870 image_sample_version[binding] = cb_state.image_layout_change_count;
1871 }
1872 }
1873}
1874
John Zulaufd2c3dae2019-12-12 11:02:17 -07001875cvdescriptorset::SamplerDescriptor::SamplerDescriptor(const ValidationStateTracker *dev_data, const VkSampler *immut)
Karl Schultz76d16a42020-11-11 05:05:33 -07001876 : immutable_(false) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001877 updated = false;
1878 descriptor_class = PlainSampler;
1879 if (immut) {
Karl Schultz76d16a42020-11-11 05:05:33 -07001880 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(*immut);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001881 immutable_ = true;
1882 updated = true;
1883 }
1884}
Tobin Ehlise2f80292016-06-02 10:08:53 -06001885// Validate given sampler. Currently this only checks to make sure it exists in the samplerMap
John Zulaufc93c4252019-06-25 09:19:49 -06001886bool CoreChecks::ValidateSampler(const VkSampler sampler) const { return (GetSamplerState(sampler) != nullptr); }
Tobin Ehlis56a30942016-05-19 08:00:00 -06001887
John Zulaufc93c4252019-06-25 09:19:49 -06001888bool CoreChecks::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type,
John Zulaufbd9b3412019-08-22 17:16:11 -06001889 const char *func_name, std::string *error_code, std::string *error_msg) const {
John Zulaufc93c4252019-06-25 09:19:49 -06001890 auto iv_state = GetImageViewState(image_view);
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001891 assert(iv_state);
1892
Tobin Ehlis81280962016-07-20 14:04:20 -06001893 // 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 -06001894 // Validate that imageLayout is compatible with aspect_mask and image format
1895 // and validate that image usage bits are correct for given usage
Tobin Ehlis8b26a382016-09-14 08:02:49 -06001896 VkImageAspectFlags aspect_mask = iv_state->create_info.subresourceRange.aspectMask;
1897 VkImage image = iv_state->create_info.image;
Tobin Ehlis1809f912016-05-25 09:24:36 -06001898 VkFormat format = VK_FORMAT_MAX_ENUM;
1899 VkImageUsageFlags usage = 0;
John Zulaufc93c4252019-06-25 09:19:49 -06001900 auto image_node = GetImageState(image);
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001901 assert(image_node);
Chris Forbes67757ff2017-07-21 13:59:01 -07001902
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001903 format = image_node->createInfo.format;
1904 usage = image_node->createInfo.usage;
Ricardo Garcia3f5984c2020-04-09 10:56:34 +02001905 const auto stencil_usage_info = lvl_find_in_chain<VkImageStencilUsageCreateInfo>(image_node->createInfo.pNext);
1906 if (stencil_usage_info) {
1907 usage |= stencil_usage_info->stencilUsage;
1908 }
Mark Lobodzinski03d00062020-06-15 14:35:45 -06001909
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001910 // Validate that memory is bound to image
Mark Lobodzinski03d00062020-06-15 14:35:45 -06001911 if (ValidateMemoryIsBoundToImage(image_node, func_name, "UNASSIGNED-CoreValidation-BoundResourceFreedMemoryAccess")) {
1912 *error_code = "UNASSIGNED-CoreValidation-BoundResourceFreedMemoryAccess";
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001913 *error_msg = "No memory bound to image.";
Tobin Ehlis1809f912016-05-25 09:24:36 -06001914 return false;
1915 }
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001916
1917 // KHR_maintenance1 allows rendering into 2D or 2DArray views which slice a 3D image,
1918 // but not binding them to descriptor sets.
1919 if (image_node->createInfo.imageType == VK_IMAGE_TYPE_3D && (iv_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_2D ||
1920 iv_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)) {
1921 *error_code = "VUID-VkDescriptorImageInfo-imageView-00343";
1922 *error_msg = "ImageView must not be a 2D or 2DArray view of a 3D image";
1923 return false;
1924 }
1925
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001926 // TODO : The various image aspect and format checks here are based on general spec language in 11.5 Image Views section under
1927 // vkCreateImageView(). What's the best way to create unique id for these cases?
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001928 *error_code = "UNASSIGNED-CoreValidation-DrawState-InvalidImageView";
Dave Houlton1d2022c2017-03-29 11:43:58 -06001929 bool ds = FormatIsDepthOrStencil(format);
Tobin Ehlis1809f912016-05-25 09:24:36 -06001930 switch (image_layout) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001931 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
1932 // Only Color bit must be set
1933 if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
Tobin Ehlis1809f912016-05-25 09:24:36 -06001934 std::stringstream error_str;
Dave Houltona9df0ce2018-02-07 10:51:23 -07001935 error_str
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001936 << "ImageView (" << report_data->FormatHandle(image_view)
Dave Houltona9df0ce2018-02-07 10:51:23 -07001937 << ") 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 -06001938 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -06001939 return false;
1940 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001941 // format must NOT be DS
1942 if (ds) {
1943 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001944 error_str << "ImageView (" << report_data->FormatHandle(image_view)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001945 << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but the image format is "
1946 << string_VkFormat(format) << " which is not a color format.";
1947 *error_msg = error_str.str();
1948 return false;
1949 }
1950 break;
1951 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
1952 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
1953 // Depth or stencil bit must be set, but both must NOT be set
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06001954 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
1955 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
1956 // both must NOT be set
1957 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001958 error_str << "ImageView (" << report_data->FormatHandle(image_view)
Mark Lobodzinski6b042922019-06-21 14:46:42 -06001959 << ") has both STENCIL and DEPTH aspects set";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001960 *error_msg = error_str.str();
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06001961 return false;
1962 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001963 } else if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
1964 // Neither were set
1965 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001966 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06001967 << string_VkImageLayout(image_layout) << " but does not have STENCIL or DEPTH aspects set";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001968 *error_msg = error_str.str();
1969 return false;
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06001970 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001971 // format must be DS
1972 if (!ds) {
1973 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001974 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06001975 << string_VkImageLayout(image_layout) << " but the image format is " << string_VkFormat(format)
1976 << " which is not a depth/stencil format.";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001977 *error_msg = error_str.str();
1978 return false;
1979 }
1980 break;
1981 default:
1982 // For other layouts if the source is depth/stencil image, both aspect bits must not be set
1983 if (ds) {
1984 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
1985 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
1986 // both must NOT be set
1987 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001988 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06001989 << string_VkImageLayout(image_layout) << " and is using depth/stencil image of format "
1990 << string_VkFormat(format)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001991 << " but it has both STENCIL and DEPTH aspects set, which is illegal. When using a depth/stencil "
1992 "image in a descriptor set, please only set either VK_IMAGE_ASPECT_DEPTH_BIT or "
1993 "VK_IMAGE_ASPECT_STENCIL_BIT depending on whether it will be used for depth reads or stencil "
1994 "reads respectively.";
Mark Lobodzinski4d05d7a2019-06-25 09:12:06 -06001995 *error_code = "VUID-VkDescriptorImageInfo-imageView-01976";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001996 *error_msg = error_str.str();
1997 return false;
1998 }
1999 }
2000 }
2001 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002002 }
2003 // Now validate that usage flags are correctly set for given type of update
Tobin Ehlisfb4cf712016-10-10 14:02:48 -06002004 // 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 -06002005 // TODO : The various image usage bit requirements are in general spec language for VkImageUsageFlags bit block in 11.3 Images
2006 // under vkCreateImage()
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002007 const char *error_usage_bit = nullptr;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002008 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002009 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
sfricke-samsung088f1242020-06-06 02:15:35 -07002010 if (iv_state->samplerConversion != VK_NULL_HANDLE) {
2011 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-01946";
2012 std::stringstream error_str;
2013 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ")"
2014 << "used as a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE can't be created with VkSamplerYcbcrConversion";
2015 *error_msg = error_str.str();
2016 return false;
2017 }
2018 // drop through
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002019 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
2020 if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
2021 error_usage_bit = "VK_IMAGE_USAGE_SAMPLED_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08002022 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00337";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002023 }
2024 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002025 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002026 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
2027 if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
2028 error_usage_bit = "VK_IMAGE_USAGE_STORAGE_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08002029 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00339";
sfricke-samsungada55a12020-08-15 03:39:41 -07002030 } else if ((VK_IMAGE_LAYOUT_GENERAL != image_layout) || ((VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR != image_layout) &&
2031 (device_extensions.vk_khr_shared_presentable_image))) {
sfricke-samsungf1058982020-09-10 22:36:49 -07002032 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04152";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002033 std::stringstream error_str;
sfricke-samsungada55a12020-08-15 03:39:41 -07002034 error_str << "Descriptor update with descriptorType VK_DESCRIPTOR_TYPE_STORAGE_IMAGE"
2035 << " is being updated with invalid imageLayout " << string_VkImageLayout(image_layout) << " for image "
2036 << report_data->FormatHandle(image) << " in imageView " << report_data->FormatHandle(image_view)
2037 << ". Allowed layouts are: VK_IMAGE_LAYOUT_GENERAL";
2038 if (device_extensions.vk_khr_shared_presentable_image) {
2039 error_str << " or VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR";
Tobin Ehlisbb03e5f2017-05-11 08:52:51 -06002040 }
sfricke-samsungada55a12020-08-15 03:39:41 -07002041 *error_msg = error_str.str();
2042 return false;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002043 }
2044 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002045 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002046 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
2047 if (!(usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
2048 error_usage_bit = "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08002049 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00338";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002050 }
2051 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002052 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002053 default:
2054 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002055 }
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002056 if (error_usage_bit) {
Tobin Ehlis1809f912016-05-25 09:24:36 -06002057 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002058 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") with usage mask " << std::hex << std::showbase
2059 << usage << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have "
2060 << error_usage_bit << " set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002061 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -06002062 return false;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002063 }
John Zulauff4c07882019-01-24 14:03:36 -07002064
sfricke-samsungada55a12020-08-15 03:39:41 -07002065 // All the following types share the same image layouts
2066 // checkf or Storage Images above
2067 if ((type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) || (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
2068 (type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
John Zulauff4c07882019-01-24 14:03:36 -07002069 // Test that the layout is compatible with the descriptorType for the two sampled image types
2070 const static std::array<VkImageLayout, 3> valid_layouts = {
Jeremy Hayesd0549f62019-06-05 10:15:36 -06002071 {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 -07002072
2073 struct ExtensionLayout {
2074 VkImageLayout layout;
Tony-LunarG2ec96bb2019-11-26 13:43:02 -07002075 ExtEnabled DeviceExtensions::*extension;
John Zulauff4c07882019-01-24 14:03:36 -07002076 };
2077
2078 const static std::array<ExtensionLayout, 3> extended_layouts{
2079 {// Note double brace req'd for aggregate initialization
2080 {VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR, &DeviceExtensions::vk_khr_shared_presentable_image},
2081 {VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, &DeviceExtensions::vk_khr_maintenance2},
2082 {VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, &DeviceExtensions::vk_khr_maintenance2}}};
John Zulaufc93c4252019-06-25 09:19:49 -06002083 auto is_layout = [image_layout, this](const ExtensionLayout &ext_layout) {
2084 return device_extensions.*(ext_layout.extension) && (ext_layout.layout == image_layout);
John Zulauff4c07882019-01-24 14:03:36 -07002085 };
2086
2087 bool valid_layout = (std::find(valid_layouts.cbegin(), valid_layouts.cend(), image_layout) != valid_layouts.cend()) ||
2088 std::any_of(extended_layouts.cbegin(), extended_layouts.cend(), is_layout);
2089
2090 if (!valid_layout) {
sfricke-samsungf1058982020-09-10 22:36:49 -07002091 // The following works as currently all 3 descriptor types share the same set of valid layouts
sfricke-samsungada55a12020-08-15 03:39:41 -07002092 switch (type) {
2093 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
Shannon McPherson2c793ba2020-08-28 12:13:24 -06002094 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04149";
sfricke-samsungada55a12020-08-15 03:39:41 -07002095 break;
2096 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
Shannon McPherson2c793ba2020-08-28 12:13:24 -06002097 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04150";
sfricke-samsungada55a12020-08-15 03:39:41 -07002098 break;
2099 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
sfricke-samsungf1058982020-09-10 22:36:49 -07002100 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04151";
sfricke-samsungada55a12020-08-15 03:39:41 -07002101 break;
2102 default:
2103 break;
2104 }
John Zulauff4c07882019-01-24 14:03:36 -07002105 std::stringstream error_str;
2106 error_str << "Descriptor update with descriptorType " << string_VkDescriptorType(type)
Mark Lobodzinski74eddba2019-06-21 14:16:33 -06002107 << " is being updated with invalid imageLayout " << string_VkImageLayout(image_layout) << " for image "
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002108 << report_data->FormatHandle(image) << " in imageView " << report_data->FormatHandle(image_view)
John Zulauff4c07882019-01-24 14:03:36 -07002109 << ". Allowed layouts are: VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "
2110 << "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL";
2111 for (auto &ext_layout : extended_layouts) {
John Zulaufc93c4252019-06-25 09:19:49 -06002112 if (device_extensions.*(ext_layout.extension)) {
John Zulauff4c07882019-01-24 14:03:36 -07002113 error_str << ", " << string_VkImageLayout(ext_layout.layout);
2114 }
2115 }
2116 *error_msg = error_str.str();
2117 return false;
2118 }
2119 }
2120
sfricke-samsungbd0e8052020-06-06 01:36:39 -07002121 if ((type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) || (type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
2122 const VkComponentMapping components = iv_state->create_info.components;
2123 if (IsIdentitySwizzle(components) == false) {
2124 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00336";
2125 std::stringstream error_str;
2126 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has a non-identiy swizzle component, "
2127 << " r swizzle = " << string_VkComponentSwizzle(components.r) << ","
2128 << " g swizzle = " << string_VkComponentSwizzle(components.g) << ","
2129 << " b swizzle = " << string_VkComponentSwizzle(components.b) << ","
2130 << " a swizzle = " << string_VkComponentSwizzle(components.a) << ".";
2131 *error_msg = error_str.str();
2132 return false;
2133 }
2134 }
2135
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002136 return true;
2137}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002138
John Zulaufd2c3dae2019-12-12 11:02:17 -07002139void cvdescriptorset::SamplerDescriptor::WriteUpdate(const ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update,
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002140 const uint32_t index) {
Chris Forbesfea2c542018-04-13 09:34:15 -07002141 if (!immutable_) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002142 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(update->pImageInfo[index].sampler);
Chris Forbesfea2c542018-04-13 09:34:15 -07002143 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002144 updated = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002145}
2146
John Zulaufd2c3dae2019-12-12 11:02:17 -07002147void cvdescriptorset::SamplerDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002148 if (!immutable_) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002149 sampler_state_ = static_cast<const SamplerDescriptor *>(src)->sampler_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002150 }
2151 updated = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002152}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002153
John Zulauffbf3c202019-07-17 14:57:14 -06002154void cvdescriptorset::SamplerDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002155 if (!immutable_) {
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002156 auto sampler_state = GetSamplerState();
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07002157 if (sampler_state) dev_data->AddCommandBufferBindingSampler(cb_node, sampler_state);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002158 }
2159}
2160
John Zulaufd2c3dae2019-12-12 11:02:17 -07002161cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(const ValidationStateTracker *dev_data, const VkSampler *immut)
Karl Schultz76d16a42020-11-11 05:05:33 -07002162 : immutable_(false), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002163 updated = false;
2164 descriptor_class = ImageSampler;
2165 if (immut) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002166 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(*immut);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002167 immutable_ = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002168 }
2169}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002170
John Zulaufd2c3dae2019-12-12 11:02:17 -07002171void cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(const ValidationStateTracker *dev_data,
2172 const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002173 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002174 const auto &image_info = update->pImageInfo[index];
Chris Forbesfea2c542018-04-13 09:34:15 -07002175 if (!immutable_) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002176 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(image_info.sampler);
Chris Forbesfea2c542018-04-13 09:34:15 -07002177 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002178 image_layout_ = image_info.imageLayout;
Karl Schultz76d16a42020-11-11 05:05:33 -07002179 image_view_state_ = dev_data->GetConstCastShared<IMAGE_VIEW_STATE>(image_info.imageView);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002180}
2181
John Zulaufd2c3dae2019-12-12 11:02:17 -07002182void cvdescriptorset::ImageSamplerDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002183 if (!immutable_) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002184 sampler_state_ = static_cast<const ImageSamplerDescriptor *>(src)->sampler_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002185 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002186 updated = true;
Karl Schultz76d16a42020-11-11 05:05:33 -07002187 image_layout_ = static_cast<const ImageSamplerDescriptor *>(src)->image_layout_;
2188 image_view_state_ = static_cast<const ImageSamplerDescriptor *>(src)->image_view_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002189}
2190
John Zulauffbf3c202019-07-17 14:57:14 -06002191void cvdescriptorset::ImageSamplerDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Tobin Ehlis81e46372016-08-17 13:33:44 -06002192 // First add binding for any non-immutable sampler
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002193 if (!immutable_) {
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002194 auto sampler_state = GetSamplerState();
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07002195 if (sampler_state) dev_data->AddCommandBufferBindingSampler(cb_node, sampler_state);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002196 }
Tobin Ehlis81e46372016-08-17 13:33:44 -06002197 // Add binding for image
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002198 auto iv_state = GetImageViewState();
Tobin Ehlis8b26a382016-09-14 08:02:49 -06002199 if (iv_state) {
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07002200 dev_data->AddCommandBufferBindingImageView(cb_node, iv_state);
John Zulauffbf3c202019-07-17 14:57:14 -06002201 dev_data->CallSetImageViewInitialLayoutCallback(cb_node, *iv_state, image_layout_);
Jeff Bolz148d94e2018-12-13 21:25:56 -06002202 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002203}
2204
Tobin Ehlis300888c2016-05-18 13:43:26 -06002205cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type)
Karl Schultz76d16a42020-11-11 05:05:33 -07002206 : storage_(false), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002207 updated = false;
2208 descriptor_class = Image;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002209 if (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE == type) storage_ = true;
Petr Kraus13c98a62017-12-09 00:22:39 +01002210}
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002211
John Zulaufd2c3dae2019-12-12 11:02:17 -07002212void cvdescriptorset::ImageDescriptor::WriteUpdate(const ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update,
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002213 const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002214 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002215 const auto &image_info = update->pImageInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06002216 image_layout_ = image_info.imageLayout;
Karl Schultz76d16a42020-11-11 05:05:33 -07002217 image_view_state_ = dev_data->GetConstCastShared<IMAGE_VIEW_STATE>(image_info.imageView);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002218}
2219
John Zulaufd2c3dae2019-12-12 11:02:17 -07002220void cvdescriptorset::ImageDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002221 updated = true;
Karl Schultz76d16a42020-11-11 05:05:33 -07002222 image_layout_ = static_cast<const ImageDescriptor *>(src)->image_layout_;
2223 image_view_state_ = static_cast<const ImageDescriptor *>(src)->image_view_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002224}
2225
John Zulauffbf3c202019-07-17 14:57:14 -06002226void cvdescriptorset::ImageDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Tobin Ehlis81e46372016-08-17 13:33:44 -06002227 // Add binding for image
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002228 auto iv_state = GetImageViewState();
Tobin Ehlis8b26a382016-09-14 08:02:49 -06002229 if (iv_state) {
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07002230 dev_data->AddCommandBufferBindingImageView(cb_node, iv_state);
John Zulauffbf3c202019-07-17 14:57:14 -06002231 dev_data->CallSetImageViewInitialLayoutCallback(cb_node, *iv_state, image_layout_);
Jeff Bolz148d94e2018-12-13 21:25:56 -06002232 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002233}
2234
Tobin Ehlis300888c2016-05-18 13:43:26 -06002235cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type)
Karl Schultz76d16a42020-11-11 05:05:33 -07002236 : storage_(false), dynamic_(false), offset_(0), range_(0) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002237 updated = false;
2238 descriptor_class = GeneralBuffer;
2239 if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) {
2240 dynamic_ = true;
2241 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type) {
2242 storage_ = true;
2243 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) {
2244 dynamic_ = true;
2245 storage_ = true;
2246 }
2247}
John Zulaufd2c3dae2019-12-12 11:02:17 -07002248void cvdescriptorset::BufferDescriptor::WriteUpdate(const ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update,
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002249 const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002250 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002251 const auto &buffer_info = update->pBufferInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06002252 offset_ = buffer_info.offset;
2253 range_ = buffer_info.range;
Karl Schultz76d16a42020-11-11 05:05:33 -07002254 buffer_state_ = dev_data->GetConstCastShared<BUFFER_STATE>(buffer_info.buffer);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002255}
2256
John Zulaufd2c3dae2019-12-12 11:02:17 -07002257void cvdescriptorset::BufferDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002258 updated = true;
Karl Schultz76d16a42020-11-11 05:05:33 -07002259 const auto buff_desc = static_cast<const BufferDescriptor *>(src);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002260 offset_ = buff_desc->offset_;
2261 range_ = buff_desc->range_;
Karl Schultz76d16a42020-11-11 05:05:33 -07002262 buffer_state_ = buff_desc->buffer_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002263}
2264
John Zulauffbf3c202019-07-17 14:57:14 -06002265void cvdescriptorset::BufferDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002266 auto buffer_node = GetBufferState();
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07002267 if (buffer_node) dev_data->AddCommandBufferBindingBuffer(cb_node, buffer_node);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002268}
2269
Karl Schultz76d16a42020-11-11 05:05:33 -07002270cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type) : storage_(false) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002271 updated = false;
2272 descriptor_class = TexelBuffer;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002273 if (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER == type) storage_ = true;
Petr Kraus13c98a62017-12-09 00:22:39 +01002274}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002275
John Zulaufd2c3dae2019-12-12 11:02:17 -07002276void cvdescriptorset::TexelDescriptor::WriteUpdate(const ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update,
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002277 const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002278 updated = true;
Karl Schultz76d16a42020-11-11 05:05:33 -07002279 buffer_view_state_ = dev_data->GetConstCastShared<BUFFER_VIEW_STATE>(update->pTexelBufferView[index]);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002280}
2281
John Zulaufd2c3dae2019-12-12 11:02:17 -07002282void cvdescriptorset::TexelDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002283 updated = true;
Karl Schultz76d16a42020-11-11 05:05:33 -07002284 buffer_view_state_ = static_cast<const TexelDescriptor *>(src)->buffer_view_state_;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002285}
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002286
John Zulauffbf3c202019-07-17 14:57:14 -06002287void cvdescriptorset::TexelDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002288 auto bv_state = GetBufferViewState();
Tobin Ehlis8b872462016-09-14 08:12:08 -06002289 if (bv_state) {
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07002290 dev_data->AddCommandBufferBindingBufferView(cb_node, bv_state);
Tobin Ehlis81e46372016-08-17 13:33:44 -06002291 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002292}
2293
Jeff Bolz95176d02020-04-01 00:36:16 -05002294cvdescriptorset::AccelerationStructureDescriptor::AccelerationStructureDescriptor(const VkDescriptorType type)
sourav parmarcd5fb182020-07-17 12:58:44 -07002295 : acc_(VK_NULL_HANDLE), acc_nv_(VK_NULL_HANDLE) {
Jeff Bolz95176d02020-04-01 00:36:16 -05002296 updated = false;
sourav parmarcd5fb182020-07-17 12:58:44 -07002297 is_khr_ = false;
Jeff Bolz95176d02020-04-01 00:36:16 -05002298 descriptor_class = AccelerationStructure;
2299}
2300void cvdescriptorset::AccelerationStructureDescriptor::WriteUpdate(const ValidationStateTracker *dev_data,
2301 const VkWriteDescriptorSet *update, const uint32_t index) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002302 const auto *acc_info = lvl_find_in_chain<VkWriteDescriptorSetAccelerationStructureKHR>(update->pNext);
2303 const auto *acc_info_nv = lvl_find_in_chain<VkWriteDescriptorSetAccelerationStructureNV>(update->pNext);
2304 assert(acc_info || acc_info_nv);
2305 is_khr_ = (acc_info != NULL);
Jeff Bolz95176d02020-04-01 00:36:16 -05002306 updated = true;
sourav parmarcd5fb182020-07-17 12:58:44 -07002307 if (is_khr_) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002308 acc_ = acc_info->pAccelerationStructures[index];
sourav parmarcd5fb182020-07-17 12:58:44 -07002309 acc_state_ = dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE_KHR>(acc_);
2310 } else {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002311 acc_nv_ = acc_info_nv->pAccelerationStructures[index];
sourav parmarcd5fb182020-07-17 12:58:44 -07002312 acc_state_nv_ = dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE>(acc_nv_);
2313 }
Jeff Bolz95176d02020-04-01 00:36:16 -05002314}
2315
2316void cvdescriptorset::AccelerationStructureDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
2317 auto acc_desc = static_cast<const AccelerationStructureDescriptor *>(src);
2318 updated = true;
sourav parmarcd5fb182020-07-17 12:58:44 -07002319 if (is_khr_) {
2320 acc_ = acc_desc->acc_;
2321 acc_state_ = dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE_KHR>(acc_);
2322 } else {
2323 acc_nv_ = acc_desc->acc_nv_;
2324 acc_state_nv_ = dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE>(acc_nv_);
2325 }
Jeff Bolz95176d02020-04-01 00:36:16 -05002326}
2327
2328void cvdescriptorset::AccelerationStructureDescriptor::UpdateDrawState(ValidationStateTracker *dev_data,
2329 CMD_BUFFER_STATE *cb_node) {
sourav parmarcd5fb182020-07-17 12:58:44 -07002330 if (is_khr_) {
2331 auto acc_node = GetAccelerationStructureStateKHR();
2332 if (acc_node) dev_data->AddCommandBufferBindingAccelerationStructure(cb_node, acc_node);
2333 } else {
2334 auto acc_node = GetAccelerationStructureStateNV();
2335 if (acc_node) dev_data->AddCommandBufferBindingAccelerationStructure(cb_node, acc_node);
2336 }
Jeff Bolz95176d02020-04-01 00:36:16 -05002337}
2338
Tobin Ehlis300888c2016-05-18 13:43:26 -06002339// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
2340// sets, and then calls their respective Validate[Write|Copy]Update functions.
2341// If the update hits an issue for which the callback returns "true", meaning that the call down the chain should
2342// be skipped, then true is returned.
2343// If there is no issue with the update, then false is returned.
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002344bool CoreChecks::ValidateUpdateDescriptorSets(uint32_t write_count, const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05002345 const VkCopyDescriptorSet *p_cds, const char *func_name) const {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002346 bool skip = false;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002347 // Validate Write updates
Tobin Ehlis56a30942016-05-19 08:00:00 -06002348 for (uint32_t i = 0; i < write_count; i++) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002349 auto dest_set = p_wds[i].dstSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002350 auto set_node = GetSetNode(dest_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002351 if (!set_node) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002352 skip |=
2353 LogError(dest_set, kVUID_Core_DrawState_InvalidDescriptorSet, "Cannot call %s on %s that has not been allocated.",
2354 func_name, report_data->FormatHandle(dest_set).c_str());
Tobin Ehlis300888c2016-05-18 13:43:26 -06002355 } else {
Dave Houltond8ed0212018-05-16 17:18:24 -06002356 std::string error_code;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002357 std::string error_str;
John Zulaufc93c4252019-06-25 09:19:49 -06002358 if (!ValidateWriteUpdate(set_node, &p_wds[i], func_name, &error_code, &error_str)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002359 skip |= LogError(dest_set, error_code, "%s failed write update validation for %s with error: %s.", func_name,
2360 report_data->FormatHandle(dest_set).c_str(), error_str.c_str());
Tobin Ehlis300888c2016-05-18 13:43:26 -06002361 }
2362 }
sourav parmara24fb7b2020-05-26 10:50:04 -07002363 if (p_wds[i].pNext) {
Mark Lobodzinski17dc4602020-05-29 07:48:40 -06002364 const auto *pnext_struct = lvl_find_in_chain<VkWriteDescriptorSetAccelerationStructureKHR>(p_wds[i].pNext);
2365 if (pnext_struct) {
2366 for (uint32_t j = 0; j < pnext_struct->accelerationStructureCount; ++j) {
sourav parmarcd5fb182020-07-17 12:58:44 -07002367 const ACCELERATION_STRUCTURE_STATE_KHR *as_state =
2368 GetAccelerationStructureStateKHR(pnext_struct->pAccelerationStructures[j]);
2369 if (as_state && (as_state->create_infoKHR.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR &&
sourav parmar766e2a72020-12-03 16:17:11 -08002370 (as_state->create_infoKHR.type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR &&
2371 as_state->create_infoKHR.type != VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR))) {
2372 // To Do: update VUID descritption after spec changes
sourav parmara24fb7b2020-05-26 10:50:04 -07002373 skip |=
sourav parmarcd5fb182020-07-17 12:58:44 -07002374 LogError(dest_set, "VUID-VkWriteDescriptorSetAccelerationStructureKHR-pAccelerationStructures-03579",
2375 "%s: Each acceleration structure in pAccelerationStructures must have been created with "
2376 "VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR or VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR "
2377 "and built with VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR.",
sourav parmara24fb7b2020-05-26 10:50:04 -07002378 func_name);
2379 }
2380 }
2381 }
sourav parmarcd5fb182020-07-17 12:58:44 -07002382 const auto *pnext_struct_nv = lvl_find_in_chain<VkWriteDescriptorSetAccelerationStructureNV>(p_wds[i].pNext);
2383 if (pnext_struct_nv) {
2384 for (uint32_t j = 0; j < pnext_struct_nv->accelerationStructureCount; ++j) {
2385 const ACCELERATION_STRUCTURE_STATE *as_state =
2386 GetAccelerationStructureStateNV(pnext_struct_nv->pAccelerationStructures[j]);
2387 if (as_state && (as_state->create_infoNV.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV &&
2388 as_state->create_infoNV.info.type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV)) {
2389 skip |= LogError(dest_set, "VUID-VkWriteDescriptorSetAccelerationStructureNV-pAccelerationStructures-03748",
2390 "%s: Each acceleration structure in pAccelerationStructures must have been created with"
2391 " VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV.",
2392 func_name);
2393 }
2394 }
2395 }
sourav parmara24fb7b2020-05-26 10:50:04 -07002396 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002397 }
2398 // Now validate copy updates
Tobin Ehlis56a30942016-05-19 08:00:00 -06002399 for (uint32_t i = 0; i < copy_count; ++i) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002400 auto dst_set = p_cds[i].dstSet;
2401 auto src_set = p_cds[i].srcSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002402 auto src_node = GetSetNode(src_set);
2403 auto dst_node = GetSetNode(dst_set);
Tobin Ehlisa1712752017-01-04 09:41:47 -07002404 // Object_tracker verifies that src & dest descriptor set are valid
2405 assert(src_node);
2406 assert(dst_node);
Dave Houltond8ed0212018-05-16 17:18:24 -06002407 std::string error_code;
Tobin Ehlisa1712752017-01-04 09:41:47 -07002408 std::string error_str;
John Zulaufc93c4252019-06-25 09:19:49 -06002409 if (!ValidateCopyUpdate(&p_cds[i], dst_node, src_node, func_name, &error_code, &error_str)) {
Mark Lobodzinski9d38ea22020-03-16 18:22:16 -06002410 LogObjectList objlist(dst_set);
2411 objlist.add(src_set);
locke-lunarg9edc2812019-06-17 23:18:52 -06002412 skip |=
Mark Lobodzinski9d38ea22020-03-16 18:22:16 -06002413 LogError(objlist, error_code, "%s failed copy update from %s to %s with error: %s.", func_name,
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002414 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 -06002415 }
2416 }
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002417 return skip;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002418}
2419// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
2420// sets, and then calls their respective Perform[Write|Copy]Update functions.
2421// Prerequisite : ValidateUpdateDescriptorSets() should be called and return "false" prior to calling PerformUpdateDescriptorSets()
2422// with the same set of updates.
2423// This is split from the validate code to allow validation prior to calling down the chain, and then update after
2424// calling down the chain.
John Zulaufe3b35f32019-06-25 14:21:21 -06002425void cvdescriptorset::PerformUpdateDescriptorSets(ValidationStateTracker *dev_data, uint32_t write_count,
2426 const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
2427 const VkCopyDescriptorSet *p_cds) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002428 // Write updates first
2429 uint32_t i = 0;
2430 for (i = 0; i < write_count; ++i) {
2431 auto dest_set = p_wds[i].dstSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002432 auto set_node = dev_data->GetSetNode(dest_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002433 if (set_node) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05002434 set_node->PerformWriteUpdate(dev_data, &p_wds[i]);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002435 }
2436 }
2437 // Now copy updates
2438 for (i = 0; i < copy_count; ++i) {
2439 auto dst_set = p_cds[i].dstSet;
2440 auto src_set = p_cds[i].srcSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002441 auto src_node = dev_data->GetSetNode(src_set);
2442 auto dst_node = dev_data->GetSetNode(dst_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002443 if (src_node && dst_node) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05002444 dst_node->PerformCopyUpdate(dev_data, &p_cds[i], src_node);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002445 }
2446 }
2447}
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002448
John Zulaufe3b35f32019-06-25 14:21:21 -06002449cvdescriptorset::DecodedTemplateUpdate::DecodedTemplateUpdate(const ValidationStateTracker *device_data,
2450 VkDescriptorSet descriptorSet, const TEMPLATE_STATE *template_state,
2451 const void *pData, VkDescriptorSetLayout push_layout) {
John Zulaufb845eb22018-10-12 11:41:06 -06002452 auto const &create_info = template_state->create_info;
2453 inline_infos.resize(create_info.descriptorUpdateEntryCount); // Make sure we have one if we need it
2454 desc_writes.reserve(create_info.descriptorUpdateEntryCount); // emplaced, so reserved without initialization
John Zulauf1d27e0a2018-11-05 10:12:48 -07002455 VkDescriptorSetLayout effective_dsl = create_info.templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
2456 ? create_info.descriptorSetLayout
2457 : push_layout;
Jeff Bolz6ae39612019-10-11 20:57:36 -05002458 auto layout_obj = device_data->GetDescriptorSetLayoutShared(effective_dsl);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002459
2460 // Create a WriteDescriptorSet struct for each template update entry
2461 for (uint32_t i = 0; i < create_info.descriptorUpdateEntryCount; i++) {
2462 auto binding_count = layout_obj->GetDescriptorCountFromBinding(create_info.pDescriptorUpdateEntries[i].dstBinding);
2463 auto binding_being_updated = create_info.pDescriptorUpdateEntries[i].dstBinding;
2464 auto dst_array_element = create_info.pDescriptorUpdateEntries[i].dstArrayElement;
2465
John Zulaufb6d71202017-12-22 16:47:09 -07002466 desc_writes.reserve(desc_writes.size() + create_info.pDescriptorUpdateEntries[i].descriptorCount);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002467 for (uint32_t j = 0; j < create_info.pDescriptorUpdateEntries[i].descriptorCount; j++) {
2468 desc_writes.emplace_back();
2469 auto &write_entry = desc_writes.back();
2470
2471 size_t offset = create_info.pDescriptorUpdateEntries[i].offset + j * create_info.pDescriptorUpdateEntries[i].stride;
2472 char *update_entry = (char *)(pData) + offset;
2473
2474 if (dst_array_element >= binding_count) {
2475 dst_array_element = 0;
Mark Lobodzinski4aa479d2017-03-10 09:14:00 -07002476 binding_being_updated = layout_obj->GetNextValidBinding(binding_being_updated);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002477 }
2478
2479 write_entry.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2480 write_entry.pNext = NULL;
2481 write_entry.dstSet = descriptorSet;
2482 write_entry.dstBinding = binding_being_updated;
2483 write_entry.dstArrayElement = dst_array_element;
2484 write_entry.descriptorCount = 1;
2485 write_entry.descriptorType = create_info.pDescriptorUpdateEntries[i].descriptorType;
2486
2487 switch (create_info.pDescriptorUpdateEntries[i].descriptorType) {
2488 case VK_DESCRIPTOR_TYPE_SAMPLER:
2489 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2490 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2491 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2492 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2493 write_entry.pImageInfo = reinterpret_cast<VkDescriptorImageInfo *>(update_entry);
2494 break;
2495
2496 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2497 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2498 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2499 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2500 write_entry.pBufferInfo = reinterpret_cast<VkDescriptorBufferInfo *>(update_entry);
2501 break;
2502
2503 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2504 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2505 write_entry.pTexelBufferView = reinterpret_cast<VkBufferView *>(update_entry);
2506 break;
Dave Houlton142c4cb2018-10-17 15:04:41 -06002507 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: {
2508 VkWriteDescriptorSetInlineUniformBlockEXT *inline_info = &inline_infos[i];
2509 inline_info->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT;
2510 inline_info->pNext = nullptr;
2511 inline_info->dataSize = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2512 inline_info->pData = update_entry;
2513 write_entry.pNext = inline_info;
Ricardo Garciafee15732019-05-28 11:13:31 +02002514 // descriptorCount must match the dataSize member of the VkWriteDescriptorSetInlineUniformBlockEXT structure
2515 write_entry.descriptorCount = inline_info->dataSize;
Dave Houlton142c4cb2018-10-17 15:04:41 -06002516 // skip the rest of the array, they just represent bytes in the update
2517 j = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2518 break;
2519 }
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002520 default:
2521 assert(0);
2522 break;
2523 }
2524 dst_array_element++;
2525 }
2526 }
John Zulaufb845eb22018-10-12 11:41:06 -06002527}
John Zulaufb45fdc32018-10-12 15:14:17 -06002528// These helper functions carry out the validate and record descriptor updates peformed via update templates. They decode
2529// the templatized data and leverage the non-template UpdateDescriptor helper functions.
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002530bool CoreChecks::ValidateUpdateDescriptorSetsWithTemplateKHR(VkDescriptorSet descriptorSet, const TEMPLATE_STATE *template_state,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05002531 const void *pData) const {
John Zulaufb45fdc32018-10-12 15:14:17 -06002532 // Translate the templated update into a normal update for validation...
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002533 cvdescriptorset::DecodedTemplateUpdate decoded_update(this, descriptorSet, template_state, pData);
2534 return ValidateUpdateDescriptorSets(static_cast<uint32_t>(decoded_update.desc_writes.size()), decoded_update.desc_writes.data(),
2535 0, NULL, "vkUpdateDescriptorSetWithTemplate()");
John Zulaufb45fdc32018-10-12 15:14:17 -06002536}
John Zulaufb845eb22018-10-12 11:41:06 -06002537
John Zulauf4e7bcb52018-11-02 10:46:30 -06002538std::string cvdescriptorset::DescriptorSet::StringifySetAndLayout() const {
2539 std::string out;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002540 auto layout_handle = layout_->GetDescriptorSetLayout();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002541 if (IsPushDescriptor()) {
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002542 std::ostringstream str;
Tony-LunarG1d3ee2d2020-10-27 15:54:52 -06002543 str << "Push Descriptors defined with " << state_data_->report_data->FormatHandle(layout_handle);
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002544 out = str.str();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002545 } else {
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002546 std::ostringstream str;
Tony-LunarG1d3ee2d2020-10-27 15:54:52 -06002547 str << state_data_->report_data->FormatHandle(set_) << " allocated with "
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002548 << state_data_->report_data->FormatHandle(layout_handle);
2549 out = str.str();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002550 }
2551 return out;
2552};
2553
John Zulauf1d27e0a2018-11-05 10:12:48 -07002554// Loop through the write updates to validate for a push descriptor set, ignoring dstSet
John Zulaufc93c4252019-06-25 09:19:49 -06002555bool CoreChecks::ValidatePushDescriptorsUpdate(const DescriptorSet *push_set, uint32_t write_count,
John Zulaufbd9b3412019-08-22 17:16:11 -06002556 const VkWriteDescriptorSet *p_wds, const char *func_name) const {
John Zulaufd9435c32019-06-05 15:55:36 -06002557 assert(push_set->IsPushDescriptor());
John Zulauf1d27e0a2018-11-05 10:12:48 -07002558 bool skip = false;
2559 for (uint32_t i = 0; i < write_count; i++) {
2560 std::string error_code;
2561 std::string error_str;
John Zulaufc93c4252019-06-25 09:19:49 -06002562 if (!ValidateWriteUpdate(push_set, &p_wds[i], func_name, &error_code, &error_str)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002563 skip |= LogError(push_set->GetDescriptorSetLayout(), error_code, "%s failed update validation: %s.", func_name,
2564 error_str.c_str());
John Zulauf1d27e0a2018-11-05 10:12:48 -07002565 }
2566 }
2567 return skip;
2568}
2569
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002570// For the given buffer, verify that its creation parameters are appropriate for the given type
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002571// 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 -06002572bool cvdescriptorset::ValidateBufferUsage(debug_report_data *report_data, BUFFER_STATE const *buffer_node, VkDescriptorType type,
2573 std::string *error_code, std::string *error_msg) {
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002574 // Verify that usage bits set correctly for given type
Tobin Ehlis94bc5d22016-06-02 07:46:52 -06002575 auto usage = buffer_node->createInfo.usage;
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002576 const char *error_usage_bit = nullptr;
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002577 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002578 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2579 if (!(usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002580 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00334";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002581 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT";
2582 }
2583 break;
2584 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2585 if (!(usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002586 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00335";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002587 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT";
2588 }
2589 break;
2590 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2591 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2592 if (!(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002593 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00330";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002594 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT";
2595 }
2596 break;
2597 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2598 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2599 if (!(usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002600 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00331";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002601 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT";
2602 }
2603 break;
2604 default:
2605 break;
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002606 }
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002607 if (error_usage_bit) {
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002608 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002609 error_str << "Buffer (" << report_data->FormatHandle(buffer_node->buffer) << ") with usage mask " << std::hex
2610 << std::showbase << usage << " being used for a descriptor update of type " << string_VkDescriptorType(type)
2611 << " does not have " << error_usage_bit << " set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002612 *error_msg = error_str.str();
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002613 return false;
2614 }
2615 return true;
2616}
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002617// For buffer descriptor updates, verify the buffer usage and VkDescriptorBufferInfo struct which includes:
2618// 1. buffer is valid
2619// 2. buffer was created with correct usage flags
2620// 3. offset is less than buffer size
2621// 4. range is either VK_WHOLE_SIZE or falls in (0, (buffer size - offset)]
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002622// 5. range and offset are within the device's limits
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002623// 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 -06002624bool CoreChecks::ValidateBufferUpdate(VkDescriptorBufferInfo const *buffer_info, VkDescriptorType type, const char *func_name,
John Zulaufbd9b3412019-08-22 17:16:11 -06002625 std::string *error_code, std::string *error_msg) const {
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002626 // First make sure that buffer is valid
John Zulaufc93c4252019-06-25 09:19:49 -06002627 auto buffer_node = GetBufferState(buffer_info->buffer);
Tobin Ehlisfa8b6182016-12-22 13:40:45 -07002628 // Any invalid buffer should already be caught by object_tracker
2629 assert(buffer_node);
John Zulaufc93c4252019-06-25 09:19:49 -06002630 if (ValidateMemoryIsBoundToBuffer(buffer_node, func_name, "VUID-VkWriteDescriptorSet-descriptorType-00329")) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002631 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00329";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002632 *error_msg = "No memory bound to buffer.";
Tobin Ehlis81280962016-07-20 14:04:20 -06002633 return false;
Tobin Ehlisfed999f2016-09-21 15:09:45 -06002634 }
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002635 // Verify usage bits
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002636 if (!cvdescriptorset::ValidateBufferUsage(report_data, buffer_node, type, error_code, error_msg)) {
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002637 // error_msg will have been updated by ValidateBufferUsage()
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002638 return false;
2639 }
2640 // offset must be less than buffer size
Jeremy Hayesd1a6a822017-03-09 14:39:45 -07002641 if (buffer_info->offset >= buffer_node->createInfo.size) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002642 *error_code = "VUID-VkDescriptorBufferInfo-offset-00340";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002643 std::stringstream error_str;
Jeremy Hayesd1a6a822017-03-09 14:39:45 -07002644 error_str << "VkDescriptorBufferInfo offset of " << buffer_info->offset << " is greater than or equal to buffer "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002645 << report_data->FormatHandle(buffer_node->buffer) << " size of " << buffer_node->createInfo.size;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002646 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002647 return false;
2648 }
2649 if (buffer_info->range != VK_WHOLE_SIZE) {
2650 // Range must be VK_WHOLE_SIZE or > 0
2651 if (!buffer_info->range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002652 *error_code = "VUID-VkDescriptorBufferInfo-range-00341";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002653 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002654 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer)
2655 << " VkDescriptorBufferInfo range is not VK_WHOLE_SIZE and is zero, which is not allowed.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002656 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002657 return false;
2658 }
2659 // Range must be VK_WHOLE_SIZE or <= (buffer size - offset)
2660 if (buffer_info->range > (buffer_node->createInfo.size - buffer_info->offset)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002661 *error_code = "VUID-VkDescriptorBufferInfo-range-00342";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002662 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002663 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer) << " VkDescriptorBufferInfo range is "
2664 << buffer_info->range << " which is greater than buffer size (" << buffer_node->createInfo.size
2665 << ") minus requested offset of " << buffer_info->offset;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002666 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002667 return false;
2668 }
2669 }
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002670 // Check buffer update sizes against device limits
John Zulaufc93c4252019-06-25 09:19:49 -06002671 const auto &limits = phys_dev_props.limits;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002672 if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == type || VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) {
John Zulaufd9435c32019-06-05 15:55:36 -06002673 auto max_ub_range = limits.maxUniformBufferRange;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002674 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_ub_range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002675 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00332";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002676 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002677 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer) << " VkDescriptorBufferInfo range is "
2678 << buffer_info->range << " which is greater than this device's maxUniformBufferRange (" << max_ub_range
2679 << ")";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002680 *error_msg = error_str.str();
2681 return false;
Peter Kohaut2794a292018-07-13 11:13:47 +02002682 } else if (buffer_info->range == VK_WHOLE_SIZE && (buffer_node->createInfo.size - buffer_info->offset) > max_ub_range) {
2683 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00332";
2684 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002685 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer)
2686 << " VkDescriptorBufferInfo range is VK_WHOLE_SIZE but effective range "
Peter Kohaut18f413d2018-07-16 13:15:42 +02002687 << "(" << (buffer_node->createInfo.size - buffer_info->offset) << ") is greater than this device's "
Peter Kohaut2794a292018-07-13 11:13:47 +02002688 << "maxUniformBufferRange (" << max_ub_range << ")";
2689 *error_msg = error_str.str();
2690 return false;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002691 }
2692 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type || VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) {
John Zulaufd9435c32019-06-05 15:55:36 -06002693 auto max_sb_range = limits.maxStorageBufferRange;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002694 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_sb_range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002695 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00333";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002696 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002697 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer) << " VkDescriptorBufferInfo range is "
2698 << buffer_info->range << " which is greater than this device's maxStorageBufferRange (" << max_sb_range
2699 << ")";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002700 *error_msg = error_str.str();
2701 return false;
Peter Kohaut2794a292018-07-13 11:13:47 +02002702 } else if (buffer_info->range == VK_WHOLE_SIZE && (buffer_node->createInfo.size - buffer_info->offset) > max_sb_range) {
2703 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00333";
2704 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002705 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer)
2706 << " VkDescriptorBufferInfo range is VK_WHOLE_SIZE but effective range "
Peter Kohaut18f413d2018-07-16 13:15:42 +02002707 << "(" << (buffer_node->createInfo.size - buffer_info->offset) << ") is greater than this device's "
Peter Kohaut2794a292018-07-13 11:13:47 +02002708 << "maxStorageBufferRange (" << max_sb_range << ")";
2709 *error_msg = error_str.str();
2710 return false;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002711 }
2712 }
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002713 return true;
2714}
sourav parmarcd5fb182020-07-17 12:58:44 -07002715template <typename T>
2716bool CoreChecks::ValidateAccelerationStructureUpdate(T acc_node, const char *func_name, std::string *error_code,
Jeff Bolz95176d02020-04-01 00:36:16 -05002717 std::string *error_msg) const {
Jeff Bolz95176d02020-04-01 00:36:16 -05002718 // Any invalid acc struct should already be caught by object_tracker
2719 assert(acc_node);
2720 if (ValidateMemoryIsBoundToAccelerationStructure(acc_node, func_name, kVUIDUndefined)) {
2721 *error_code = kVUIDUndefined;
2722 *error_msg = "No memory bound to acceleration structure.";
2723 return false;
2724 }
2725 return true;
2726}
2727
Tobin Ehlis300888c2016-05-18 13:43:26 -06002728// Verify that the contents of the update are ok, but don't perform actual update
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002729bool CoreChecks::VerifyCopyUpdateContents(const VkCopyDescriptorSet *update, const DescriptorSet *src_set,
2730 VkDescriptorType src_type, uint32_t src_index, const DescriptorSet *dst_set,
2731 VkDescriptorType dst_type, uint32_t dst_index, const char *func_name,
2732 std::string *error_code, std::string *error_msg) const {
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002733 // Note : Repurposing some Write update error codes here as specific details aren't called out for copy updates like they are
2734 // for write updates
John Zulaufc93c4252019-06-25 09:19:49 -06002735 using DescriptorClass = cvdescriptorset::DescriptorClass;
2736 using BufferDescriptor = cvdescriptorset::BufferDescriptor;
2737 using ImageDescriptor = cvdescriptorset::ImageDescriptor;
2738 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
2739 using SamplerDescriptor = cvdescriptorset::SamplerDescriptor;
2740 using TexelDescriptor = cvdescriptorset::TexelDescriptor;
2741
2742 auto device_data = this;
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002743
2744 if (dst_type == VK_DESCRIPTOR_TYPE_SAMPLER) {
2745 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
2746 const auto dst_desc = dst_set->GetDescriptorFromGlobalIndex(dst_index + di);
2747 if (!dst_desc->updated) continue;
2748 if (dst_desc->IsImmutableSampler()) {
2749 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02753";
2750 std::stringstream error_str;
2751 error_str << "Attempted copy update to an immutable sampler descriptor.";
2752 *error_msg = error_str.str();
2753 return false;
2754 }
2755 }
2756 }
2757
2758 switch (src_set->GetDescriptorFromGlobalIndex(src_index)->descriptor_class) {
John Zulaufc93c4252019-06-25 09:19:49 -06002759 case DescriptorClass::PlainSampler: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002760 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002761 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002762 if (!src_desc->updated) continue;
2763 if (!src_desc->IsImmutableSampler()) {
John Zulaufd9435c32019-06-05 15:55:36 -06002764 auto update_sampler = static_cast<const SamplerDescriptor *>(src_desc)->GetSampler();
John Zulaufc93c4252019-06-25 09:19:49 -06002765 if (!ValidateSampler(update_sampler)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002766 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002767 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002768 error_str << "Attempted copy update to sampler descriptor with invalid sampler: "
2769 << report_data->FormatHandle(update_sampler) << ".";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002770 *error_msg = error_str.str();
2771 return false;
2772 }
2773 } else {
2774 // TODO : Warn here
2775 }
2776 }
2777 break;
2778 }
John Zulaufc93c4252019-06-25 09:19:49 -06002779 case DescriptorClass::ImageSampler: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002780 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002781 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002782 if (!src_desc->updated) continue;
2783 auto img_samp_desc = static_cast<const ImageSamplerDescriptor *>(src_desc);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002784 // First validate sampler
2785 if (!img_samp_desc->IsImmutableSampler()) {
2786 auto update_sampler = img_samp_desc->GetSampler();
John Zulaufc93c4252019-06-25 09:19:49 -06002787 if (!ValidateSampler(update_sampler)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002788 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002789 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002790 error_str << "Attempted copy update to sampler descriptor with invalid sampler: "
2791 << report_data->FormatHandle(update_sampler) << ".";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002792 *error_msg = error_str.str();
2793 return false;
2794 }
2795 } else {
2796 // TODO : Warn here
2797 }
2798 // Validate image
2799 auto image_view = img_samp_desc->GetImageView();
2800 auto image_layout = img_samp_desc->GetImageLayout();
Jeff Bolz165818a2020-05-08 11:19:03 -05002801 if (image_view) {
2802 if (!ValidateImageUpdate(image_view, image_layout, src_type, func_name, error_code, error_msg)) {
2803 std::stringstream error_str;
2804 error_str << "Attempted copy update to combined image sampler descriptor failed due to: "
2805 << error_msg->c_str();
2806 *error_msg = error_str.str();
2807 return false;
2808 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002809 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002810 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002811 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002812 }
John Zulaufc93c4252019-06-25 09:19:49 -06002813 case DescriptorClass::Image: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002814 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002815 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002816 if (!src_desc->updated) continue;
2817 auto img_desc = static_cast<const ImageDescriptor *>(src_desc);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002818 auto image_view = img_desc->GetImageView();
2819 auto image_layout = img_desc->GetImageLayout();
Jeff Bolz165818a2020-05-08 11:19:03 -05002820 if (image_view) {
2821 if (!ValidateImageUpdate(image_view, image_layout, src_type, func_name, error_code, error_msg)) {
2822 std::stringstream error_str;
2823 error_str << "Attempted copy update to image descriptor failed due to: " << error_msg->c_str();
2824 *error_msg = error_str.str();
2825 return false;
2826 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002827 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002828 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002829 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002830 }
John Zulaufc93c4252019-06-25 09:19:49 -06002831 case DescriptorClass::TexelBuffer: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002832 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002833 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002834 if (!src_desc->updated) continue;
John Zulaufd9435c32019-06-05 15:55:36 -06002835 auto buffer_view = static_cast<const TexelDescriptor *>(src_desc)->GetBufferView();
Jeff Bolz165818a2020-05-08 11:19:03 -05002836 if (buffer_view) {
2837 auto bv_state = device_data->GetBufferViewState(buffer_view);
2838 if (!bv_state) {
2839 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
2840 std::stringstream error_str;
2841 error_str << "Attempted copy update to texel buffer descriptor with invalid buffer view: "
2842 << report_data->FormatHandle(buffer_view);
2843 *error_msg = error_str.str();
2844 return false;
2845 }
2846 auto buffer = bv_state->create_info.buffer;
2847 if (!cvdescriptorset::ValidateBufferUsage(report_data, GetBufferState(buffer), src_type, error_code,
2848 error_msg)) {
2849 std::stringstream error_str;
2850 error_str << "Attempted copy update to texel buffer descriptor failed due to: " << error_msg->c_str();
2851 *error_msg = error_str.str();
2852 return false;
2853 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002854 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002855 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002856 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002857 }
John Zulaufc93c4252019-06-25 09:19:49 -06002858 case DescriptorClass::GeneralBuffer: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002859 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002860 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002861 if (!src_desc->updated) continue;
John Zulaufd9435c32019-06-05 15:55:36 -06002862 auto buffer = static_cast<const BufferDescriptor *>(src_desc)->GetBuffer();
Jeff Bolz165818a2020-05-08 11:19:03 -05002863 if (buffer) {
2864 if (!cvdescriptorset::ValidateBufferUsage(report_data, GetBufferState(buffer), src_type, error_code,
2865 error_msg)) {
2866 std::stringstream error_str;
2867 error_str << "Attempted copy update to buffer descriptor failed due to: " << error_msg->c_str();
2868 *error_msg = error_str.str();
2869 return false;
2870 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002871 }
Tobin Ehliscbcf2342016-05-24 13:07:12 -06002872 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002873 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002874 }
John Zulaufc93c4252019-06-25 09:19:49 -06002875 case DescriptorClass::InlineUniform:
2876 case DescriptorClass::AccelerationStructure:
Jeff Bolze54ae892018-09-08 12:16:29 -05002877 break;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002878 default:
2879 assert(0); // We've already verified update type so should never get here
2880 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002881 }
2882 // All checks passed so update contents are good
2883 return true;
Chris Forbesb4e0bdb2016-05-31 16:34:40 +12002884}
Tobin Ehlisee471462016-05-26 11:21:59 -06002885// Verify that the state at allocate time is correct, but don't actually allocate the sets yet
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002886bool CoreChecks::ValidateAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *p_alloc_info,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05002887 const cvdescriptorset::AllocateDescriptorSetsData *ds_data) const {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002888 bool skip = false;
Mark Lobodzinski7804bd42019-03-06 11:28:48 -07002889 auto pool_state = GetDescriptorPoolState(p_alloc_info->descriptorPool);
Tobin Ehlisee471462016-05-26 11:21:59 -06002890
2891 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
Jeff Bolz6ae39612019-10-11 20:57:36 -05002892 auto layout = GetDescriptorSetLayoutShared(p_alloc_info->pSetLayouts[i]);
John Zulauf5562d062018-01-24 11:54:05 -07002893 if (layout) { // nullptr layout indicates no valid layout handle for this device, validated/logged in object_tracker
John Zulauf1d27e0a2018-11-05 10:12:48 -07002894 if (layout->IsPushDescriptor()) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002895 skip |= LogError(p_alloc_info->pSetLayouts[i], "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-00308",
2896 "%s specified at pSetLayouts[%" PRIu32
2897 "] in vkAllocateDescriptorSets() was created with invalid flag %s set.",
2898 report_data->FormatHandle(p_alloc_info->pSetLayouts[i]).c_str(), i,
2899 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR");
John Zulauf5562d062018-01-24 11:54:05 -07002900 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05002901 if (layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT &&
2902 !(pool_state->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002903 skip |= LogError(device, "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-03044",
2904 "Descriptor set layout create flags and pool create flags mismatch for index (%d)", i);
Jeff Bolzfdf96072018-04-10 14:32:18 -05002905 }
Tobin Ehlisee471462016-05-26 11:21:59 -06002906 }
2907 }
Mark Lobodzinskif45e45f2019-04-19 14:15:39 -06002908 if (!device_extensions.vk_khr_maintenance1) {
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06002909 // Track number of descriptorSets allowable in this pool
2910 if (pool_state->availableSets < p_alloc_info->descriptorSetCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002911 skip |= LogError(pool_state->pool, "VUID-VkDescriptorSetAllocateInfo-descriptorSetCount-00306",
2912 "Unable to allocate %u descriptorSets from %s"
2913 ". This pool only has %d descriptorSets remaining.",
2914 p_alloc_info->descriptorSetCount, report_data->FormatHandle(pool_state->pool).c_str(),
2915 pool_state->availableSets);
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06002916 }
2917 // Determine whether descriptor counts are satisfiable
Jeff Bolze54ae892018-09-08 12:16:29 -05002918 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 -05002919 auto count_iter = pool_state->availableDescriptorTypeCount.find(it->first);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002920 uint32_t available_count = (count_iter != pool_state->availableDescriptorTypeCount.end()) ? count_iter->second : 0;
Jeff Bolz46c0ea02019-10-09 13:06:29 -05002921
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002922 if (ds_data->required_descriptors_by_type.at(it->first) > available_count) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002923 skip |= LogError(pool_state->pool, "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307",
2924 "Unable to allocate %u descriptors of type %s from %s"
2925 ". This pool only has %d descriptors of this type remaining.",
2926 ds_data->required_descriptors_by_type.at(it->first),
2927 string_VkDescriptorType(VkDescriptorType(it->first)),
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002928 report_data->FormatHandle(pool_state->pool).c_str(), available_count);
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06002929 }
Tobin Ehlisee471462016-05-26 11:21:59 -06002930 }
2931 }
Tobin Ehlis5d749ea2016-07-18 13:14:01 -06002932
Jeff Bolzfdf96072018-04-10 14:32:18 -05002933 const auto *count_allocate_info = lvl_find_in_chain<VkDescriptorSetVariableDescriptorCountAllocateInfoEXT>(p_alloc_info->pNext);
2934
2935 if (count_allocate_info) {
2936 if (count_allocate_info->descriptorSetCount != 0 &&
2937 count_allocate_info->descriptorSetCount != p_alloc_info->descriptorSetCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002938 skip |= LogError(device, "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfo-descriptorSetCount-03045",
2939 "VkDescriptorSetAllocateInfo::descriptorSetCount (%d) != "
2940 "VkDescriptorSetVariableDescriptorCountAllocateInfoEXT::descriptorSetCount (%d)",
2941 p_alloc_info->descriptorSetCount, count_allocate_info->descriptorSetCount);
Jeff Bolzfdf96072018-04-10 14:32:18 -05002942 }
2943 if (count_allocate_info->descriptorSetCount == p_alloc_info->descriptorSetCount) {
2944 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
Jeff Bolz6ae39612019-10-11 20:57:36 -05002945 auto layout = GetDescriptorSetLayoutShared(p_alloc_info->pSetLayouts[i]);
Jeff Bolzfdf96072018-04-10 14:32:18 -05002946 if (count_allocate_info->pDescriptorCounts[i] > layout->GetDescriptorCountFromBinding(layout->GetMaxBinding())) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07002947 skip |= LogError(device, "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfo-pSetLayouts-03046",
2948 "pDescriptorCounts[%d] = (%d), binding's descriptorCount = (%d)", i,
2949 count_allocate_info->pDescriptorCounts[i],
2950 layout->GetDescriptorCountFromBinding(layout->GetMaxBinding()));
Jeff Bolzfdf96072018-04-10 14:32:18 -05002951 }
2952 }
2953 }
2954 }
2955
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002956 return skip;
Tobin Ehlisee471462016-05-26 11:21:59 -06002957}
John Zulauf48a6a702017-12-22 17:14:54 -07002958
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05002959const BindingReqMap &cvdescriptorset::PrefilterBindRequestMap::FilteredMap(const CMD_BUFFER_STATE &cb_state,
2960 const PIPELINE_STATE &pipeline) {
John Zulauffbf3c202019-07-17 14:57:14 -06002961 if (IsManyDescriptors()) {
Karl Schultz7090a052020-11-10 08:54:21 -07002962 filtered_map_.reset(new BindingReqMap);
John Zulauffbf3c202019-07-17 14:57:14 -06002963 descriptor_set_.FilterBindingReqs(cb_state, pipeline, orig_map_, filtered_map_.get());
2964 return *filtered_map_;
John Zulauf48a6a702017-12-22 17:14:54 -07002965 }
John Zulauffbf3c202019-07-17 14:57:14 -06002966 return orig_map_;
Artem Kharytoniuk2456f992018-01-12 14:17:41 +01002967}
John Zulauf4a015c92019-06-04 09:50:05 -06002968
2969// Starting at offset descriptor of given binding, parse over update_count
2970// descriptor updates and verify that for any binding boundaries that are crossed, the next binding(s) are all consistent
2971// Consistency means that their type, stage flags, and whether or not they use immutable samplers matches
2972// If so, return true. If not, fill in error_msg and return false
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002973bool cvdescriptorset::VerifyUpdateConsistency(debug_report_data *report_data,
2974 DescriptorSetLayout::ConstBindingIterator current_binding, uint32_t offset,
John Zulauf4a015c92019-06-04 09:50:05 -06002975 uint32_t update_count, const char *type, const VkDescriptorSet set,
2976 std::string *error_msg) {
locke-lunarge46b7782019-09-10 01:44:20 -06002977 bool pass = true;
John Zulauf4a015c92019-06-04 09:50:05 -06002978 // Verify consecutive bindings match (if needed)
2979 auto orig_binding = current_binding;
locke-lunarge46b7782019-09-10 01:44:20 -06002980
2981 while (pass && update_count) {
2982 // First, it's legal to offset beyond your own binding so handle that case
2983 if (offset > 0) {
2984 const auto &index_range = current_binding.GetGlobalIndexRange();
2985 // index_range.start + offset is which descriptor is needed to update. If it > index_range.end, it means the descriptor
2986 // isn't in this binding, maybe in next binding.
2987 if ((index_range.start + offset) >= index_range.end) {
2988 // Advance to next binding, decrement offset by binding size
2989 offset -= current_binding.GetDescriptorCount();
2990 ++current_binding;
2991 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
2992 if (!orig_binding.IsConsistent(current_binding)) {
2993 pass = false;
2994 }
2995 continue;
John Zulauf4a015c92019-06-04 09:50:05 -06002996 }
John Zulauf4a015c92019-06-04 09:50:05 -06002997 }
locke-lunarge46b7782019-09-10 01:44:20 -06002998
2999 update_count -= std::min(update_count, current_binding.GetDescriptorCount() - offset);
3000 if (update_count) {
3001 // Starting offset is beyond the current binding. Check consistency, update counters and advance to the next binding,
3002 // looking for the start point. All bindings (even those skipped) must be consistent with the update and with the
3003 // original binding.
3004 offset = 0;
3005 ++current_binding;
3006 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
3007 if (!orig_binding.IsConsistent(current_binding)) {
3008 pass = false;
3009 }
3010 }
John Zulauf4a015c92019-06-04 09:50:05 -06003011 }
locke-lunarge46b7782019-09-10 01:44:20 -06003012
3013 if (!pass) {
3014 std::stringstream error_str;
3015 error_str << "Attempting " << type;
3016 if (current_binding.Layout()->IsPushDescriptor()) {
3017 error_str << " push descriptors";
3018 } else {
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003019 error_str << " descriptor set " << report_data->FormatHandle(set);
locke-lunarge46b7782019-09-10 01:44:20 -06003020 }
3021 error_str << " binding #" << orig_binding.Binding() << " with #" << update_count
3022 << " descriptors being updated but this update oversteps the bounds of this binding and the next binding is "
3023 "not consistent with current binding so this update is invalid.";
3024 *error_msg = error_str.str();
3025 }
3026 return pass;
John Zulauf4a015c92019-06-04 09:50:05 -06003027}
John Zulauf4956fff2019-06-04 16:54:38 -06003028
3029// Validate the state for a given write update but don't actually perform the update
3030// 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 -06003031bool CoreChecks::ValidateWriteUpdate(const DescriptorSet *dest_set, const VkWriteDescriptorSet *update, const char *func_name,
John Zulaufbd9b3412019-08-22 17:16:11 -06003032 std::string *error_code, std::string *error_msg) const {
Jeff Bolz6aad1742019-10-16 11:10:09 -05003033 const auto dest_layout = dest_set->GetLayout().get();
John Zulauf4956fff2019-06-04 16:54:38 -06003034
3035 // Verify dst layout still valid
Jeff Bolz6ae39612019-10-11 20:57:36 -05003036 if (dest_layout->destroyed) {
John Zulauf4956fff2019-06-04 16:54:38 -06003037 *error_code = "VUID-VkWriteDescriptorSet-dstSet-00320";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06003038 std::ostringstream str;
3039 str << "Cannot call " << func_name << " to perform write update on " << dest_set->StringifySetAndLayout()
3040 << " which has been destroyed";
3041 *error_msg = str.str();
John Zulauf4956fff2019-06-04 16:54:38 -06003042 return false;
3043 }
3044 // Verify dst binding exists
3045 if (!dest_layout->HasBinding(update->dstBinding)) {
3046 *error_code = "VUID-VkWriteDescriptorSet-dstBinding-00315";
3047 std::stringstream error_str;
3048 error_str << dest_set->StringifySetAndLayout() << " does not have binding " << update->dstBinding;
3049 *error_msg = error_str.str();
3050 return false;
3051 }
3052
Jeff Bolz6aad1742019-10-16 11:10:09 -05003053 DescriptorSetLayout::ConstBindingIterator dest(dest_layout, update->dstBinding);
John Zulauf4956fff2019-06-04 16:54:38 -06003054 // Make sure binding isn't empty
3055 if (0 == dest.GetDescriptorCount()) {
3056 *error_code = "VUID-VkWriteDescriptorSet-dstBinding-00316";
3057 std::stringstream error_str;
3058 error_str << dest_set->StringifySetAndLayout() << " cannot updated binding " << update->dstBinding
3059 << " that has 0 descriptors";
3060 *error_msg = error_str.str();
3061 return false;
3062 }
3063
3064 // Verify idle ds
3065 if (dest_set->in_use.load() && !(dest.GetDescriptorBindingFlags() & (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT |
3066 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) {
3067 // TODO : Re-using Free Idle error code, need write update idle error code
3068 *error_code = "VUID-vkFreeDescriptorSets-pDescriptorSets-00309";
3069 std::stringstream error_str;
3070 error_str << "Cannot call " << func_name << " to perform write update on " << dest_set->StringifySetAndLayout()
3071 << " that is in use by a command buffer";
3072 *error_msg = error_str.str();
3073 return false;
3074 }
3075 // We know that binding is valid, verify update and do update on each descriptor
3076 auto start_idx = dest.GetGlobalIndexRange().start + update->dstArrayElement;
3077 auto type = dest.GetType();
3078 if (type != update->descriptorType) {
3079 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00319";
3080 std::stringstream error_str;
3081 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3082 << " with type " << string_VkDescriptorType(type) << " but update type is "
3083 << string_VkDescriptorType(update->descriptorType);
3084 *error_msg = error_str.str();
3085 return false;
3086 }
John Zulauf4956fff2019-06-04 16:54:38 -06003087 if (type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
3088 if ((update->dstArrayElement % 4) != 0) {
3089 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02219";
3090 std::stringstream error_str;
3091 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3092 << " with "
3093 << "dstArrayElement " << update->dstArrayElement << " not a multiple of 4";
3094 *error_msg = error_str.str();
3095 return false;
3096 }
3097 if ((update->descriptorCount % 4) != 0) {
3098 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02220";
3099 std::stringstream error_str;
3100 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3101 << " with "
3102 << "descriptorCount " << update->descriptorCount << " not a multiple of 4";
3103 *error_msg = error_str.str();
3104 return false;
3105 }
3106 const auto *write_inline_info = lvl_find_in_chain<VkWriteDescriptorSetInlineUniformBlockEXT>(update->pNext);
3107 if (!write_inline_info || write_inline_info->dataSize != update->descriptorCount) {
3108 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02221";
3109 std::stringstream error_str;
3110 if (!write_inline_info) {
3111 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #"
3112 << update->dstBinding << " with "
3113 << "VkWriteDescriptorSetInlineUniformBlockEXT missing";
3114 } else {
3115 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #"
3116 << update->dstBinding << " with "
3117 << "VkWriteDescriptorSetInlineUniformBlockEXT dataSize " << write_inline_info->dataSize
3118 << " not equal to "
3119 << "VkWriteDescriptorSet descriptorCount " << update->descriptorCount;
3120 }
3121 *error_msg = error_str.str();
3122 return false;
3123 }
3124 // This error is probably unreachable due to the previous two errors
3125 if (write_inline_info && (write_inline_info->dataSize % 4) != 0) {
3126 *error_code = "VUID-VkWriteDescriptorSetInlineUniformBlockEXT-dataSize-02222";
3127 std::stringstream error_str;
3128 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3129 << " with "
3130 << "VkWriteDescriptorSetInlineUniformBlockEXT dataSize " << write_inline_info->dataSize
3131 << " not a multiple of 4";
3132 *error_msg = error_str.str();
3133 return false;
3134 }
3135 }
sfricke-samsung941d48b2020-02-10 00:20:01 -08003136 // Verify all bindings update share identical properties across all items
3137 if (update->descriptorCount > 0) {
3138 // Save first binding information and error if something different is found
3139 DescriptorSetLayout::ConstBindingIterator current_binding(dest_layout, update->dstBinding);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003140 VkShaderStageFlags stage_flags = current_binding.GetStageFlags();
3141 VkDescriptorType descriptor_type = current_binding.GetType();
3142 bool immutable_samplers = (current_binding.GetImmutableSamplerPtr() == nullptr);
3143 uint32_t dst_array_element = update->dstArrayElement;
sfricke-samsung941d48b2020-02-10 00:20:01 -08003144
Jeff Bolz9198e882020-03-18 13:03:30 -05003145 for (uint32_t i = 0; i < update->descriptorCount;) {
sfricke-samsung941d48b2020-02-10 00:20:01 -08003146 if (current_binding.AtEnd() == true) {
3147 break; // prevents setting error here if bindings don't exist
3148 }
3149
3150 // Check for consistent stageFlags and descriptorType
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003151 if ((current_binding.GetStageFlags() != stage_flags) || (current_binding.GetType() != descriptor_type)) {
sfricke-samsung941d48b2020-02-10 00:20:01 -08003152 *error_code = "VUID-VkWriteDescriptorSet-descriptorCount-00317";
3153 std::stringstream error_str;
3154 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3155 << current_binding.GetIndex() << " (" << i << " from dstBinding offset)"
3156 << " with a different stageFlag and/or descriptorType from previous bindings."
3157 << " All bindings must have consecutive stageFlag and/or descriptorType across a VkWriteDescriptorSet";
3158 *error_msg = error_str.str();
3159 return false;
3160 }
3161 // Check if all immutableSamplers or not
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003162 if ((current_binding.GetImmutableSamplerPtr() == nullptr) != immutable_samplers) {
sfricke-samsung941d48b2020-02-10 00:20:01 -08003163 *error_code = "VUID-VkWriteDescriptorSet-descriptorCount-00318";
3164 std::stringstream error_str;
3165 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3166 << current_binding.GetIndex() << " (" << i << " from dstBinding offset)"
3167 << " with a different usage of immutable samplers from previous bindings."
3168 << " All bindings must have all or none usage of immutable samplers across a VkWriteDescriptorSet";
3169 *error_msg = error_str.str();
3170 return false;
3171 }
Jeff Bolz9198e882020-03-18 13:03:30 -05003172
3173 // Skip the remaining descriptors for this binding, and move to the next binding
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003174 i += (current_binding.GetDescriptorCount() - dst_array_element);
3175 dst_array_element = 0;
sfricke-samsung941d48b2020-02-10 00:20:01 -08003176 ++current_binding;
3177 }
3178 }
3179
John Zulauf4956fff2019-06-04 16:54:38 -06003180 // Verify consecutive bindings match (if needed)
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003181 if (!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(dest_layout, update->dstBinding),
John Zulauf4956fff2019-06-04 16:54:38 -06003182 update->dstArrayElement, update->descriptorCount, "write update to", dest_set->GetSet(),
3183 error_msg)) {
3184 // TODO : Should break out "consecutive binding updates" language into valid usage statements
3185 *error_code = "VUID-VkWriteDescriptorSet-dstArrayElement-00321";
3186 return false;
3187 }
Tony-LunarG1f79c952020-10-27 15:55:51 -06003188 // Verify write to variable descriptor
3189 if (dest_set->IsVariableDescriptorCount(update->dstBinding)) {
3190 if ((update->dstArrayElement + update->descriptorCount) > dest_set->GetVariableDescriptorCount()) {
3191 std::stringstream error_str;
3192 *error_code = "VUID-VkWriteDescriptorSet-dstArrayElement-00321";
3193 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3194 << update->dstBinding << " array element " << update->dstArrayElement << " with " << update->descriptorCount
3195 << " writes but variable descriptor size is " << dest_set->GetVariableDescriptorCount();
3196 *error_msg = error_str.str();
3197 return false;
3198 }
3199 }
John Zulauf4956fff2019-06-04 16:54:38 -06003200 // Update is within bounds and consistent so last step is to validate update contents
John Zulauf459939f2019-06-04 16:49:35 -06003201 if (!VerifyWriteUpdateContents(dest_set, update, start_idx, func_name, error_code, error_msg)) {
John Zulauf4956fff2019-06-04 16:54:38 -06003202 std::stringstream error_str;
3203 error_str << "Write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3204 << " failed with error message: " << error_msg->c_str();
3205 *error_msg = error_str.str();
3206 return false;
3207 }
3208 // All checks passed, update is clean
3209 return true;
3210}
John Zulaufadb3f542019-06-04 17:01:00 -06003211
3212// Verify that the contents of the update are ok, but don't perform actual update
John Zulaufc93c4252019-06-25 09:19:49 -06003213bool CoreChecks::VerifyWriteUpdateContents(const DescriptorSet *dest_set, const VkWriteDescriptorSet *update, const uint32_t index,
John Zulaufbd9b3412019-08-22 17:16:11 -06003214 const char *func_name, std::string *error_code, std::string *error_msg) const {
John Zulaufc93c4252019-06-25 09:19:49 -06003215 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
Nathaniel Cesarioff521512020-12-11 16:00:26 -07003216 using Descriptor = cvdescriptorset::Descriptor;
John Zulaufc93c4252019-06-25 09:19:49 -06003217
John Zulaufadb3f542019-06-04 17:01:00 -06003218 switch (update->descriptorType) {
3219 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
3220 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3221 // Validate image
3222 auto image_view = update->pImageInfo[di].imageView;
3223 auto image_layout = update->pImageInfo[di].imageLayout;
Mark Lobodzinski3ca937b2020-02-14 14:56:06 -07003224 auto sampler = update->pImageInfo[di].sampler;
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003225 auto iv_state = GetImageViewState(image_view);
Nathaniel Cesarioff521512020-12-11 16:00:26 -07003226 const ImageSamplerDescriptor *desc =
3227 (const ImageSamplerDescriptor *)dest_set->GetDescriptorFromGlobalIndex(index + di);
Jeff Bolz165818a2020-05-08 11:19:03 -05003228 if (image_view) {
3229 auto image_state = iv_state->image_state.get();
3230 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, func_name, error_code, error_msg)) {
3231 std::stringstream error_str;
3232 error_str << "Attempted write update to combined image sampler descriptor failed due to: "
3233 << error_msg->c_str();
3234 *error_msg = error_str.str();
3235 return false;
3236 }
3237 if (device_extensions.vk_khr_sampler_ycbcr_conversion) {
3238 if (desc->IsImmutableSampler()) {
3239 auto sampler_state = GetSamplerState(desc->GetSampler());
3240 if (iv_state && sampler_state) {
3241 if (iv_state->samplerConversion != sampler_state->samplerConversion) {
3242 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-01948";
3243 std::stringstream error_str;
3244 error_str
3245 << "Attempted write update to combined image sampler and image view and sampler ycbcr "
3246 "conversions are not identical, sampler: "
3247 << report_data->FormatHandle(desc->GetSampler())
3248 << " image view: " << report_data->FormatHandle(iv_state->image_view) << ".";
3249 *error_msg = error_str.str();
3250 return false;
3251 }
3252 }
3253 } else {
3254 if (iv_state && (iv_state->samplerConversion != VK_NULL_HANDLE)) {
3255 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02738";
John Zulaufadb3f542019-06-04 17:01:00 -06003256 std::stringstream error_str;
Jeff Bolz165818a2020-05-08 11:19:03 -05003257 error_str << "Because dstSet (" << report_data->FormatHandle(update->dstSet)
3258 << ") is bound to image view (" << report_data->FormatHandle(iv_state->image_view)
3259 << ") that includes a YCBCR conversion, it must have been allocated with a layout that "
3260 "includes an immutable sampler.";
John Zulaufadb3f542019-06-04 17:01:00 -06003261 *error_msg = error_str.str();
3262 return false;
3263 }
3264 }
Jeff Bolz165818a2020-05-08 11:19:03 -05003265 }
John Baumanda8abff2020-10-19 21:25:21 +00003266 // If there is an immutable sampler then |sampler| isn't used, so the following VU does not apply.
3267 if (sampler && !desc->IsImmutableSampler() && FormatIsMultiplane(image_state->createInfo.format)) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003268 // multiplane formats must be created with mutable format bit
3269 if (0 == (image_state->createInfo.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) {
3270 *error_code = "VUID-VkDescriptorImageInfo-sampler-01564";
John Zulaufadb3f542019-06-04 17:01:00 -06003271 std::stringstream error_str;
Jeff Bolz165818a2020-05-08 11:19:03 -05003272 error_str << "image " << report_data->FormatHandle(image_state->image)
3273 << " combined image sampler is a multi-planar "
3274 << "format and was not was not created with the VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT";
John Zulaufadb3f542019-06-04 17:01:00 -06003275 *error_msg = error_str.str();
3276 return false;
3277 }
Jeff Bolz165818a2020-05-08 11:19:03 -05003278 // image view need aspect mask for only the planes supported of format
3279 VkImageAspectFlags legal_aspect_flags = (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT);
3280 legal_aspect_flags |=
3281 (FormatPlaneCount(image_state->createInfo.format) == 3) ? VK_IMAGE_ASPECT_PLANE_2_BIT : 0;
3282 if (0 != (iv_state->create_info.subresourceRange.aspectMask & (~legal_aspect_flags))) {
3283 *error_code = "VUID-VkDescriptorImageInfo-sampler-01564";
3284 std::stringstream error_str;
3285 error_str << "image " << report_data->FormatHandle(image_state->image)
3286 << " combined image sampler is a multi-planar "
3287 << "format and " << report_data->FormatHandle(iv_state->image_view)
3288 << " aspectMask must only include " << string_VkImageAspectFlags(legal_aspect_flags);
3289 *error_msg = error_str.str();
3290 return false;
3291 }
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003292 }
Nathaniel Cesario23afadd2020-11-17 12:51:45 -07003293
3294 // Verify portability
3295 auto sampler_state = GetSamplerState(sampler);
3296 if (sampler_state) {
3297 if (ExtEnabled::kNotEnabled != device_extensions.vk_khr_portability_subset) {
3298 if ((VK_FALSE == enabled_features.portability_subset_features.mutableComparisonSamplers) &&
3299 (VK_FALSE != sampler_state->createInfo.compareEnable)) {
3300 LogError(device, "VUID-VkDescriptorImageInfo-mutableComparisonSamplers-04450",
3301 "%s (portability error): sampler comparison not available.", func_name);
3302 }
3303 }
3304 }
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003305 }
John Zulaufadb3f542019-06-04 17:01:00 -06003306 }
3307 }
Mark Lobodzinskiac727772020-01-08 10:47:30 -07003308 // Fall through
John Zulaufadb3f542019-06-04 17:01:00 -06003309 case VK_DESCRIPTOR_TYPE_SAMPLER: {
3310 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003311 const auto *desc = static_cast<const Descriptor *>(dest_set->GetDescriptorFromGlobalIndex(index + di));
John Zulaufadb3f542019-06-04 17:01:00 -06003312 if (!desc->IsImmutableSampler()) {
John Zulaufc93c4252019-06-25 09:19:49 -06003313 if (!ValidateSampler(update->pImageInfo[di].sampler)) {
John Zulaufadb3f542019-06-04 17:01:00 -06003314 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
3315 std::stringstream error_str;
3316 error_str << "Attempted write update to sampler descriptor with invalid sampler: "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003317 << report_data->FormatHandle(update->pImageInfo[di].sampler) << ".";
John Zulaufadb3f542019-06-04 17:01:00 -06003318 *error_msg = error_str.str();
3319 return false;
3320 }
Mark Lobodzinskiac727772020-01-08 10:47:30 -07003321 } else if (update->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003322 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02752";
3323 std::stringstream error_str;
3324 error_str << "Attempted write update to an immutable sampler descriptor.";
3325 *error_msg = error_str.str();
3326 return false;
John Zulaufadb3f542019-06-04 17:01:00 -06003327 }
3328 }
3329 break;
3330 }
3331 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
3332 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
3333 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
3334 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3335 auto image_view = update->pImageInfo[di].imageView;
3336 auto image_layout = update->pImageInfo[di].imageLayout;
Jeff Bolz165818a2020-05-08 11:19:03 -05003337 if (image_view) {
3338 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, func_name, error_code, error_msg)) {
3339 std::stringstream error_str;
3340 error_str << "Attempted write update to image descriptor failed due to: " << error_msg->c_str();
3341 *error_msg = error_str.str();
3342 return false;
3343 }
John Zulaufadb3f542019-06-04 17:01:00 -06003344 }
3345 }
3346 break;
3347 }
3348 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
3349 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
3350 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3351 auto buffer_view = update->pTexelBufferView[di];
Jeff Bolz165818a2020-05-08 11:19:03 -05003352 if (buffer_view) {
3353 auto bv_state = GetBufferViewState(buffer_view);
3354 if (!bv_state) {
3355 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
3356 std::stringstream error_str;
3357 error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: "
3358 << report_data->FormatHandle(buffer_view);
3359 *error_msg = error_str.str();
3360 return false;
3361 }
3362 auto buffer = bv_state->create_info.buffer;
3363 auto buffer_state = GetBufferState(buffer);
3364 // Verify that buffer underlying the view hasn't been destroyed prematurely
3365 if (!buffer_state) {
3366 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
3367 std::stringstream error_str;
3368 error_str << "Attempted write update to texel buffer descriptor failed because underlying buffer ("
3369 << report_data->FormatHandle(buffer) << ") has been destroyed: " << error_msg->c_str();
3370 *error_msg = error_str.str();
3371 return false;
3372 } else if (!cvdescriptorset::ValidateBufferUsage(report_data, buffer_state, update->descriptorType, error_code,
3373 error_msg)) {
3374 std::stringstream error_str;
3375 error_str << "Attempted write update to texel buffer descriptor failed due to: " << error_msg->c_str();
3376 *error_msg = error_str.str();
3377 return false;
3378 }
John Zulaufadb3f542019-06-04 17:01:00 -06003379 }
3380 }
3381 break;
3382 }
3383 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
3384 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
3385 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
3386 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
3387 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003388 if (update->pBufferInfo[di].buffer) {
3389 if (!ValidateBufferUpdate(update->pBufferInfo + di, update->descriptorType, func_name, error_code, error_msg)) {
3390 std::stringstream error_str;
3391 error_str << "Attempted write update to buffer descriptor failed due to: " << error_msg->c_str();
3392 *error_msg = error_str.str();
3393 return false;
3394 }
John Zulaufadb3f542019-06-04 17:01:00 -06003395 }
3396 }
3397 break;
3398 }
3399 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
3400 break;
Jeff Bolz95176d02020-04-01 00:36:16 -05003401 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003402 const auto *acc_info = lvl_find_in_chain<VkWriteDescriptorSetAccelerationStructureNV>(update->pNext);
Jeff Bolz95176d02020-04-01 00:36:16 -05003403 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003404 if (!ValidateAccelerationStructureUpdate(GetAccelerationStructureStateNV(acc_info->pAccelerationStructures[di]),
Mark Lobodzinski85ebd402020-12-03 12:56:07 -07003405 func_name, error_code, error_msg)) {
Jeff Bolz95176d02020-04-01 00:36:16 -05003406 std::stringstream error_str;
3407 error_str << "Attempted write update to acceleration structure descriptor failed due to: "
3408 << error_msg->c_str();
3409 *error_msg = error_str.str();
3410 return false;
3411 }
3412 }
3413
3414 } break;
sourav parmarcd5fb182020-07-17 12:58:44 -07003415 // KHR acceleration structures don't require memory to be bound manually to them.
3416 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
3417 break;
John Zulaufadb3f542019-06-04 17:01:00 -06003418 default:
3419 assert(0); // We've already verified update type so should never get here
3420 break;
3421 }
3422 // All checks passed so update contents are good
3423 return true;
3424}