blob: 4638fa2746b2c7f668fa024caf5e57071bcc326c [file] [log] [blame]
sfricke-samsung691299b2021-01-01 20:48:48 -08001/* Copyright (c) 2015-2021 The Khronos Group Inc.
2 * Copyright (c) 2015-2021 Valve Corporation
3 * Copyright (c) 2015-2021 LunarG, Inc.
4 * Copyright (C) 2015-2021 Google Inc.
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06005 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Tobin Ehlis <tobine@google.com>
John Zulaufc483f442017-12-15 14:02:06 -070019 * John Zulauf <jzulauf@lunarg.com>
Jeremy Kniagere6827432020-04-01 09:05:56 -060020 * Jeremy Kniager <jeremyk@lunarg.com>
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060021 */
22
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -070023#include "chassis.h"
Mark Lobodzinski76d76662019-02-14 14:38:21 -070024#include "core_validation_error_enums.h"
25#include "core_validation.h"
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060026#include "descriptor_sets.h"
John Zulaufd47d0612018-02-16 13:00:34 -070027#include "hash_vk_types.h"
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060028#include "vk_enum_string_helper.h"
29#include "vk_safe_struct.h"
Jeff Bolzfdf96072018-04-10 14:32:18 -050030#include "vk_typemap_helper.h"
Tobin Ehlisc8266452017-04-07 12:20:30 -060031#include "buffer_validation.h"
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060032#include <sstream>
Mark Lobodzinski2eee5d82016-12-02 15:33:18 -070033#include <algorithm>
John Zulauff4c07882019-01-24 14:03:36 -070034#include <array>
John Zulauf1f8174b2018-02-16 12:58:37 -070035#include <memory>
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060036
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 {
Mike Schuchardt2df08912020-12-15 16:28:09 -080041 ExtendedBinding(const VkDescriptorSetLayoutBinding *l, VkDescriptorBindingFlags f) : layout_binding(l), binding_flags(f) {}
Jeff Bolzfdf96072018-04-10 14:32:18 -050042
43 const VkDescriptorSetLayoutBinding *layout_binding;
Mike Schuchardt2df08912020-12-15 16:28:09 -080044 VkDescriptorBindingFlags binding_flags;
Jeff Bolzfdf96072018-04-10 14:32:18 -050045};
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) {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -070069 const auto *flags_create_info = LvlFindInChain<VkDescriptorSetLayoutBindingFlagsCreateInfo>(p_create_info->pNext);
Jeff Bolzfdf96072018-04-10 14:32:18 -050070
sfricke-samsung0d00aed2021-03-08 23:31:17 -080071 binding_type_stats_ = {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++) {
Mike Schuchardt2df08912020-12-15 16:28:09 -080076 VkDescriptorBindingFlags flags = 0;
Jeff Bolzfdf96072018-04-10 14:32:18 -050077 if (flags_create_info && flags_create_info->bindingCount == p_create_info->bindingCount) {
78 flags = flags_create_info->pBindingFlags[i];
79 }
Jeremy Gebbenfc6f8152021-03-18 16:58:55 -060080 sorted_bindings.emplace(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
John Zulauf508d13a2018-01-05 15:10:34 -070084 uint32_t index = 0;
85 binding_count_ = static_cast<uint32_t>(sorted_bindings.size());
86 bindings_.reserve(binding_count_);
Jeff Bolzfdf96072018-04-10 14:32:18 -050087 binding_flags_.reserve(binding_count_);
John Zulauf508d13a2018-01-05 15:10:34 -070088 binding_to_index_map_.reserve(binding_count_);
John Zulauf79f06582021-02-27 18:38:39 -070089 for (const auto &input_binding : sorted_bindings) {
John Zulauf508d13a2018-01-05 15:10:34 -070090 // Add to binding and map, s.t. it is robust to invalid duplication of binding_num
Jeff Bolzfdf96072018-04-10 14:32:18 -050091 const auto binding_num = input_binding.layout_binding->binding;
John Zulauf508d13a2018-01-05 15:10:34 -070092 binding_to_index_map_[binding_num] = index++;
Jeff Bolzfdf96072018-04-10 14:32:18 -050093 bindings_.emplace_back(input_binding.layout_binding);
John Zulauf508d13a2018-01-05 15:10:34 -070094 auto &binding_info = bindings_.back();
Jeff Bolzfdf96072018-04-10 14:32:18 -050095 binding_flags_.emplace_back(input_binding.binding_flags);
John Zulauf508d13a2018-01-05 15:10:34 -070096
John Zulaufb6d71202017-12-22 16:47:09 -070097 descriptor_count_ += binding_info.descriptorCount;
98 if (binding_info.descriptorCount > 0) {
99 non_empty_bindings_.insert(binding_num);
Tobin Ehlis9637fb22016-12-12 15:59:34 -0700100 }
John Zulaufb6d71202017-12-22 16:47:09 -0700101
sfricke-samsung60f29ec2021-03-10 20:37:25 -0800102 if (IsDynamicDescriptor(binding_info.descriptorType)) {
sfricke-samsung0d00aed2021-03-08 23:31:17 -0800103 dynamic_descriptor_count_ += binding_info.descriptorCount;
104 }
105
106 // Get stats depending on descriptor type for caching later
sfricke-samsung60f29ec2021-03-10 20:37:25 -0800107 if (IsBufferDescriptor(binding_info.descriptorType)) {
108 if (IsDynamicDescriptor(binding_info.descriptorType)) {
109 binding_type_stats_.dynamic_buffer_count++;
110 } else {
111 binding_type_stats_.non_dynamic_buffer_count++;
112 }
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 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600125}
Tobin Ehlis154c2692016-10-25 09:36:53 -0600126
John Zulaufd47d0612018-02-16 13:00:34 -0700127size_t cvdescriptorset::DescriptorSetLayoutDef::hash() const {
128 hash_util::HashCombiner hc;
129 hc << flags_;
130 hc.Combine(bindings_);
John Zulauf223b69d2018-11-09 16:00:59 -0700131 hc.Combine(binding_flags_);
John Zulaufd47d0612018-02-16 13:00:34 -0700132 return hc.Value();
133}
134//
135
John Zulauf1f8174b2018-02-16 12:58:37 -0700136// Return valid index or "end" i.e. binding_count_;
137// The asserts in "Get" are reduced to the set where no valid answer(like null or 0) could be given
138// Common code for all binding lookups.
139uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetIndexFromBinding(uint32_t binding) const {
140 const auto &bi_itr = binding_to_index_map_.find(binding);
141 if (bi_itr != binding_to_index_map_.cend()) return bi_itr->second;
142 return GetBindingCount();
143}
144VkDescriptorSetLayoutBinding const *cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorSetLayoutBindingPtrFromIndex(
145 const uint32_t index) const {
146 if (index >= bindings_.size()) return nullptr;
147 return bindings_[index].ptr();
148}
149// Return descriptorCount for given index, 0 if index is unavailable
150uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorCountFromIndex(const uint32_t index) const {
151 if (index >= bindings_.size()) return 0;
152 return bindings_[index].descriptorCount;
153}
154// For the given index, return descriptorType
155VkDescriptorType cvdescriptorset::DescriptorSetLayoutDef::GetTypeFromIndex(const uint32_t index) const {
156 assert(index < bindings_.size());
157 if (index < bindings_.size()) return bindings_[index].descriptorType;
158 return VK_DESCRIPTOR_TYPE_MAX_ENUM;
159}
160// For the given index, return stageFlags
161VkShaderStageFlags cvdescriptorset::DescriptorSetLayoutDef::GetStageFlagsFromIndex(const uint32_t index) const {
162 assert(index < bindings_.size());
163 if (index < bindings_.size()) return bindings_[index].stageFlags;
164 return VkShaderStageFlags(0);
165}
Jeff Bolzfdf96072018-04-10 14:32:18 -0500166// Return binding flags for given index, 0 if index is unavailable
Mike Schuchardt2df08912020-12-15 16:28:09 -0800167VkDescriptorBindingFlags cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorBindingFlagsFromIndex(const uint32_t index) const {
Jeff Bolzfdf96072018-04-10 14:32:18 -0500168 if (index >= binding_flags_.size()) return 0;
169 return binding_flags_[index];
170}
John Zulauf1f8174b2018-02-16 12:58:37 -0700171
John Zulauf7705bfc2019-06-10 09:52:04 -0600172const cvdescriptorset::IndexRange &cvdescriptorset::DescriptorSetLayoutDef::GetGlobalIndexRangeFromIndex(uint32_t index) const {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700173 const static IndexRange k_invalid_range = {0xFFFFFFFF, 0xFFFFFFFF};
174 if (index >= binding_flags_.size()) return k_invalid_range;
John Zulauf7705bfc2019-06-10 09:52:04 -0600175 return global_index_range_[index];
John Zulauf1f8174b2018-02-16 12:58:37 -0700176}
177
John Zulauf7705bfc2019-06-10 09:52:04 -0600178// For the given binding, return the global index range (half open)
179// As start and end are often needed in pairs, get both with a single lookup.
John Zulauf1f8174b2018-02-16 12:58:37 -0700180const cvdescriptorset::IndexRange &cvdescriptorset::DescriptorSetLayoutDef::GetGlobalIndexRangeFromBinding(
181 const uint32_t binding) const {
John Zulauf7705bfc2019-06-10 09:52:04 -0600182 uint32_t index = GetIndexFromBinding(binding);
183 return GetGlobalIndexRangeFromIndex(index);
John Zulauf1f8174b2018-02-16 12:58:37 -0700184}
185
186// For given binding, return ptr to ImmutableSampler array
187VkSampler const *cvdescriptorset::DescriptorSetLayoutDef::GetImmutableSamplerPtrFromBinding(const uint32_t binding) const {
188 const auto &bi_itr = binding_to_index_map_.find(binding);
189 if (bi_itr != binding_to_index_map_.end()) {
190 return bindings_[bi_itr->second].pImmutableSamplers;
191 }
192 return nullptr;
193}
194// Move to next valid binding having a non-zero binding count
195uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetNextValidBinding(const uint32_t binding) const {
196 auto it = non_empty_bindings_.upper_bound(binding);
197 assert(it != non_empty_bindings_.cend());
198 if (it != non_empty_bindings_.cend()) return *it;
199 return GetMaxBinding() + 1;
200}
201// For given index, return ptr to ImmutableSampler array
202VkSampler const *cvdescriptorset::DescriptorSetLayoutDef::GetImmutableSamplerPtrFromIndex(const uint32_t index) const {
203 if (index < bindings_.size()) {
204 return bindings_[index].pImmutableSamplers;
205 }
206 return nullptr;
207}
John Zulauf9ce3b252019-06-06 15:20:22 -0600208
209// If our layout is compatible with rh_ds_layout, return true.
210bool cvdescriptorset::DescriptorSetLayout::IsCompatible(DescriptorSetLayout const *rh_ds_layout) const {
211 bool compatible = (this == rh_ds_layout) || (GetLayoutDef() == rh_ds_layout->GetLayoutDef());
212 return compatible;
213}
John Zulauf1f8174b2018-02-16 12:58:37 -0700214
John Zulauff43695f2019-09-13 17:56:26 -0600215// TODO: Find a way to add smarts to the autogenerated version of this
216static std::string smart_string_VkShaderStageFlags(VkShaderStageFlags stage_flags) {
217 if (stage_flags == VK_SHADER_STAGE_ALL) {
218 return string_VkShaderStageFlagBits(VK_SHADER_STAGE_ALL);
219 }
220
221 return string_VkShaderStageFlags(stage_flags);
222}
223
224// If our layout is compatible with bound_dsl, return true,
225// else return false and fill in error_msg will description of what causes incompatibility
226bool cvdescriptorset::VerifySetLayoutCompatibility(const debug_report_data *report_data, DescriptorSetLayout const *layout_dsl,
227 DescriptorSetLayout const *bound_dsl, std::string *error_msg) {
228 // Short circuit the detailed check.
229 if (layout_dsl->IsCompatible(bound_dsl)) return true;
230
231 // 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 -0600232 // Should only be run if trivial accept has failed, and in that context should return false.
John Zulauff43695f2019-09-13 17:56:26 -0600233 VkDescriptorSetLayout layout_dsl_handle = layout_dsl->GetDescriptorSetLayout();
234 VkDescriptorSetLayout bound_dsl_handle = bound_dsl->GetDescriptorSetLayout();
235 DescriptorSetLayoutDef const *layout_ds_layout_def = layout_dsl->GetLayoutDef();
236 DescriptorSetLayoutDef const *bound_ds_layout_def = bound_dsl->GetLayoutDef();
John Zulauf9ce3b252019-06-06 15:20:22 -0600237
238 // Check descriptor counts
John Zulauff43695f2019-09-13 17:56:26 -0600239 const auto bound_total_count = bound_ds_layout_def->GetTotalDescriptorCount();
240 if (layout_ds_layout_def->GetTotalDescriptorCount() != bound_ds_layout_def->GetTotalDescriptorCount()) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700241 std::stringstream error_str;
John Zulauff43695f2019-09-13 17:56:26 -0600242 error_str << report_data->FormatHandle(layout_dsl_handle) << " from pipeline layout has "
243 << layout_ds_layout_def->GetTotalDescriptorCount() << " total descriptors, but "
244 << report_data->FormatHandle(bound_dsl_handle) << ", which is bound, has " << bound_total_count
245 << " total descriptors.";
John Zulauf1f8174b2018-02-16 12:58:37 -0700246 *error_msg = error_str.str();
247 return false; // trivial fail case
248 }
John Zulaufd47d0612018-02-16 13:00:34 -0700249
John Zulauf1f8174b2018-02-16 12:58:37 -0700250 // Descriptor counts match so need to go through bindings one-by-one
251 // and verify that type and stageFlags match
John Zulauff43695f2019-09-13 17:56:26 -0600252 for (const auto &layout_binding : layout_ds_layout_def->GetBindings()) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700253 // TODO : Do we also need to check immutable samplers?
John Zulauff43695f2019-09-13 17:56:26 -0600254 const auto bound_binding = bound_ds_layout_def->GetBindingInfoFromBinding(layout_binding.binding);
255 if (layout_binding.descriptorCount != bound_binding->descriptorCount) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700256 std::stringstream error_str;
John Zulauff43695f2019-09-13 17:56:26 -0600257 error_str << "Binding " << layout_binding.binding << " for " << report_data->FormatHandle(layout_dsl_handle)
258 << " from pipeline layout has a descriptorCount of " << layout_binding.descriptorCount << " but binding "
259 << layout_binding.binding << " for " << report_data->FormatHandle(bound_dsl_handle)
260 << ", which is bound, has a descriptorCount of " << bound_binding->descriptorCount;
John Zulauf1f8174b2018-02-16 12:58:37 -0700261 *error_msg = error_str.str();
262 return false;
John Zulauff43695f2019-09-13 17:56:26 -0600263 } else if (layout_binding.descriptorType != bound_binding->descriptorType) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700264 std::stringstream error_str;
John Zulauff43695f2019-09-13 17:56:26 -0600265 error_str << "Binding " << layout_binding.binding << " for " << report_data->FormatHandle(layout_dsl_handle)
266 << " from pipeline layout is type '" << string_VkDescriptorType(layout_binding.descriptorType)
267 << "' but binding " << layout_binding.binding << " for " << report_data->FormatHandle(bound_dsl_handle)
268 << ", which is bound, is type '" << string_VkDescriptorType(bound_binding->descriptorType) << "'";
John Zulauf1f8174b2018-02-16 12:58:37 -0700269 *error_msg = error_str.str();
270 return false;
John Zulauff43695f2019-09-13 17:56:26 -0600271 } else if (layout_binding.stageFlags != bound_binding->stageFlags) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700272 std::stringstream error_str;
John Zulauff43695f2019-09-13 17:56:26 -0600273 error_str << "Binding " << layout_binding.binding << " for " << report_data->FormatHandle(layout_dsl_handle)
274 << " from pipeline layout has stageFlags " << smart_string_VkShaderStageFlags(layout_binding.stageFlags)
275 << " but binding " << layout_binding.binding << " for " << report_data->FormatHandle(bound_dsl_handle)
276 << ", which is bound, has stageFlags " << smart_string_VkShaderStageFlags(bound_binding->stageFlags);
John Zulauf1f8174b2018-02-16 12:58:37 -0700277 *error_msg = error_str.str();
278 return false;
279 }
280 }
Tony-LunarG692b8b42019-09-30 16:07:26 -0600281
282 const auto &ds_layout_flags = layout_ds_layout_def->GetBindingFlags();
283 const auto &bound_layout_flags = bound_ds_layout_def->GetBindingFlags();
284 if (bound_layout_flags != ds_layout_flags) {
285 std::stringstream error_str;
286 assert(ds_layout_flags.size() == bound_layout_flags.size());
287 size_t i;
288 for (i = 0; i < ds_layout_flags.size(); i++) {
289 if (ds_layout_flags[i] != bound_layout_flags[i]) break;
290 }
291 error_str << report_data->FormatHandle(layout_dsl_handle)
292 << " from pipeline layout does not have the same binding flags at binding " << i << " ( "
293 << string_VkDescriptorBindingFlagsEXT(ds_layout_flags[i]) << " ) as "
294 << report_data->FormatHandle(bound_dsl_handle) << " ( "
295 << string_VkDescriptorBindingFlagsEXT(bound_layout_flags[i]) << " ), which is bound";
296 *error_msg = error_str.str();
297 return false;
298 }
299
John Zulauf9ce3b252019-06-06 15:20:22 -0600300 // No detailed check should succeed if the trivial check failed -- or the dictionary has failed somehow.
301 bool compatible = true;
302 assert(!compatible);
303 return compatible;
John Zulauf1f8174b2018-02-16 12:58:37 -0700304}
305
306bool cvdescriptorset::DescriptorSetLayoutDef::IsNextBindingConsistent(const uint32_t binding) const {
307 if (!binding_to_index_map_.count(binding + 1)) return false;
308 auto const &bi_itr = binding_to_index_map_.find(binding);
309 if (bi_itr != binding_to_index_map_.end()) {
310 const auto &next_bi_itr = binding_to_index_map_.find(binding + 1);
311 if (next_bi_itr != binding_to_index_map_.end()) {
312 auto type = bindings_[bi_itr->second].descriptorType;
313 auto stage_flags = bindings_[bi_itr->second].stageFlags;
314 auto immut_samp = bindings_[bi_itr->second].pImmutableSamplers ? true : false;
Jeff Bolzfdf96072018-04-10 14:32:18 -0500315 auto flags = binding_flags_[bi_itr->second];
John Zulauf1f8174b2018-02-16 12:58:37 -0700316 if ((type != bindings_[next_bi_itr->second].descriptorType) ||
317 (stage_flags != bindings_[next_bi_itr->second].stageFlags) ||
Jeff Bolzfdf96072018-04-10 14:32:18 -0500318 (immut_samp != (bindings_[next_bi_itr->second].pImmutableSamplers ? true : false)) ||
319 (flags != binding_flags_[next_bi_itr->second])) {
John Zulauf1f8174b2018-02-16 12:58:37 -0700320 return false;
321 }
322 return true;
323 }
324 }
325 return false;
326}
John Zulauf1f8174b2018-02-16 12:58:37 -0700327
328// The DescriptorSetLayout stores the per handle data for a descriptor set layout, and references the common defintion for the
329// handle invariant portion
330cvdescriptorset::DescriptorSetLayout::DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info,
331 const VkDescriptorSetLayout layout)
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600332 : BASE_NODE(layout, kVulkanObjectTypeDescriptorSetLayout), layout_id_(GetCanonicalId(p_create_info)) {}
John Zulauf1f8174b2018-02-16 12:58:37 -0700333
Tobin Ehlis154c2692016-10-25 09:36:53 -0600334// Validate descriptor set layout create info
John Zulaufd9435c32019-06-05 15:55:36 -0600335bool cvdescriptorset::ValidateDescriptorSetLayoutCreateInfo(
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700336 const ValidationObject *val_obj, const VkDescriptorSetLayoutCreateInfo *create_info, const bool push_descriptor_ext,
Jeff Bolzfdf96072018-04-10 14:32:18 -0500337 const uint32_t max_push_descriptors, const bool descriptor_indexing_ext,
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700338 const VkPhysicalDeviceVulkan12Features *core12_features,
Jeff Bolze54ae892018-09-08 12:16:29 -0500339 const VkPhysicalDeviceInlineUniformBlockFeaturesEXT *inline_uniform_block_features,
ziga-lunarg637356a2021-07-19 12:36:34 +0200340 const VkPhysicalDeviceInlineUniformBlockPropertiesEXT *inline_uniform_block_props,
341 const VkPhysicalDeviceAccelerationStructureFeaturesKHR *acceleration_structure_features,
342 const DeviceExtensions *device_extensions) {
Tobin Ehlis154c2692016-10-25 09:36:53 -0600343 bool skip = false;
Jeremy Gebbencbf22862021-03-03 12:01:22 -0700344 layer_data::unordered_set<uint32_t> bindings;
John Zulauf0fdeab32018-01-23 11:27:35 -0700345 uint64_t total_descriptors = 0;
346
Mark Lobodzinski1f887d32020-12-30 15:31:33 -0700347 const auto *flags_create_info = LvlFindInChain<VkDescriptorSetLayoutBindingFlagsCreateInfo>(create_info->pNext);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500348
349 const bool push_descriptor_set = !!(create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR);
John Zulauf0fdeab32018-01-23 11:27:35 -0700350 if (push_descriptor_set && !push_descriptor_ext) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800351 skip |= val_obj->LogError(
352 val_obj->device, kVUID_Core_DrawState_ExtensionNotEnabled,
353 "vkCreateDescriptorSetLayout(): Attempted to use %s in %s but its required extension %s has not been enabled.\n",
354 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR", "VkDescriptorSetLayoutCreateInfo::flags",
355 VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
John Zulauf0fdeab32018-01-23 11:27:35 -0700356 }
357
Mike Schuchardt2df08912020-12-15 16:28:09 -0800358 const bool update_after_bind_set = !!(create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500359 if (update_after_bind_set && !descriptor_indexing_ext) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800360 skip |= val_obj->LogError(
361 val_obj->device, kVUID_Core_DrawState_ExtensionNotEnabled,
362 "vkCreateDescriptorSetLayout(): Attemped to use %s in %s but its required extension %s has not been enabled.\n",
363 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT", "VkDescriptorSetLayoutCreateInfo::flags",
364 VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500365 }
366
John Zulauf0fdeab32018-01-23 11:27:35 -0700367 auto valid_type = [push_descriptor_set](const VkDescriptorType type) {
368 return !push_descriptor_set ||
Dave Houlton142c4cb2018-10-17 15:04:41 -0600369 ((type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) && (type != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) &&
Jeff Bolze54ae892018-09-08 12:16:29 -0500370 (type != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT));
John Zulauf0fdeab32018-01-23 11:27:35 -0700371 };
372
Jeff Bolzfdf96072018-04-10 14:32:18 -0500373 uint32_t max_binding = 0;
374
ziga-lunarg185ef282021-07-19 13:13:28 +0200375 uint32_t update_after_bind = create_info->bindingCount;
376 uint32_t uniform_buffer_dynamic = create_info->bindingCount;
377 uint32_t storage_buffer_dynamic = create_info->bindingCount;
378
Tobin Ehlis154c2692016-10-25 09:36:53 -0600379 for (uint32_t i = 0; i < create_info->bindingCount; ++i) {
John Zulauf0fdeab32018-01-23 11:27:35 -0700380 const auto &binding_info = create_info->pBindings[i];
Jeff Bolzfdf96072018-04-10 14:32:18 -0500381 max_binding = std::max(max_binding, binding_info.binding);
382
John Zulauf0fdeab32018-01-23 11:27:35 -0700383 if (!bindings.insert(binding_info.binding).second) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700384 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-binding-00279",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800385 "vkCreateDescriptorSetLayout(): pBindings[%u] has duplicated binding number (%u).", i,
386 binding_info.binding);
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",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800393 "vkCreateDescriptorSetLayout(): pBindings[%u] has invalid type %s , for push descriptors.", i,
394 string_VkDescriptorType(binding_info.descriptorType));
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) {
sfricke-samsungc1e27c32021-01-16 09:32:49 -0800398 if (!inline_uniform_block_features->inlineUniformBlock) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800399 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-04604",
400 "vkCreateDescriptorSetLayout(): pBindings[%u] is creating VkDescriptorSetLayout with "
401 "descriptor type VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT "
Jeremy Gebbenda6b48f2021-05-13 10:46:18 -0600402 "but the inlineUniformBlock feature is not enabled",
403 i);
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600404 } else {
405 if ((binding_info.descriptorCount % 4) != 0) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800406 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-02209",
407 "vkCreateDescriptorSetLayout(): pBindings[%u] has descriptorCount =(%" PRIu32
408 ") but must be a multiple of 4",
409 i, binding_info.descriptorCount);
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600410 }
411 if (binding_info.descriptorCount > inline_uniform_block_props->maxInlineUniformBlockSize) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700412 skip |=
413 val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-02210",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800414 "vkCreateDescriptorSetLayout(): pBindings[%u] has descriptorCount =(%" PRIu32
415 ") but must be less than or equal to maxInlineUniformBlockSize (%u)",
416 i, binding_info.descriptorCount, inline_uniform_block_props->maxInlineUniformBlockSize);
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600417 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500418 }
ziga-lunarg185ef282021-07-19 13:13:28 +0200419 } else if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
420 uniform_buffer_dynamic = i;
421 } else if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
422 storage_buffer_dynamic = i;
Jeff Bolze54ae892018-09-08 12:16:29 -0500423 }
424
Tony-LunarG7337b312020-04-15 16:40:25 -0600425 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
426 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
sfricke-samsung45996a42021-09-16 13:45:27 -0700427 binding_info.pImmutableSamplers && IsExtEnabled(device_extensions->vk_ext_custom_border_color)) {
Tony-LunarG7337b312020-04-15 16:40:25 -0600428 const CoreChecks *core_checks = reinterpret_cast<const CoreChecks *>(val_obj);
429 for (uint32_t j = 0; j < binding_info.descriptorCount; j++) {
430 const SAMPLER_STATE *sampler_state = core_checks->GetSamplerState(binding_info.pImmutableSamplers[j]);
431 if (sampler_state && (sampler_state->createInfo.borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT ||
432 sampler_state->createInfo.borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT)) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800433 skip |= val_obj->LogError(
434 val_obj->device, "VUID-VkDescriptorSetLayoutBinding-pImmutableSamplers-04009",
Jeremy Gebbenda6b48f2021-05-13 10:46:18 -0600435 "vkCreateDescriptorSetLayout(): pBindings[%u].pImmutableSamplers[%u] has VkSampler %s"
sfricke-samsungbda4a852021-03-06 20:58:01 -0800436 " presented as immutable has a custom border color",
Jeremy Gebbenda6b48f2021-05-13 10:46:18 -0600437 i, j, val_obj->report_data->FormatHandle(binding_info.pImmutableSamplers[j]).c_str());
Tony-LunarG7337b312020-04-15 16:40:25 -0600438 }
439 }
440 }
441
ziga-lunarg6d770792021-07-19 11:27:18 +0200442 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE && binding_info.pImmutableSamplers != nullptr) {
443 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-04605",
444 "vkCreateDescriptorSetLayout(): pBindings[%u] has descriptorType "
445 "VK_DESCRIPTOR_TYPE_MUTABLE_VALVE but pImmutableSamplers is not NULL.",
446 i);
447 }
448
John Zulauf0fdeab32018-01-23 11:27:35 -0700449 total_descriptors += binding_info.descriptorCount;
Tobin Ehlis154c2692016-10-25 09:36:53 -0600450 }
John Zulauf0fdeab32018-01-23 11:27:35 -0700451
Jeff Bolzfdf96072018-04-10 14:32:18 -0500452 if (flags_create_info) {
453 if (flags_create_info->bindingCount != 0 && flags_create_info->bindingCount != create_info->bindingCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700454 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-bindingCount-03002",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800455 "vkCreateDescriptorSetLayout(): VkDescriptorSetLayoutCreateInfo::bindingCount (%d) != "
Mike Schuchardt2df08912020-12-15 16:28:09 -0800456 "VkDescriptorSetLayoutBindingFlagsCreateInfo::bindingCount (%d)",
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700457 create_info->bindingCount, flags_create_info->bindingCount);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500458 }
459
460 if (flags_create_info->bindingCount == create_info->bindingCount) {
461 for (uint32_t i = 0; i < create_info->bindingCount; ++i) {
462 const auto &binding_info = create_info->pBindings[i];
463
Mike Schuchardt2df08912020-12-15 16:28:09 -0800464 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT) {
ziga-lunarg185ef282021-07-19 13:13:28 +0200465 update_after_bind = i;
Jeff Bolzfdf96072018-04-10 14:32:18 -0500466 if (!update_after_bind_set) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700467 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-flags-03000",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800468 "vkCreateDescriptorSetLayout(): pBindings[%u] does not have "
469 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT.",
470 i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500471 }
472
473 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700474 !core12_features->descriptorBindingUniformBufferUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800475 skip |= val_obj->LogError(
476 val_obj->device,
477 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
478 "descriptorBindingUniformBufferUpdateAfterBind-03005",
479 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
480 "for %s since descriptorBindingUniformBufferUpdateAfterBind is not enabled.",
481 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500482 }
483 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
484 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
485 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700486 !core12_features->descriptorBindingSampledImageUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800487 skip |= val_obj->LogError(
488 val_obj->device,
489 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
490 "descriptorBindingSampledImageUpdateAfterBind-03006",
491 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
492 "for %s since descriptorBindingSampledImageUpdateAfterBind is not enabled.",
493 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500494 }
495 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700496 !core12_features->descriptorBindingStorageImageUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800497 skip |= val_obj->LogError(
498 val_obj->device,
499 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
500 "descriptorBindingStorageImageUpdateAfterBind-03007",
501 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
502 "for %s since descriptorBindingStorageImageUpdateAfterBind is not enabled.",
503 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500504 }
505 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700506 !core12_features->descriptorBindingStorageBufferUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800507 skip |= val_obj->LogError(
508 val_obj->device,
509 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
510 "descriptorBindingStorageBufferUpdateAfterBind-03008",
511 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
512 "for %s since descriptorBindingStorageBufferUpdateAfterBind is not enabled.",
513 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500514 }
515 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700516 !core12_features->descriptorBindingUniformTexelBufferUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800517 skip |= val_obj->LogError(
518 val_obj->device,
519 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
520 "descriptorBindingUniformTexelBufferUpdateAfterBind-03009",
521 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
522 "for %s since descriptorBindingUniformTexelBufferUpdateAfterBind is not enabled.",
523 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500524 }
525 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700526 !core12_features->descriptorBindingStorageTexelBufferUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800527 skip |= val_obj->LogError(
528 val_obj->device,
529 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
530 "descriptorBindingStorageTexelBufferUpdateAfterBind-03010",
531 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
532 "for %s since descriptorBindingStorageTexelBufferUpdateAfterBind is not enabled.",
533 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500534 }
535 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ||
536 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
537 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700538 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-None-03011",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800539 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have "
540 "VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT for %s.",
541 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500542 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500543
544 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT &&
545 !inline_uniform_block_features->descriptorBindingInlineUniformBlockUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800546 skip |= val_obj->LogError(
547 val_obj->device,
548 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
549 "descriptorBindingInlineUniformBlockUpdateAfterBind-02211",
550 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
551 "for %s since descriptorBindingInlineUniformBlockUpdateAfterBind is not enabled.",
552 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolze54ae892018-09-08 12:16:29 -0500553 }
ziga-lunarg637356a2021-07-19 12:36:34 +0200554 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR ||
555 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV) &&
556 !acceleration_structure_features->descriptorBindingAccelerationStructureUpdateAfterBind) {
557 skip |= val_obj->LogError(val_obj->device,
558 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
559 "descriptorBindingAccelerationStructureUpdateAfterBind-03570",
560 "vkCreateDescriptorSetLayout(): pBindings[%" PRIu32
561 "] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
562 "for %s if "
563 "VkPhysicalDeviceAccelerationStructureFeaturesKHR::"
564 "descriptorBindingAccelerationStructureUpdateAfterBind is not enabled.",
565 i, string_VkDescriptorType(binding_info.descriptorType));
566 }
Jeff Bolzfdf96072018-04-10 14:32:18 -0500567 }
568
Mike Schuchardt2df08912020-12-15 16:28:09 -0800569 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT) {
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700570 if (!core12_features->descriptorBindingUpdateUnusedWhilePending) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700571 skip |= val_obj->LogError(
572 val_obj->device,
Mike Schuchardt65847d92019-12-20 13:50:47 -0800573 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingUpdateUnusedWhilePending-03012",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800574 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have "
575 "VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT for %s since "
576 "descriptorBindingUpdateUnusedWhilePending is not enabled.",
577 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500578 }
579 }
580
Mike Schuchardt2df08912020-12-15 16:28:09 -0800581 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT) {
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700582 if (!core12_features->descriptorBindingPartiallyBound) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700583 skip |= val_obj->LogError(
584 val_obj->device,
585 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingPartiallyBound-03013",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800586 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT for "
587 "%s since descriptorBindingPartiallyBound is not enabled.",
588 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500589 }
590 }
591
Mike Schuchardt2df08912020-12-15 16:28:09 -0800592 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT) {
Jeff Bolzfdf96072018-04-10 14:32:18 -0500593 if (binding_info.binding != max_binding) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800594 skip |= val_obj->LogError(
595 val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03004",
596 "vkCreateDescriptorSetLayout(): pBindings[%u] has VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT "
597 "but %u is the largest value of all the bindings.",
598 i, binding_info.binding);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500599 }
600
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700601 if (!core12_features->descriptorBindingVariableDescriptorCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700602 skip |= val_obj->LogError(
603 val_obj->device,
Mike Schuchardt65847d92019-12-20 13:50:47 -0800604 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingVariableDescriptorCount-03014",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800605 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have "
606 "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT for %s since "
607 "descriptorBindingVariableDescriptorCount is not enabled.",
608 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500609 }
sfricke-samsung4ba7d6e2021-03-06 20:56:35 -0800610 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
611 (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700612 skip |= val_obj->LogError(val_obj->device,
613 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03015",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800614 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have "
615 "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT for %s.",
616 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500617 }
618 }
619
620 if (push_descriptor_set &&
621 (flags_create_info->pBindingFlags[i] &
Mike Schuchardt2df08912020-12-15 16:28:09 -0800622 (VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT |
623 VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT))) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800624 skip |= val_obj->LogError(
625 val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-flags-03003",
626 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT, "
627 "VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, or "
628 "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT for with "
629 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR.",
630 i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500631 }
632 }
633 }
634 }
635
ziga-lunarg185ef282021-07-19 13:13:28 +0200636 if (update_after_bind < create_info->bindingCount) {
637 if (uniform_buffer_dynamic < create_info->bindingCount) {
638 skip |=
639 val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-descriptorType-03001",
640 "vkCreateDescriptorSetLayout(): binding (%" PRIi32
641 ") has VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
642 "flag, but binding (%" PRIi32 ") has descriptor type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC.",
643 update_after_bind, uniform_buffer_dynamic);
644 }
645 if (storage_buffer_dynamic < create_info->bindingCount) {
646 skip |=
647 val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-descriptorType-03001",
648 "vkCreateDescriptorSetLayout(): binding (%" PRIi32
649 ") has VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
650 "flag, but binding (%" PRIi32 ") has descriptor type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC.",
651 update_after_bind, storage_buffer_dynamic);
652 }
653 }
654
John Zulauf0fdeab32018-01-23 11:27:35 -0700655 if ((push_descriptor_set) && (total_descriptors > max_push_descriptors)) {
656 const char *undefined = push_descriptor_ext ? "" : " -- undefined";
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700657 skip |= val_obj->LogError(
658 val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-flags-00281",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800659 "vkCreateDescriptorSetLayout(): for push descriptor, total descriptor count in layout (%" PRIu64
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700660 ") must not be greater than VkPhysicalDevicePushDescriptorPropertiesKHR::maxPushDescriptors (%" PRIu32 "%s).",
661 total_descriptors, max_push_descriptors, undefined);
John Zulauf0fdeab32018-01-23 11:27:35 -0700662 }
663
Tobin Ehlis154c2692016-10-25 09:36:53 -0600664 return skip;
665}
666
Mark Lobodzinskie12b6e32020-06-29 11:44:15 -0600667void cvdescriptorset::AllocateDescriptorSetsData::Init(uint32_t count) {
668 layout_nodes.resize(count);
Mark Lobodzinskie12b6e32020-06-29 11:44:15 -0600669}
Tobin Ehlis68d0adf2016-06-01 11:33:50 -0600670
Jeff Bolz41a1ced2019-10-11 11:40:49 -0500671cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, DESCRIPTOR_POOL_STATE *pool_state,
Jeff Bolzfdf96072018-04-10 14:32:18 -0500672 const std::shared_ptr<DescriptorSetLayout const> &layout, uint32_t variable_count,
John Zulaufd2c3dae2019-12-12 11:02:17 -0700673 const cvdescriptorset::DescriptorSet::StateTracker *state_data)
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -0600674 : BASE_NODE(set, kVulkanObjectTypeDescriptorSet),
675 some_update_(false),
Jeff Bolz41a1ced2019-10-11 11:40:49 -0500676 pool_state_(pool_state),
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700677 layout_(layout),
John Zulaufd2c3dae2019-12-12 11:02:17 -0700678 state_data_(state_data),
Jeff Bolzdd4cfa12019-08-11 20:57:51 -0500679 variable_count_(variable_count),
680 change_count_(0) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600681 if (pool_state_) {
682 pool_state_->AddParent(this);
683 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600684 // Foreach binding, create default descriptors of given type
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700685 descriptors_.reserve(layout_->GetTotalDescriptorCount());
686 descriptor_store_.resize(layout_->GetTotalDescriptorCount());
John Zulaufe4850d42019-12-30 16:10:55 -0700687 auto free_descriptor = descriptor_store_.data();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700688 for (uint32_t i = 0; i < layout_->GetBindingCount(); ++i) {
689 auto type = layout_->GetTypeFromIndex(i);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600690 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700691 case VK_DESCRIPTOR_TYPE_SAMPLER: {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700692 auto immut_sampler = layout_->GetImmutableSamplerPtrFromIndex(i);
693 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
Tobin Ehlis082c7512017-05-08 11:24:57 -0600694 if (immut_sampler) {
John Zulaufe4850d42019-12-30 16:10:55 -0700695 descriptors_.emplace_back(new ((free_descriptor++)->Sampler())
696 SamplerDescriptor(state_data, immut_sampler + di));
Tobin Ehlis082c7512017-05-08 11:24:57 -0600697 some_update_ = true; // Immutable samplers are updated at creation
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700698 } else {
John Zulaufe4850d42019-12-30 16:10:55 -0700699 descriptors_.emplace_back(new ((free_descriptor++)->Sampler()) SamplerDescriptor(state_data, nullptr));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700700 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600701 descriptors_.back()->AddParent(this);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700702 }
703 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600704 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700705 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700706 auto immut = layout_->GetImmutableSamplerPtrFromIndex(i);
707 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
Tobin Ehlis082c7512017-05-08 11:24:57 -0600708 if (immut) {
John Zulaufe4850d42019-12-30 16:10:55 -0700709 descriptors_.emplace_back(new ((free_descriptor++)->ImageSampler())
710 ImageSamplerDescriptor(state_data, immut + di));
Tobin Ehlis082c7512017-05-08 11:24:57 -0600711 some_update_ = true; // Immutable samplers are updated at creation
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700712 } else {
John Zulaufe4850d42019-12-30 16:10:55 -0700713 descriptors_.emplace_back(new ((free_descriptor++)->ImageSampler())
714 ImageSamplerDescriptor(state_data, nullptr));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700715 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600716 descriptors_.back()->AddParent(this);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700717 }
718 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600719 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700720 // ImageDescriptors
721 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
722 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
723 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700724 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700725 descriptors_.emplace_back(new ((free_descriptor++)->Image()) ImageDescriptor(type));
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600726 descriptors_.back()->AddParent(this);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700727 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700728 break;
729 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
730 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700731 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700732 descriptors_.emplace_back(new ((free_descriptor++)->Texel()) TexelDescriptor(type));
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600733 descriptors_.back()->AddParent(this);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700734 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700735 break;
sfricke-samsung4ca35652021-03-05 02:22:10 -0800736 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
737 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
738 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700739 descriptors_.emplace_back(new ((free_descriptor++)->Buffer()) BufferDescriptor(type));
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600740 descriptors_.back()->AddParent(this);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700741 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700742 break;
Jeff Bolze54ae892018-09-08 12:16:29 -0500743 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700744 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700745 descriptors_.emplace_back(new ((free_descriptor++)->InlineUniform()) InlineUniformDescriptor(type));
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600746 descriptors_.back()->AddParent(this);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700747 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500748 break;
Eric Werness30127fd2018-10-31 21:01:03 -0700749 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
sourav parmarcd5fb182020-07-17 12:58:44 -0700750 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700751 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700752 descriptors_.emplace_back(new ((free_descriptor++)->AccelerationStructure())
753 AccelerationStructureDescriptor(type));
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600754 descriptors_.back()->AddParent(this);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700755 }
Jeff Bolzfbe51582018-09-13 10:01:35 -0500756 break;
Tony-LunarGf563b362021-03-18 16:13:18 -0600757 case VK_DESCRIPTOR_TYPE_MUTABLE_VALVE:
758 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
759 descriptors_.emplace_back(new ((free_descriptor++)->InlineUniform()) MutableDescriptor());
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600760 descriptors_.back()->AddParent(this);
Tony-LunarGf563b362021-03-18 16:13:18 -0600761 }
762 break;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700763 default:
sfricke-samsung60f29ec2021-03-10 20:37:25 -0800764 if (IsDynamicDescriptor(type) && IsBufferDescriptor(type)) {
765 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
766 dynamic_offset_idx_to_descriptor_list_.push_back(descriptors_.size());
767 descriptors_.emplace_back(new ((free_descriptor++)->Buffer()) BufferDescriptor(type));
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600768 descriptors_.back()->AddParent(this);
sfricke-samsung60f29ec2021-03-10 20:37:25 -0800769 }
770 } else {
771 assert(0); // Bad descriptor type specified
772 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700773 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600774 }
775 }
776}
Tobin Ehlis56a30942016-05-19 08:00:00 -0600777
Jeremy Gebben5570abe2021-05-16 18:35:13 -0600778void cvdescriptorset::DescriptorSet::Destroy() {
779 if (pool_state_) {
780 pool_state_->RemoveParent(this);
781 }
782 for (auto &desc: descriptors_) {
783 desc->RemoveParent(this);
784 }
785 BASE_NODE::Destroy();
786}
Chris Forbes57989132016-07-26 17:06:10 +1200787
Jeremy Gebben90ce4162021-08-25 14:23:07 -0600788static std::string StringDescriptorReqViewType(DescriptorReqFlags req) {
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700789 std::string result("");
Mark Lobodzinski29f451a2020-02-10 16:15:30 -0700790 for (unsigned i = 0; i <= VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; i++) {
Chris Forbes57989132016-07-26 17:06:10 +1200791 if (req & (1 << i)) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700792 if (result.size()) result += ", ";
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700793 result += string_VkImageViewType(VkImageViewType(i));
Chris Forbes57989132016-07-26 17:06:10 +1200794 }
795 }
796
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700797 if (!result.size()) result = "(none)";
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700798
799 return result;
Chris Forbes57989132016-07-26 17:06:10 +1200800}
801
Jeremy Gebben90ce4162021-08-25 14:23:07 -0600802static char const *StringDescriptorReqComponentType(DescriptorReqFlags req) {
Chris Forbesda01e8d2018-08-27 15:36:57 -0700803 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_SINT) return "SINT";
804 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_UINT) return "UINT";
805 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT) return "FLOAT";
806 return "(none)";
807}
808
Jeff Bolz6cede832019-08-09 23:30:39 -0500809unsigned DescriptorRequirementsBitsFromFormat(VkFormat fmt) {
Chris Forbesda01e8d2018-08-27 15:36:57 -0700810 if (FormatIsSInt(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_SINT;
811 if (FormatIsUInt(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_UINT;
sfricke-samsunged028b02021-09-06 23:14:51 -0700812 // Formats such as VK_FORMAT_D16_UNORM_S8_UINT are both
Chris Forbesda01e8d2018-08-27 15:36:57 -0700813 if (FormatIsDepthAndStencil(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT | DESCRIPTOR_REQ_COMPONENT_TYPE_UINT;
814 if (fmt == VK_FORMAT_UNDEFINED) return 0;
815 // everything else -- UNORM/SNORM/FLOAT/USCALED/SSCALED is all float in the shader.
816 return DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT;
817}
818
Tobin Ehlis3066db62016-08-22 08:12:23 -0600819// 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 -0600820// This includes validating that all descriptors in the given bindings are updated,
821// that any update buffers are valid, and that any dynamic offsets are within the bounds of their buffers.
822// Return true if state is acceptable, or false and write an error message into error string
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600823bool CoreChecks::ValidateDrawState(const DescriptorSet *descriptor_set, const BindingReqMap &bindings,
824 const std::vector<uint32_t> &dynamic_offsets, const CMD_BUFFER_STATE *cb_node,
Niels Möller1f945f62021-07-12 15:06:02 +0200825 const std::vector<IMAGE_VIEW_STATE *> *attachments, const std::vector<SUBPASS_INFO> *subpasses,
locke-lunargfc78e932020-11-19 17:06:24 -0700826 const char *caller, const DrawDispatchVuid &vuids) const {
Jeremy Gebben37ed31e2021-04-23 12:12:10 -0600827 layer_data::optional<layer_data::unordered_map<VkImageView, VkImageLayout>> checked_layouts;
Karl Schultz2171f932021-03-19 10:47:01 -0600828 if (descriptor_set->GetTotalDescriptorCount() > cvdescriptorset::PrefilterBindRequestMap::kManyDescriptors_) {
829 checked_layouts.emplace();
830 }
Tony-LunarGace473a2020-05-06 12:48:04 -0600831 bool result = false;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600832 VkFramebuffer framebuffer = cb_node->activeFramebuffer ? cb_node->activeFramebuffer->framebuffer() : VK_NULL_HANDLE;
John Zulauf79f06582021-02-27 18:38:39 -0700833 for (const auto &binding_pair : bindings) {
834 const auto binding = binding_pair.first;
John Zulauf382e1912019-06-10 15:27:44 -0600835 DescriptorSetLayout::ConstBindingIterator binding_it(descriptor_set->GetLayout().get(), binding);
836 if (binding_it.AtEnd()) { // End at construction is the condition for an invalid binding.
Tony-LunarGace473a2020-05-06 12:48:04 -0600837 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600838 result |= LogError(set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -0600839 "%s encountered the following validation error at %s time: Attempting to "
840 "validate DrawState for binding #%u which is an invalid binding for this descriptor set.",
841 report_data->FormatHandle(set).c_str(), caller, binding);
842 return result;
Tobin Ehlis58c59582016-06-21 12:34:33 -0600843 }
Jeff Bolz6cede832019-08-09 23:30:39 -0500844
845 if (binding_it.GetDescriptorBindingFlags() &
Mike Schuchardt2df08912020-12-15 16:28:09 -0800846 (VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT)) {
Jeff Bolz6cede832019-08-09 23:30:39 -0500847 // Can't validate the descriptor because it may not have been updated,
848 // or the view could have been destroyed
849 continue;
850 }
John Zulauf81dd1f12021-01-26 16:49:16 -0700851 // // This is a record time only path
852 const bool record_time_validate = true;
locke-lunargfc78e932020-11-19 17:06:24 -0700853 result |= ValidateDescriptorSetBindingData(cb_node, descriptor_set, dynamic_offsets, binding_pair, framebuffer, attachments,
Karl Schultz2171f932021-03-19 10:47:01 -0600854 subpasses, record_time_validate, caller, vuids, checked_layouts);
unknown3087a642019-09-26 17:21:05 -0600855 }
Tony-LunarGace473a2020-05-06 12:48:04 -0600856 return result;
unknown3087a642019-09-26 17:21:05 -0600857}
Jeff Bolz6cede832019-08-09 23:30:39 -0500858
locke-lunargb8be8222020-10-20 00:34:37 -0600859bool CoreChecks::ValidateDescriptorSetBindingData(const CMD_BUFFER_STATE *cb_node, const DescriptorSet *descriptor_set,
860 const std::vector<uint32_t> &dynamic_offsets,
John Zulauf79f06582021-02-27 18:38:39 -0700861 const std::pair<const uint32_t, DescriptorRequirement> &binding_info,
Mark Lobodzinski85ebd402020-12-03 12:56:07 -0700862 VkFramebuffer framebuffer, const std::vector<IMAGE_VIEW_STATE *> *attachments,
Niels Möller1f945f62021-07-12 15:06:02 +0200863 const std::vector<SUBPASS_INFO> *subpasses, bool record_time_validate,
Karl Schultz2171f932021-03-19 10:47:01 -0600864 const char *caller, const DrawDispatchVuid &vuids,
Jeremy Gebben37ed31e2021-04-23 12:12:10 -0600865 layer_data::optional<layer_data::unordered_map<VkImageView, VkImageLayout>> &checked_layouts) const {
unknown3087a642019-09-26 17:21:05 -0600866 using DescriptorClass = cvdescriptorset::DescriptorClass;
867 using BufferDescriptor = cvdescriptorset::BufferDescriptor;
868 using ImageDescriptor = cvdescriptorset::ImageDescriptor;
869 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
870 using SamplerDescriptor = cvdescriptorset::SamplerDescriptor;
871 using TexelDescriptor = cvdescriptorset::TexelDescriptor;
Jeff Bolz95176d02020-04-01 00:36:16 -0500872 using AccelerationStructureDescriptor = cvdescriptorset::AccelerationStructureDescriptor;
locke-lunarg36045992020-08-20 16:54:37 -0600873 const auto binding = binding_info.first;
Jeremy Gebbene151b6b2021-04-09 18:03:06 -0600874 bool skip = false;
unknown3087a642019-09-26 17:21:05 -0600875 DescriptorSetLayout::ConstBindingIterator binding_it(descriptor_set->GetLayout().get(), binding);
876 {
John Zulauf382e1912019-06-10 15:27:44 -0600877 // Copy the range, the end range is subject to update based on variable length descriptor arrays.
878 cvdescriptorset::IndexRange index_range = binding_it.GetGlobalIndexRange();
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700879 auto array_idx = 0; // Track array idx if we're dealing with array descriptors
Jeff Bolzfdf96072018-04-10 14:32:18 -0500880
John Zulauf382e1912019-06-10 15:27:44 -0600881 if (binding_it.IsVariableDescriptorCount()) {
Jeff Bolzfdf96072018-04-10 14:32:18 -0500882 // Only validate the first N descriptors if it uses variable_count
John Zulauf382e1912019-06-10 15:27:44 -0600883 index_range.end = index_range.start + descriptor_set->GetVariableDescriptorCount();
Jeff Bolzfdf96072018-04-10 14:32:18 -0500884 }
Jeremy Gebbene151b6b2021-04-09 18:03:06 -0600885 for (uint32_t i = index_range.start; !skip && i < index_range.end; ++i, ++array_idx) {
Lockeb994adf2019-03-29 23:52:31 -0600886 uint32_t index = i - index_range.start;
John Zulauf382e1912019-06-10 15:27:44 -0600887 const auto *descriptor = descriptor_set->GetDescriptorFromGlobalIndex(i);
Jeremy Gebben550ebbd2021-03-11 05:04:52 -0700888 const auto descriptor_class = descriptor->GetClass();
Lockeb994adf2019-03-29 23:52:31 -0600889
Jeremy Gebben550ebbd2021-03-11 05:04:52 -0700890 if (descriptor_class == DescriptorClass::InlineUniform) {
Jeff Bolz6cede832019-08-09 23:30:39 -0500891 // Can't validate the descriptor because it may not have been updated.
Jeff Bolzfdf96072018-04-10 14:32:18 -0500892 continue;
John Zulauf382e1912019-06-10 15:27:44 -0600893 } else if (!descriptor->updated) {
Tony-LunarGace473a2020-05-06 12:48:04 -0600894 auto set = descriptor_set->GetSet();
sfricke-samsungbda4a852021-03-06 20:58:01 -0800895 return LogError(
896 set, vuids.descriptor_valid,
897 "Descriptor set %s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
898 " index %" PRIu32
899 " is being used in draw but has never been updated via vkUpdateDescriptorSets() or a similar call.",
900 report_data->FormatHandle(set).c_str(), caller, binding, index);
Jeremy Gebbene151b6b2021-04-09 18:03:06 -0600901 }
902 switch (descriptor_class) {
903 case DescriptorClass::GeneralBuffer: {
904 const auto *buffer_desc = static_cast<const BufferDescriptor *>(descriptor);
905 skip =
906 ValidateGeneralBufferDescriptor(caller, vuids, cb_node, descriptor_set, *buffer_desc, binding_info, index);
907 } break;
908 case DescriptorClass::ImageSampler: {
909 const auto *image_sampler_desc = static_cast<const ImageSamplerDescriptor *>(descriptor);
910 skip = ValidateImageDescriptor(caller, vuids, cb_node, descriptor_set, *image_sampler_desc, binding_info, index,
911 record_time_validate, attachments, subpasses, framebuffer, binding_it.GetType(),
912 checked_layouts);
913 if (!skip) {
914 skip = ValidateSamplerDescriptor(caller, vuids, cb_node, descriptor_set, binding_info, index,
915 image_sampler_desc->GetSampler(), image_sampler_desc->IsImmutableSampler(),
916 image_sampler_desc->GetSamplerState());
Karl Schultz76d16a42020-11-11 05:05:33 -0700917 }
Jeremy Gebbene151b6b2021-04-09 18:03:06 -0600918 } break;
919 case DescriptorClass::Image: {
920 const auto *image_desc = static_cast<const ImageDescriptor *>(descriptor);
921 skip = ValidateImageDescriptor(caller, vuids, cb_node, descriptor_set, *image_desc, binding_info, index,
922 record_time_validate, attachments, subpasses, framebuffer, binding_it.GetType(),
923 checked_layouts);
924 } break;
925 case DescriptorClass::PlainSampler: {
926 const auto *sampler_desc = static_cast<const SamplerDescriptor *>(descriptor);
927 skip = ValidateSamplerDescriptor(caller, vuids, cb_node, descriptor_set, binding_info, index,
928 sampler_desc->GetSampler(), sampler_desc->IsImmutableSampler(),
929 sampler_desc->GetSamplerState());
930 } break;
931 case DescriptorClass::TexelBuffer: {
932 const auto *texel_desc = static_cast<const TexelDescriptor *>(descriptor);
933 skip = ValidateTexelDescriptor(caller, vuids, cb_node, descriptor_set, *texel_desc, binding_info, index);
934 } break;
935 case DescriptorClass::AccelerationStructure: {
936 const auto *accel_desc = static_cast<const AccelerationStructureDescriptor *>(descriptor);
937 skip = ValidateAccelerationDescriptor(caller, vuids, cb_node, descriptor_set, *accel_desc, binding_info, index);
938 } break;
939 default:
940 break;
941 }
942 }
943 }
944 return skip;
945}
locke-lunarg36045992020-08-20 16:54:37 -0600946
Jeremy Gebbene151b6b2021-04-09 18:03:06 -0600947bool CoreChecks::ValidateGeneralBufferDescriptor(const char *caller, const DrawDispatchVuid &vuids, const CMD_BUFFER_STATE *cb_node,
948 const cvdescriptorset::DescriptorSet *descriptor_set,
949 const cvdescriptorset::BufferDescriptor &descriptor,
950 const std::pair<const uint32_t, DescriptorRequirement> &binding_info,
951 uint32_t index) const {
952 // Verify that buffers are valid
953 auto buffer = descriptor.GetBuffer();
954 auto buffer_node = descriptor.GetBufferState();
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -0600955 if ((!buffer_node && !enabled_features.robustness2_features.nullDescriptor) || (buffer_node && buffer_node->Destroyed())) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -0600956 auto set = descriptor_set->GetSet();
957 return LogError(set, vuids.descriptor_valid,
958 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
959 "binding #%" PRIu32 " index %" PRIu32 " is using buffer %s that is invalid or has been destroyed.",
960 report_data->FormatHandle(set).c_str(), caller, binding_info.first, index,
961 report_data->FormatHandle(buffer).c_str());
962 }
963 if (buffer) {
964 if (buffer_node && !buffer_node->sparse) {
Jeremy Gebben6fbf8242021-06-21 09:14:46 -0600965 for (const auto &item: buffer_node->GetBoundMemory()) {
966 auto &binding = item.second;
967 if (binding.mem_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -0600968 auto set = descriptor_set->GetSet();
969 return LogError(set, vuids.descriptor_valid,
970 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
971 "binding #%" PRIu32 " index %" PRIu32 " is uses buffer %s that references invalid memory %s.",
972 report_data->FormatHandle(set).c_str(), caller, binding_info.first, index,
Jeremy Gebben6fbf8242021-06-21 09:14:46 -0600973 report_data->FormatHandle(buffer).c_str(),
974 report_data->FormatHandle(binding.mem_state->mem()).c_str());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -0600975 }
976 }
977 }
978 if (enabled_features.core11.protectedMemory == VK_TRUE) {
979 if (ValidateProtectedBuffer(cb_node, buffer_node, caller, vuids.unprotected_command_buffer,
980 "Buffer is in a descriptorSet")) {
981 return true;
982 }
983 if (binding_info.second.is_writable &&
984 ValidateUnprotectedBuffer(cb_node, buffer_node, caller, vuids.protected_command_buffer,
985 "Buffer is in a descriptorSet")) {
986 return true;
987 }
988 }
989 }
990 return false;
991}
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700992
Jeremy Gebbene151b6b2021-04-09 18:03:06 -0600993bool CoreChecks::ValidateImageDescriptor(const char *caller, const DrawDispatchVuid &vuids, const CMD_BUFFER_STATE *cb_node,
994 const cvdescriptorset::DescriptorSet *descriptor_set,
995 const cvdescriptorset::ImageDescriptor &image_descriptor,
996 const std::pair<const uint32_t, DescriptorRequirement> &binding_info, uint32_t index,
997 bool record_time_validate, const std::vector<IMAGE_VIEW_STATE *> *attachments,
Niels Möller1f945f62021-07-12 15:06:02 +0200998 const std::vector<SUBPASS_INFO> *subpasses, VkFramebuffer framebuffer,
Jeremy Gebbene151b6b2021-04-09 18:03:06 -0600999 VkDescriptorType descriptor_type,
Jeremy Gebben37ed31e2021-04-23 12:12:10 -06001000 layer_data::optional<layer_data::unordered_map<VkImageView, VkImageLayout>> &checked_layouts) const {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001001 std::vector<const SAMPLER_STATE *> sampler_states;
1002 VkImageView image_view = image_descriptor.GetImageView();
1003 const IMAGE_VIEW_STATE *image_view_state = image_descriptor.GetImageViewState();
1004 VkImageLayout image_layout = image_descriptor.GetImageLayout();
1005 const auto binding = binding_info.first;
1006 const auto reqs = binding_info.second.reqs;
Karl Schultz76d16a42020-11-11 05:05:33 -07001007
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001008 if (image_descriptor.GetClass() == cvdescriptorset::DescriptorClass::ImageSampler) {
1009 sampler_states.emplace_back(
1010 static_cast<const cvdescriptorset::ImageSamplerDescriptor &>(image_descriptor).GetSamplerState());
1011 } else {
1012 if (binding_info.second.samplers_used_by_image.size() > index) {
1013 for (auto &sampler : binding_info.second.samplers_used_by_image[index]) {
1014 // NOTE: This check _shouldn't_ be necessary due to the checks made in IsSpecificDescriptorType in
1015 // shader_validation.cpp. However, without this check some traces still crash.
1016 if (sampler.second && (sampler.second->GetClass() == cvdescriptorset::DescriptorClass::PlainSampler)) {
1017 const auto *sampler_state =
1018 static_cast<const cvdescriptorset::SamplerDescriptor *>(sampler.second)->GetSamplerState();
1019 if (sampler_state) sampler_states.emplace_back(sampler_state);
1020 }
1021 }
1022 }
1023 }
locke-lunarg4e1e4632020-10-26 01:52:19 -06001024
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001025 if ((!image_view_state && !enabled_features.robustness2_features.nullDescriptor) ||
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001026 (image_view_state && image_view_state->Destroyed())) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001027 // Image view must have been destroyed since initial update. Could potentially flag the descriptor
1028 // as "invalid" (updated = false) at DestroyImageView() time and detect this error at bind time
Jeff Bolz165818a2020-05-08 11:19:03 -05001029
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001030 auto set = descriptor_set->GetSet();
1031 return LogError(set, vuids.descriptor_valid,
1032 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1033 "binding #%" PRIu32 " index %" PRIu32 " is using imageView %s that is invalid or has been destroyed.",
1034 report_data->FormatHandle(set).c_str(), caller, binding, index,
1035 report_data->FormatHandle(image_view).c_str());
1036 }
1037 if (image_view) {
1038 const auto &image_view_ci = image_view_state->create_info;
1039 const auto *image_state = image_view_state->image_state.get();
Jeff Bolz165818a2020-05-08 11:19:03 -05001040
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001041 if (reqs & DESCRIPTOR_REQ_ALL_VIEW_TYPE_BITS) {
1042 if (~reqs & (1 << image_view_ci.viewType)) {
1043 auto set = descriptor_set->GetSet();
1044 return LogError(set, vuids.descriptor_valid,
1045 "Descriptor set %s encountered the following validation error at %s time: Descriptor "
1046 "in binding #%" PRIu32 " index %" PRIu32 " requires an image view of type %s but got %s.",
sfricke-samsungbda4a852021-03-06 20:58:01 -08001047 report_data->FormatHandle(set).c_str(), caller, binding, index,
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001048 StringDescriptorReqViewType(reqs).c_str(), string_VkImageViewType(image_view_ci.viewType));
1049 }
locke-lunarg25b6c352020-08-06 17:44:18 -06001050
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001051 if (!(reqs & image_view_state->descriptor_format_bits)) {
1052 // bad component type
1053 auto set = descriptor_set->GetSet();
1054 return LogError(set, vuids.descriptor_valid,
1055 "Descriptor set %s encountered the following validation error at %s time: "
1056 "Descriptor in binding "
1057 "#%" PRIu32 " index %" PRIu32 " requires %s component type, but bound descriptor format is %s.",
1058 report_data->FormatHandle(set).c_str(), caller, binding, index,
1059 StringDescriptorReqComponentType(reqs), string_VkFormat(image_view_ci.format));
1060 }
1061 }
locke-lunarg540b2252020-08-03 13:23:36 -06001062
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001063 // NOTE: Submit time validation of UPDATE_AFTER_BIND image layout is not possible with the
1064 // image layout tracking as currently implemented, so only record_time_validation is done
1065 if (!disabled[image_layout_validation] && record_time_validate) {
1066 // Verify Image Layout
1067 // No "invalid layout" VUID required for this call, since the optimal_layout parameter is UNDEFINED.
1068 // The caller provides a checked_layouts map when there are a large number of layouts to check,
1069 // making it worthwhile to keep track of verified layouts and not recheck them.
1070 bool already_validated = false;
1071 if (checked_layouts) {
1072 auto search = checked_layouts->find(image_view);
1073 if (search != checked_layouts->end() && search->second == image_layout) {
1074 already_validated = true;
1075 }
1076 }
1077 if (!already_validated) {
1078 bool hit_error = false;
1079 VerifyImageLayout(cb_node, image_state, image_view_state->normalized_subresource_range,
1080 image_view_ci.subresourceRange.aspectMask, image_layout, VK_IMAGE_LAYOUT_UNDEFINED, caller,
1081 kVUIDUndefined, "VUID-VkDescriptorImageInfo-imageLayout-00344", &hit_error);
1082 if (hit_error) {
1083 auto set = descriptor_set->GetSet();
1084 return LogError(set, vuids.descriptor_valid,
1085 "Descriptor set %s encountered the following validation error at %s time: Image layout "
1086 "specified "
1087 "at vkUpdateDescriptorSet* or vkCmdPushDescriptorSet* time "
1088 "doesn't match actual image layout at time descriptor is used. See previous error callback for "
1089 "specific details.",
1090 report_data->FormatHandle(set).c_str(), caller);
1091 }
1092 if (checked_layouts) {
1093 checked_layouts->emplace(image_view, image_layout);
1094 }
1095 }
1096 }
locke-lunarg540b2252020-08-03 13:23:36 -06001097
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001098 // Verify Sample counts
1099 if ((reqs & DESCRIPTOR_REQ_SINGLE_SAMPLE) && image_view_state->samples != VK_SAMPLE_COUNT_1_BIT) {
1100 auto set = descriptor_set->GetSet();
1101 return LogError(set, vuids.descriptor_valid,
1102 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1103 "binding #%" PRIu32 " index %" PRIu32 " requires bound image to have VK_SAMPLE_COUNT_1_BIT but got %s.",
1104 report_data->FormatHandle(set).c_str(), caller, binding, index,
1105 string_VkSampleCountFlagBits(image_view_state->samples));
1106 }
1107 if ((reqs & DESCRIPTOR_REQ_MULTI_SAMPLE) && image_view_state->samples == VK_SAMPLE_COUNT_1_BIT) {
1108 auto set = descriptor_set->GetSet();
1109 return LogError(set, vuids.descriptor_valid,
1110 "Descriptor set %s encountered the following validation error at %s time: Descriptor "
1111 "in binding #%" PRIu32 " index %" PRIu32
1112 " requires bound image to have multiple samples, but got VK_SAMPLE_COUNT_1_BIT.",
1113 report_data->FormatHandle(set).c_str(), caller, binding, index);
1114 }
locke-lunarg36045992020-08-20 16:54:37 -06001115
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001116 // Verify VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
1117 if ((reqs & DESCRIPTOR_REQ_VIEW_ATOMIC_OPERATION) && (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) &&
1118 !(image_view_state->format_features & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)) {
1119 auto set = descriptor_set->GetSet();
1120 LogObjectList objlist(set);
1121 objlist.add(image_view);
1122 return LogError(objlist, vuids.imageview_atomic,
1123 "Descriptor set %s encountered the following validation error at %s time: Descriptor "
1124 "in binding #%" PRIu32 " index %" PRIu32
1125 ", %s, format %s, doesn't "
1126 "contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT.",
1127 report_data->FormatHandle(set).c_str(), caller, binding, index,
1128 report_data->FormatHandle(image_view).c_str(), string_VkFormat(image_view_ci.format));
1129 }
locke-lunarg654a9052020-10-13 16:28:42 -06001130
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001131 // Verify if attachments are used in DescriptorSet
Niels Möller1f945f62021-07-12 15:06:02 +02001132 if (attachments && attachments->size() > 0 && subpasses && (descriptor_type != VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
Jeremy Gebbenb4d17012021-07-08 13:18:15 -06001133 bool ds_aspect = (image_view_state->normalized_subresource_range.aspectMask &
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001134 (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
1135 ? true
1136 : false;
1137 uint32_t att_index = 0;
1138 for (const auto &view_state : *attachments) {
Niels Möller1f945f62021-07-12 15:06:02 +02001139 const SUBPASS_INFO& subpass = (*subpasses)[att_index];
1140 if (!subpass.used || !view_state || view_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001141 continue;
1142 }
Ricardo Garciafe2b7682021-07-30 10:44:57 +02001143 if (ds_aspect && (subpass.usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ||
1144 subpass.usage == VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001145 if ((image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ||
1146 image_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
1147 image_layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL) &&
Niels Möller1f945f62021-07-12 15:06:02 +02001148 (subpass.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ||
1149 subpass.layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
1150 subpass.layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL)) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001151 continue;
Chris Forbes1f7f3ca2017-05-08 13:54:50 -07001152 }
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001153 if ((image_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL &&
Niels Möller1f945f62021-07-12 15:06:02 +02001154 subpass.layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL) ||
1155 (subpass.layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL &&
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001156 image_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)) {
1157 continue;
1158 }
1159 }
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001160 if (view_state->image_view() == image_view) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001161 auto set = descriptor_set->GetSet();
1162 LogObjectList objlist(set);
1163 objlist.add(image_view);
1164 objlist.add(framebuffer);
1165 return LogError(objlist, vuids.image_subresources,
1166 "Descriptor set %s encountered the following validation error at %s time: %s is used in "
1167 "Descriptor in binding #%" PRIu32 " index %" PRIu32 " and %s attachment # %" PRIu32 ".",
1168 report_data->FormatHandle(set).c_str(), caller, report_data->FormatHandle(image_view).c_str(),
1169 binding, index, report_data->FormatHandle(framebuffer).c_str(), att_index);
1170 } else {
1171 if (image_view_state->OverlapSubresource(*view_state)) {
Karl Schultz76d16a42020-11-11 05:05:33 -07001172 auto set = descriptor_set->GetSet();
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001173 LogObjectList objlist(set);
1174 objlist.add(image_view);
1175 objlist.add(framebuffer);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001176 objlist.add(view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001177 return LogError(
1178 objlist, vuids.image_subresources,
1179 "Descriptor set %s encountered the following validation error at %s time: "
1180 "Image subresources of %s in "
1181 "Descriptor in binding #%" PRIu32 " index %" PRIu32 " and %s in %s attachment # %" PRIu32 " overlap.",
1182 report_data->FormatHandle(set).c_str(), caller, report_data->FormatHandle(image_view).c_str(), binding,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001183 index, report_data->FormatHandle(view_state->image_view()).c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001184 report_data->FormatHandle(framebuffer).c_str(), att_index);
Karl Schultz76d16a42020-11-11 05:05:33 -07001185 }
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001186 }
1187 ++att_index;
1188 }
1189 if (enabled_features.core11.protectedMemory == VK_TRUE) {
1190 if (ValidateProtectedImage(cb_node, image_view_state->image_state.get(), caller, vuids.unprotected_command_buffer,
1191 "Image is in a descriptorSet")) {
1192 return true;
1193 }
1194 if (binding_info.second.is_writable &&
1195 ValidateUnprotectedImage(cb_node, image_view_state->image_state.get(), caller, vuids.protected_command_buffer,
1196 "Image is in a descriptorSet")) {
1197 return true;
1198 }
1199 }
1200 }
Chris Forbese92dd1d2019-01-21 15:58:57 -08001201
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001202 for (const auto *sampler_state : sampler_states) {
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001203 if (!sampler_state || sampler_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001204 continue;
1205 }
locke-lunarg25b6c352020-08-06 17:44:18 -06001206
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001207 // TODO: Validate 04015 for DescriptorClass::PlainSampler
1208 if ((sampler_state->createInfo.borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT ||
1209 sampler_state->createInfo.borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT) &&
1210 (sampler_state->customCreateInfo.format == VK_FORMAT_UNDEFINED)) {
1211 if (image_view_state->create_info.format == VK_FORMAT_B4G4R4A4_UNORM_PACK16 ||
1212 image_view_state->create_info.format == VK_FORMAT_B5G6R5_UNORM_PACK16 ||
1213 image_view_state->create_info.format == VK_FORMAT_B5G5R5A1_UNORM_PACK16) {
1214 auto set = descriptor_set->GetSet();
1215 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001216 objlist.add(sampler_state->sampler());
1217 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001218 return LogError(objlist, "VUID-VkSamplerCustomBorderColorCreateInfoEXT-format-04015",
1219 "Descriptor set %s encountered the following validation error at %s time: Sampler %s in "
1220 "binding #%" PRIu32 " index %" PRIu32
1221 " has a custom border color with format = VK_FORMAT_UNDEFINED and is used to "
1222 "sample an image view %s with format %s",
1223 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001224 report_data->FormatHandle(sampler_state->sampler()).c_str(), binding, index,
1225 report_data->FormatHandle(image_view_state->image_view()).c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001226 string_VkFormat(image_view_state->create_info.format));
1227 }
1228 }
1229 VkFilter sampler_mag_filter = sampler_state->createInfo.magFilter;
1230 VkFilter sampler_min_filter = sampler_state->createInfo.minFilter;
1231 VkBool32 sampler_compare_enable = sampler_state->createInfo.compareEnable;
1232 if ((sampler_mag_filter == VK_FILTER_LINEAR || sampler_min_filter == VK_FILTER_LINEAR) &&
1233 (sampler_compare_enable == VK_FALSE) &&
1234 !(image_view_state->format_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
1235 auto set = descriptor_set->GetSet();
1236 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001237 objlist.add(sampler_state->sampler());
1238 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001239 return LogError(objlist, vuids.linear_sampler,
1240 "Descriptor set %s encountered the following validation error at %s time: Sampler "
1241 "(%s) is set to use VK_FILTER_LINEAR with "
1242 "compareEnable is set to VK_TRUE, but image view's (%s) format (%s) does not "
1243 "contain VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT in its format features.",
1244 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001245 report_data->FormatHandle(sampler_state->sampler()).c_str(),
1246 report_data->FormatHandle(image_view_state->image_view()).c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001247 string_VkFormat(image_view_state->create_info.format));
1248 }
1249 if (sampler_mag_filter == VK_FILTER_CUBIC_EXT || sampler_min_filter == VK_FILTER_CUBIC_EXT) {
1250 if (!(image_view_state->format_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) {
1251 auto set = descriptor_set->GetSet();
1252 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001253 objlist.add(sampler_state->sampler());
1254 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001255 return LogError(objlist, vuids.cubic_sampler,
1256 "Descriptor set %s encountered the following validation error at %s time: "
1257 "Sampler (%s) is set to use VK_FILTER_CUBIC_EXT, then "
1258 "image view's (%s) format (%s) MUST contain "
1259 "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT in its format features.",
1260 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001261 report_data->FormatHandle(sampler_state->sampler()).c_str(),
1262 report_data->FormatHandle(image_view_state->image_view()).c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001263 string_VkFormat(image_view_state->create_info.format));
1264 }
1265
1266 if (IsExtEnabled(device_extensions.vk_ext_filter_cubic)) {
1267 const auto reduction_mode_info =
1268 LvlFindInChain<VkSamplerReductionModeCreateInfo>(sampler_state->createInfo.pNext);
1269 if (reduction_mode_info &&
1270 (reduction_mode_info->reductionMode == VK_SAMPLER_REDUCTION_MODE_MIN ||
1271 reduction_mode_info->reductionMode == VK_SAMPLER_REDUCTION_MODE_MAX) &&
1272 !image_view_state->filter_cubic_props.filterCubicMinmax) {
1273 auto set = descriptor_set->GetSet();
1274 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001275 objlist.add(sampler_state->sampler());
1276 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001277 return LogError(objlist, vuids.filter_cubic_min_max,
1278 "Descriptor set %s encountered the following validation error at %s time: "
1279 "Sampler (%s) is set to use VK_FILTER_CUBIC_EXT & %s, "
1280 "but image view (%s) doesn't support filterCubicMinmax.",
1281 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001282 report_data->FormatHandle(sampler_state->sampler()).c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001283 string_VkSamplerReductionMode(reduction_mode_info->reductionMode),
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001284 report_data->FormatHandle(image_view_state->image_view()).c_str());
Chris Forbese92dd1d2019-01-21 15:58:57 -08001285 }
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001286
1287 if (!image_view_state->filter_cubic_props.filterCubic) {
1288 auto set = descriptor_set->GetSet();
1289 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001290 objlist.add(sampler_state->sampler());
1291 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001292 return LogError(objlist, vuids.filter_cubic,
1293 "Descriptor set %s encountered the following validation error at %s time: "
1294 "Sampler (%s) is set to use VK_FILTER_CUBIC_EXT, "
1295 "but image view (%s) doesn't support filterCubic.",
1296 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001297 report_data->FormatHandle(sampler_state->sampler()).c_str(),
1298 report_data->FormatHandle(image_view_state->image_view()).c_str());
Jeff Bolz95176d02020-04-01 00:36:16 -05001299 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001300 }
locke-lunarg4e1e4632020-10-26 01:52:19 -06001301
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001302 if (IsExtEnabled(device_extensions.vk_img_filter_cubic)) {
1303 if (image_view_state->create_info.viewType &
1304 (VK_IMAGE_VIEW_TYPE_3D | VK_IMAGE_VIEW_TYPE_CUBE | VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001305 auto set = descriptor_set->GetSet();
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001306 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001307 objlist.add(sampler_state->sampler());
1308 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001309 return LogError(objlist, vuids.img_filter_cubic,
1310 "Descriptor set %s encountered the following validation error at %s time: Sampler "
1311 "(%s)is set to use VK_FILTER_CUBIC_EXT while the VK_IMG_filter_cubic extension "
1312 "is enabled, but image view (%s) has an invalid imageViewType (%s).",
1313 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001314 report_data->FormatHandle(sampler_state->sampler()).c_str(),
1315 report_data->FormatHandle(image_view_state->image_view()).c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001316 string_VkImageViewType(image_view_state->create_info.viewType));
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001317 }
1318 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001319 }
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001320
1321 if ((image_state->createInfo.flags & VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV) &&
1322 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ||
1323 sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ||
1324 sampler_state->createInfo.addressModeW != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)) {
1325 std::string address_mode_letter =
1326 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1327 ? "U"
1328 : (sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE) ? "V" : "W";
1329 VkSamplerAddressMode address_mode =
1330 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1331 ? sampler_state->createInfo.addressModeU
1332 : (sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1333 ? sampler_state->createInfo.addressModeV
1334 : sampler_state->createInfo.addressModeW;
1335 auto set = descriptor_set->GetSet();
1336 LogObjectList objlist(set);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001337 objlist.add(sampler_state->sampler());
1338 objlist.add(image_state->image());
1339 objlist.add(image_view_state->image_view());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001340 return LogError(objlist, vuids.corner_sampled_address_mode,
1341 "Descriptor set %s encountered the following validation error at %s time: Image "
1342 "(%s) in image view (%s) is created with flag "
1343 "VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV and can only be sampled using "
1344 "VK_SAMPLER_ADDRESS_MODE_CLAMP_EDGE, but sampler (%s) has "
1345 "createInfo.addressMode%s set to %s.",
1346 report_data->FormatHandle(set).c_str(), caller,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001347 report_data->FormatHandle(image_state->image()).c_str(),
1348 report_data->FormatHandle(image_view_state->image_view()).c_str(),
1349 report_data->FormatHandle(sampler_state->sampler()).c_str(), address_mode_letter.c_str(),
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001350 string_VkSamplerAddressMode(address_mode));
1351 }
1352
1353 // UnnormalizedCoordinates sampler validations
1354 if (sampler_state->createInfo.unnormalizedCoordinates) {
1355 // If ImageView is used by a unnormalizedCoordinates sampler, it needs to check ImageView type
1356 if (image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_3D || image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
1357 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY ||
1358 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY ||
1359 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
1360 auto set = descriptor_set->GetSet();
1361 LogObjectList objlist(set);
1362 objlist.add(image_view);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001363 objlist.add(sampler_state->sampler());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001364 return LogError(objlist, vuids.sampler_imageview_type,
1365 "Descriptor set %s encountered the following validation error at %s time: %s, type: %s in "
1366 "Descriptor in binding #%" PRIu32 " index %" PRIu32 "is used by %s.",
1367 report_data->FormatHandle(set).c_str(), caller, report_data->FormatHandle(image_view).c_str(),
1368 string_VkImageViewType(image_view_ci.viewType), binding, index,
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001369 report_data->FormatHandle(sampler_state->sampler()).c_str());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001370 }
1371
1372 // sampler must not be used with any of the SPIR-V OpImageSample* or OpImageSparseSample*
1373 // instructions with ImplicitLod, Dref or Proj in their name
1374 if (reqs & DESCRIPTOR_REQ_SAMPLER_IMPLICITLOD_DREF_PROJ) {
1375 auto set = descriptor_set->GetSet();
1376 LogObjectList objlist(set);
1377 objlist.add(image_view);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001378 objlist.add(sampler_state->sampler());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001379 return LogError(objlist, vuids.sampler_implicitLod_dref_proj,
1380 "Descriptor set %s encountered the following validation error at %s time: %s in "
1381 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1382 " is used by %s that uses invalid operator.",
1383 report_data->FormatHandle(set).c_str(), caller, report_data->FormatHandle(image_view).c_str(),
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001384 binding, index, report_data->FormatHandle(sampler_state->sampler()).c_str());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001385 }
1386
1387 // sampler must not be used with any of the SPIR-V OpImageSample* or OpImageSparseSample*
1388 // instructions that includes a LOD bias or any offset values
1389 if (reqs & DESCRIPTOR_REQ_SAMPLER_BIAS_OFFSET) {
1390 auto set = descriptor_set->GetSet();
1391 LogObjectList objlist(set);
1392 objlist.add(image_view);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001393 objlist.add(sampler_state->sampler());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001394 return LogError(objlist, vuids.sampler_bias_offset,
1395 "Descriptor set %s encountered the following validation error at %s time: %s in "
1396 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1397 " is used by %s that uses invalid bias or offset operator.",
1398 report_data->FormatHandle(set).c_str(), caller, report_data->FormatHandle(image_view).c_str(),
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001399 binding, index, report_data->FormatHandle(sampler_state->sampler()).c_str());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001400 }
1401 }
1402 }
1403 }
1404 return false;
1405}
1406
1407bool CoreChecks::ValidateTexelDescriptor(const char *caller, const DrawDispatchVuid &vuids, const CMD_BUFFER_STATE *cb_node,
1408 const cvdescriptorset::DescriptorSet *descriptor_set,
1409 const cvdescriptorset::TexelDescriptor &texel_descriptor,
1410 const std::pair<const uint32_t, DescriptorRequirement> &binding_info,
1411 uint32_t index) const {
1412 auto buffer_view = texel_descriptor.GetBufferView();
1413 auto buffer_view_state = texel_descriptor.GetBufferViewState();
1414 const auto binding = binding_info.first;
1415 const auto reqs = binding_info.second.reqs;
1416 if ((!buffer_view_state && !enabled_features.robustness2_features.nullDescriptor) ||
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001417 (buffer_view_state && buffer_view_state->Destroyed())) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001418 auto set = descriptor_set->GetSet();
1419 return LogError(set, vuids.descriptor_valid,
1420 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1421 "binding #%" PRIu32 " index %" PRIu32 " is using bufferView %s that is invalid or has been destroyed.",
1422 report_data->FormatHandle(set).c_str(), caller, binding, index,
1423 report_data->FormatHandle(buffer_view).c_str());
1424 }
1425 if (buffer_view) {
1426 auto buffer = buffer_view_state->create_info.buffer;
1427 auto buffer_state = buffer_view_state->buffer_state.get();
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001428 if (buffer_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001429 auto set = descriptor_set->GetSet();
1430 return LogError(set, vuids.descriptor_valid,
1431 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1432 "binding #%" PRIu32 " index %" PRIu32 " is using buffer %s that has been destroyed.",
1433 report_data->FormatHandle(set).c_str(), caller, binding, index,
1434 report_data->FormatHandle(buffer).c_str());
1435 }
1436 auto format_bits = DescriptorRequirementsBitsFromFormat(buffer_view_state->create_info.format);
1437
1438 if (!(reqs & format_bits)) {
1439 // bad component type
1440 auto set = descriptor_set->GetSet();
1441 return LogError(set, vuids.descriptor_valid,
1442 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1443 "binding #%" PRIu32 " index %" PRIu32 " requires %s component type, but bound descriptor format is %s.",
1444 report_data->FormatHandle(set).c_str(), caller, binding, index, StringDescriptorReqComponentType(reqs),
1445 string_VkFormat(buffer_view_state->create_info.format));
1446 }
1447
1448 // Verify VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT
1449 if ((reqs & DESCRIPTOR_REQ_VIEW_ATOMIC_OPERATION) &&
1450 (descriptor_set->GetTypeFromBinding(binding) == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) &&
1451 !(buffer_view_state->format_features & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT)) {
1452 auto set = descriptor_set->GetSet();
1453 LogObjectList objlist(set);
1454 objlist.add(buffer_view);
1455 return LogError(objlist, "UNASSIGNED-None-MismatchAtomicBufferFeature",
1456 "Descriptor set %s encountered the following validation error at %s time: Descriptor "
1457 "in binding #%" PRIu32 " index %" PRIu32
1458 ", %s, format %s, doesn't "
1459 "contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT.",
1460 report_data->FormatHandle(set).c_str(), caller, binding, index,
1461 report_data->FormatHandle(buffer_view).c_str(), string_VkFormat(buffer_view_state->create_info.format));
1462 }
1463 if (enabled_features.core11.protectedMemory == VK_TRUE) {
1464 if (ValidateProtectedBuffer(cb_node, buffer_view_state->buffer_state.get(), caller, vuids.unprotected_command_buffer,
1465 "Buffer is in a descriptorSet")) {
1466 return true;
1467 }
1468 if (binding_info.second.is_writable &&
1469 ValidateUnprotectedBuffer(cb_node, buffer_view_state->buffer_state.get(), caller, vuids.protected_command_buffer,
1470 "Buffer is in a descriptorSet")) {
1471 return true;
1472 }
1473 }
1474 }
1475 return false;
1476}
1477
1478bool CoreChecks::ValidateAccelerationDescriptor(const char *caller, const DrawDispatchVuid &vuids, const CMD_BUFFER_STATE *cb_node,
1479 const cvdescriptorset::DescriptorSet *descriptor_set,
1480 const cvdescriptorset::AccelerationStructureDescriptor &descriptor,
1481 const std::pair<const uint32_t, DescriptorRequirement> &binding_info,
1482 uint32_t index) const {
1483 // Verify that acceleration structures are valid
1484 const auto binding = binding_info.first;
1485 if (descriptor.is_khr()) {
1486 auto acc = descriptor.GetAccelerationStructure();
1487 auto acc_node = descriptor.GetAccelerationStructureStateKHR();
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001488 if (!acc_node || acc_node->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001489 if (acc != VK_NULL_HANDLE || !enabled_features.robustness2_features.nullDescriptor) {
1490 auto set = descriptor_set->GetSet();
1491 return LogError(set, vuids.descriptor_valid,
1492 "Descriptor set %s encountered the following validation error at %s time: "
1493 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1494 " is using acceleration structure %s that is invalid or has been destroyed.",
1495 report_data->FormatHandle(set).c_str(), caller, binding, index,
1496 report_data->FormatHandle(acc).c_str());
1497 }
1498 } else {
Jeremy Gebben6fbf8242021-06-21 09:14:46 -06001499 for (const auto &item: acc_node->GetBoundMemory()) {
1500 auto &mem_binding = item.second;
1501 if (mem_binding.mem_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001502 auto set = descriptor_set->GetSet();
1503 return LogError(set, vuids.descriptor_valid,
1504 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1505 "binding #%" PRIu32 " index %" PRIu32
1506 " is using acceleration structure %s that references invalid memory %s.",
1507 report_data->FormatHandle(set).c_str(), caller, binding, index,
Jeremy Gebben6fbf8242021-06-21 09:14:46 -06001508 report_data->FormatHandle(acc).c_str(),
1509 report_data->FormatHandle(mem_binding.mem_state->mem()).c_str());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001510 }
1511 }
1512 }
1513 } else {
1514 auto acc = descriptor.GetAccelerationStructureNV();
1515 auto acc_node = descriptor.GetAccelerationStructureStateNV();
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001516 if (!acc_node || acc_node->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001517 if (acc != VK_NULL_HANDLE || !enabled_features.robustness2_features.nullDescriptor) {
1518 auto set = descriptor_set->GetSet();
1519 return LogError(set, vuids.descriptor_valid,
1520 "Descriptor set %s encountered the following validation error at %s time: "
1521 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1522 " is using acceleration structure %s that is invalid or has been destroyed.",
1523 report_data->FormatHandle(set).c_str(), caller, binding, index,
1524 report_data->FormatHandle(acc).c_str());
1525 }
1526 } else {
Jeremy Gebben6fbf8242021-06-21 09:14:46 -06001527 for (const auto &item : acc_node->GetBoundMemory()) {
1528 auto &mem_binding = item.second;
1529 if (mem_binding.mem_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001530 auto set = descriptor_set->GetSet();
1531 return LogError(set, vuids.descriptor_valid,
1532 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1533 "binding #%" PRIu32 " index %" PRIu32
1534 " is using acceleration structure %s that references invalid memory %s.",
1535 report_data->FormatHandle(set).c_str(), caller, binding, index,
Jeremy Gebben6fbf8242021-06-21 09:14:46 -06001536 report_data->FormatHandle(acc).c_str(),
1537 report_data->FormatHandle(mem_binding.mem_state->mem()).c_str());
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001538 }
1539 }
1540 }
1541 }
1542 return false;
1543}
1544
1545// If the validation is related to both of image and sampler,
1546// please leave it in (descriptor_class == DescriptorClass::ImageSampler || descriptor_class ==
1547// DescriptorClass::Image) Here is to validate for only sampler.
1548bool CoreChecks::ValidateSamplerDescriptor(const char *caller, const DrawDispatchVuid &vuids, const CMD_BUFFER_STATE *cb_node,
1549 const cvdescriptorset::DescriptorSet *descriptor_set,
1550 const std::pair<const uint32_t, DescriptorRequirement> &binding_info, uint32_t index,
1551 VkSampler sampler, bool is_immutable, const SAMPLER_STATE *sampler_state) const {
1552 // Verify Sampler still valid
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001553 if (!sampler_state || sampler_state->Destroyed()) {
Jeremy Gebbene151b6b2021-04-09 18:03:06 -06001554 auto set = descriptor_set->GetSet();
1555 return LogError(set, vuids.descriptor_valid,
1556 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1557 "binding #%" PRIu32 " index %" PRIu32 " is using sampler %s that is invalid or has been destroyed.",
1558 report_data->FormatHandle(set).c_str(), caller, binding_info.first, index,
1559 report_data->FormatHandle(sampler).c_str());
1560 } else {
1561 if (sampler_state->samplerConversion && !is_immutable) {
1562 auto set = descriptor_set->GetSet();
1563 return LogError(set, vuids.descriptor_valid,
1564 "Descriptor set %s encountered the following validation error at %s time: sampler (%s) "
1565 "in the descriptor set (%s) contains a YCBCR conversion (%s), then the sampler MUST "
1566 "also exist as an immutable sampler.",
1567 report_data->FormatHandle(set).c_str(), caller, report_data->FormatHandle(sampler).c_str(),
1568 report_data->FormatHandle(descriptor_set->GetSet()).c_str(),
1569 report_data->FormatHandle(sampler_state->samplerConversion).c_str());
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001570 }
1571 }
Tony-LunarGace473a2020-05-06 12:48:04 -06001572 return false;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001573}
Chris Forbes57989132016-07-26 17:06:10 +12001574
John Zulauf1d27e0a2018-11-05 10:12:48 -07001575// Loop through the write updates to do for a push descriptor set, ignoring dstSet
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001576void cvdescriptorset::DescriptorSet::PerformPushDescriptorsUpdate(ValidationStateTracker *dev_data, uint32_t write_count,
1577 const VkWriteDescriptorSet *p_wds) {
John Zulauf1d27e0a2018-11-05 10:12:48 -07001578 assert(IsPushDescriptor());
1579 for (uint32_t i = 0; i < write_count; i++) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001580 PerformWriteUpdate(dev_data, &p_wds[i]);
John Zulauf1d27e0a2018-11-05 10:12:48 -07001581 }
Jason Macnak83cfd582019-07-31 10:14:24 -07001582
1583 push_descriptor_set_writes.clear();
1584 push_descriptor_set_writes.reserve(static_cast<std::size_t>(write_count));
1585 for (uint32_t i = 0; i < write_count; i++) {
1586 push_descriptor_set_writes.push_back(safe_VkWriteDescriptorSet(&p_wds[i]));
1587 }
John Zulauf1d27e0a2018-11-05 10:12:48 -07001588}
1589
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001590// Perform write update in given update struct
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001591void cvdescriptorset::DescriptorSet::PerformWriteUpdate(ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update) {
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001592 // Perform update on a per-binding basis as consecutive updates roll over to next binding
1593 auto descriptors_remaining = update->descriptorCount;
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001594 auto offset = update->dstArrayElement;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001595 auto orig_binding = DescriptorSetLayout::ConstBindingIterator(layout_.get(), update->dstBinding);
locke-lunarge46b7782019-09-10 01:44:20 -06001596 auto current_binding = orig_binding;
1597
Tobin Ehlise16805c2017-08-09 09:10:37 -06001598 uint32_t update_index = 0;
locke-lunarge46b7782019-09-10 01:44:20 -06001599 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
1600 while (descriptors_remaining && orig_binding.IsConsistent(current_binding)) {
1601 const auto &index_range = current_binding.GetGlobalIndexRange();
1602 auto global_idx = index_range.start + offset;
1603 // global_idx is which descriptor is needed to update. If global_idx > index_range.end, it means the descriptor isn't in
1604 // this binding, maybe in next binding.
1605 if (global_idx >= index_range.end) {
1606 offset -= current_binding.GetDescriptorCount();
1607 ++current_binding;
1608 continue;
1609 }
1610
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001611 // Loop over the updates for a single binding at a time
locke-lunarge46b7782019-09-10 01:44:20 -06001612 uint32_t update_count = std::min(descriptors_remaining, current_binding.GetDescriptorCount() - offset);
Tobin Ehlise16805c2017-08-09 09:10:37 -06001613 for (uint32_t di = 0; di < update_count; ++di, ++update_index) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06001614 descriptors_[global_idx + di]->WriteUpdate(this, state_data_, update, update_index);
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001615 }
1616 // Roll over to next binding in case of consecutive update
1617 descriptors_remaining -= update_count;
locke-lunarge46b7782019-09-10 01:44:20 -06001618 if (descriptors_remaining) {
1619 // Starting offset is beyond the current binding. Check consistency, update counters and advance to the next binding,
1620 // looking for the start point. All bindings (even those skipped) must be consistent with the update and with the
1621 // original binding.
1622 offset = 0;
1623 ++current_binding;
1624 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001625 }
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05001626 if (update->descriptorCount) {
1627 some_update_ = true;
1628 change_count_++;
1629 }
Tobin Ehlis56a30942016-05-19 08:00:00 -06001630
Jeremy Gebben5570abe2021-05-16 18:35:13 -06001631 if (!IsPushDescriptor() && !(layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Mike Schuchardt2df08912020-12-15 16:28:09 -08001632 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT))) {
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001633 Invalidate(false);
Jeff Bolzfdf96072018-04-10 14:32:18 -05001634 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001635}
Tobin Ehlis300888c2016-05-18 13:43:26 -06001636// Validate Copy update
John Zulaufc93c4252019-06-25 09:19:49 -06001637bool CoreChecks::ValidateCopyUpdate(const VkCopyDescriptorSet *update, const DescriptorSet *dst_set, const DescriptorSet *src_set,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05001638 const char *func_name, std::string *error_code, std::string *error_msg) const {
Jeff Bolz6aad1742019-10-16 11:10:09 -05001639 auto dst_layout = dst_set->GetLayout().get();
1640 auto src_layout = src_set->GetLayout().get();
John Zulaufd9435c32019-06-05 15:55:36 -06001641
John Zulauf5dfd45c2018-01-17 11:06:34 -07001642 // Verify dst layout still valid
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001643 if (dst_layout->Destroyed()) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001644 *error_code = "VUID-VkCopyDescriptorSet-dstSet-parameter";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06001645 std::ostringstream str;
1646 str << "Cannot call " << func_name << " to perform copy update on dstSet " << report_data->FormatHandle(dst_set->GetSet())
1647 << " created with destroyed " << report_data->FormatHandle(dst_layout->GetDescriptorSetLayout()) << ".";
1648 *error_msg = str.str();
John Zulauf5dfd45c2018-01-17 11:06:34 -07001649 return false;
1650 }
1651
1652 // Verify src layout still valid
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001653 if (src_layout->Destroyed()) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001654 *error_code = "VUID-VkCopyDescriptorSet-srcSet-parameter";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06001655 std::ostringstream str;
1656 str << "Cannot call " << func_name << " to perform copy update on dstSet " << report_data->FormatHandle(dst_set->GetSet())
1657 << " from srcSet " << report_data->FormatHandle(src_set->GetSet()) << " created with destroyed "
1658 << report_data->FormatHandle(src_layout->GetDescriptorSetLayout()) << ".";
1659 *error_msg = str.str();
John Zulauf5dfd45c2018-01-17 11:06:34 -07001660 return false;
1661 }
1662
John Zulaufd9435c32019-06-05 15:55:36 -06001663 if (!dst_layout->HasBinding(update->dstBinding)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001664 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-00347";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001665 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001666 error_str << "DescriptorSet " << report_data->FormatHandle(dst_set->GetSet())
1667 << " does not have copy update dest binding of " << update->dstBinding;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001668 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001669 return false;
1670 }
1671 if (!src_set->HasBinding(update->srcBinding)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001672 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-00345";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001673 std::stringstream error_str;
sourav parmarf4a78252020-04-10 13:04:21 -07001674 error_str << "DescriptorSet " << report_data->FormatHandle(src_set->GetSet())
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001675 << " does not have copy update src binding of " << update->srcBinding;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001676 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001677 return false;
1678 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001679 // Verify idle ds
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001680 if (dst_set->InUse() &&
John Zulaufd9435c32019-06-05 15:55:36 -06001681 !(dst_layout->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Mike Schuchardt2df08912020-12-15 16:28:09 -08001682 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT))) {
Jeff Bolzfdf96072018-04-10 14:32:18 -05001683 // TODO : Re-using Free Idle error code, need copy update idle error code
Dave Houlton00c154e2018-05-24 13:20:50 -06001684 *error_code = "VUID-vkFreeDescriptorSets-pDescriptorSets-00309";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001685 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001686 error_str << "Cannot call " << func_name << " to perform copy update on descriptor set "
1687 << report_data->FormatHandle(dst_set->GetSet()) << " that is in use by a command buffer";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001688 *error_msg = error_str.str();
1689 return false;
1690 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001691 // src & dst set bindings are valid
1692 // Check bounds of src & dst
John Zulaufc483f442017-12-15 14:02:06 -07001693 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001694 if ((src_start_idx + update->descriptorCount) > src_set->GetTotalDescriptorCount()) {
1695 // SRC update out of bounds
Dave Houlton00c154e2018-05-24 13:20:50 -06001696 *error_code = "VUID-VkCopyDescriptorSet-srcArrayElement-00346";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001697 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001698 error_str << "Attempting copy update from descriptorSet " << report_data->FormatHandle(update->srcSet) << " binding#"
1699 << update->srcBinding << " with offset index of "
1700 << src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start << " plus update array offset of "
1701 << update->srcArrayElement << " and update of " << update->descriptorCount
Tobin Ehlis1d81edd2016-11-21 09:50:49 -07001702 << " descriptors oversteps total number of descriptors in set: " << src_set->GetTotalDescriptorCount();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001703 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001704 return false;
1705 }
John Zulaufd9435c32019-06-05 15:55:36 -06001706 auto dst_start_idx = dst_layout->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
1707 if ((dst_start_idx + update->descriptorCount) > dst_layout->GetTotalDescriptorCount()) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001708 // DST update out of bounds
Dave Houlton00c154e2018-05-24 13:20:50 -06001709 *error_code = "VUID-VkCopyDescriptorSet-dstArrayElement-00348";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001710 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001711 error_str << "Attempting copy update to descriptorSet " << report_data->FormatHandle(dst_set->GetSet()) << " binding#"
1712 << update->dstBinding << " with offset index of "
1713 << dst_layout->GetGlobalIndexRangeFromBinding(update->dstBinding).start << " plus update array offset of "
1714 << update->dstArrayElement << " and update of " << update->descriptorCount
John Zulaufd9435c32019-06-05 15:55:36 -06001715 << " descriptors oversteps total number of descriptors in set: " << dst_layout->GetTotalDescriptorCount();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001716 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001717 return false;
1718 }
1719 // Check that types match
Shannon McPhersonafe55122020-05-25 16:20:19 -06001720 // TODO : Base default error case going from here is "VUID-VkAcquireNextImageInfoKHR-semaphore-parameter" 2ba which covers all
Dave Houltond8ed0212018-05-16 17:18:24 -06001721 // consistency issues, need more fine-grained error codes
Dave Houlton00c154e2018-05-24 13:20:50 -06001722 *error_code = "VUID-VkCopyDescriptorSet-srcSet-00349";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001723 auto src_type = src_set->GetTypeFromBinding(update->srcBinding);
John Zulaufd9435c32019-06-05 15:55:36 -06001724 auto dst_type = dst_layout->GetTypeFromBinding(update->dstBinding);
Ricardo Garcia14f4f762021-04-13 11:36:12 +02001725 if (src_type != VK_DESCRIPTOR_TYPE_MUTABLE_VALVE && dst_type != VK_DESCRIPTOR_TYPE_MUTABLE_VALVE && src_type != dst_type) {
sourav parmarf4a78252020-04-10 13:04:21 -07001726 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02632";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001727 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001728 error_str << "Attempting copy update to descriptorSet " << report_data->FormatHandle(dst_set->GetSet()) << " binding #"
1729 << update->dstBinding << " with type " << string_VkDescriptorType(dst_type) << " from descriptorSet "
1730 << report_data->FormatHandle(src_set->GetSet()) << " binding #" << update->srcBinding << " with type "
1731 << string_VkDescriptorType(src_type) << ". Types do not match";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001732 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001733 return false;
1734 }
1735 // Verify consistency of src & dst bindings if update crosses binding boundaries
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001736 if ((!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(src_layout, update->srcBinding),
John Zulauf4a015c92019-06-04 09:50:05 -06001737 update->srcArrayElement, update->descriptorCount, "copy update from", src_set->GetSet(),
1738 error_msg)) ||
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001739 (!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(dst_layout, update->dstBinding),
John Zulaufd9435c32019-06-05 15:55:36 -06001740 update->dstArrayElement, update->descriptorCount, "copy update to", dst_set->GetSet(),
1741 error_msg))) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001742 return false;
1743 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001744
Mike Schuchardt2df08912020-12-15 16:28:09 -08001745 if ((src_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT) &&
1746 !(dst_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001747 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01918";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001748 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001749 error_str << "If pname:srcSet's (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001750 << ") layout was created with the "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001751 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag "
Jeff Bolzfdf96072018-04-10 14:32:18 -05001752 "set, then pname:dstSet's ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001753 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001754 << ") layout must: also have been created with the "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001755 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag set";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001756 *error_msg = error_str.str();
1757 return false;
1758 }
1759
sfricke-samsung45996a42021-09-16 13:45:27 -07001760 if (IsExtEnabled(device_extensions.vk_valve_mutable_descriptor_type)) {
Mike Schuchardt294a1592021-05-12 15:38:00 -07001761 if (!(src_layout->GetCreateFlags() & (VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT |
1762 VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE)) &&
1763 (dst_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT)) {
1764 *error_code = "VUID-VkCopyDescriptorSet-srcSet-04885";
1765 std::stringstream error_str;
1766 error_str << "If pname:srcSet's (" << report_data->FormatHandle(update->srcSet)
1767 << ") layout was created with neither ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT nor "
1768 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE flags set, then pname:dstSet's ("
1769 << report_data->FormatHandle(update->dstSet)
1770 << ") layout must: have been created without the "
1771 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag set";
1772 *error_msg = error_str.str();
1773 return false;
1774 }
1775 } else {
1776 if (!(src_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT) &&
1777 (dst_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT)) {
1778 *error_code = "VUID-VkCopyDescriptorSet-srcSet-04886";
1779 std::stringstream error_str;
1780 error_str << "If pname:srcSet's (" << report_data->FormatHandle(update->srcSet)
1781 << ") layout was created without the ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag "
1782 "set, then pname:dstSet's ("
1783 << report_data->FormatHandle(update->dstSet)
1784 << ") layout must: also have been created without the "
1785 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag set";
1786 *error_msg = error_str.str();
1787 return false;
1788 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001789 }
1790
Mike Schuchardt2df08912020-12-15 16:28:09 -08001791 if ((src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT) &&
1792 !(dst_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001793 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01920";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001794 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001795 error_str << "If the descriptor pool from which pname:srcSet (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001796 << ") was allocated was created "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001797 "with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag "
Jeff Bolzfdf96072018-04-10 14:32:18 -05001798 "set, then the descriptor pool from which pname:dstSet ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001799 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001800 << ") was allocated must: "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001801 "also have been created with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag set";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001802 *error_msg = error_str.str();
1803 return false;
1804 }
1805
sfricke-samsung45996a42021-09-16 13:45:27 -07001806 if (IsExtEnabled(device_extensions.vk_valve_mutable_descriptor_type)) {
Mike Schuchardt294a1592021-05-12 15:38:00 -07001807 if (!(src_set->GetPoolState()->createInfo.flags &
1808 (VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE)) &&
1809 (dst_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT)) {
1810 *error_code = "VUID-VkCopyDescriptorSet-srcSet-04887";
1811 std::stringstream error_str;
1812 error_str << "If the descriptor pool from which pname:srcSet (" << report_data->FormatHandle(update->srcSet)
1813 << ") was allocated was created with neither ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT nor "
1814 "ename:VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE flags set, then the descriptor pool from which "
1815 "pname:dstSet ("
1816 << report_data->FormatHandle(update->dstSet)
1817 << ") was allocated must: have been created without the "
1818 "ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag set";
1819 *error_msg = error_str.str();
1820 return false;
1821 }
1822 } else {
1823 if (!(src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT) &&
1824 (dst_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT)) {
1825 *error_code = "VUID-VkCopyDescriptorSet-srcSet-04888";
1826 std::stringstream error_str;
1827 error_str << "If the descriptor pool from which pname:srcSet (" << report_data->FormatHandle(update->srcSet)
1828 << ") was allocated was created without the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag set, "
1829 "then the descriptor pool from which pname:dstSet ("
1830 << report_data->FormatHandle(update->dstSet)
1831 << ") was allocated must: also have been created without the "
1832 "ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag set";
1833 *error_msg = error_str.str();
1834 return false;
1835 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001836 }
1837
Jeff Bolze54ae892018-09-08 12:16:29 -05001838 if (src_type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
1839 if ((update->srcArrayElement % 4) != 0) {
1840 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-02223";
1841 std::stringstream error_str;
1842 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1843 << "srcArrayElement " << update->srcArrayElement << " not a multiple of 4";
1844 *error_msg = error_str.str();
1845 return false;
1846 }
1847 if ((update->dstArrayElement % 4) != 0) {
1848 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02224";
1849 std::stringstream error_str;
1850 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1851 << "dstArrayElement " << update->dstArrayElement << " not a multiple of 4";
1852 *error_msg = error_str.str();
1853 return false;
1854 }
1855 if ((update->descriptorCount % 4) != 0) {
1856 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-02225";
1857 std::stringstream error_str;
1858 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1859 << "descriptorCount " << update->descriptorCount << " not a multiple of 4";
1860 *error_msg = error_str.str();
1861 return false;
1862 }
1863 }
1864
Tobin Ehlisd41e7b62016-05-19 07:56:18 -06001865 // Update parameters all look good and descriptor updated so verify update contents
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07001866 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 -07001867 error_msg)) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07001868 return false;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001869 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06001870
1871 // All checks passed so update is good
1872 return true;
1873}
1874// Perform Copy update
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001875void cvdescriptorset::DescriptorSet::PerformCopyUpdate(ValidationStateTracker *dev_data, const VkCopyDescriptorSet *update,
1876 const DescriptorSet *src_set) {
John Zulaufc483f442017-12-15 14:02:06 -07001877 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001878 auto dst_start_idx = layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001879 // Update parameters all look good so perform update
1880 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Józef Kucia5297e372017-10-13 22:31:34 +02001881 auto src = src_set->descriptors_[src_start_idx + di].get();
1882 auto dst = descriptors_[dst_start_idx + di].get();
1883 if (src->updated) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06001884 dst->CopyUpdate(this, state_data_, src);
Józef Kucia5297e372017-10-13 22:31:34 +02001885 some_update_ = true;
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05001886 change_count_++;
Józef Kucia5297e372017-10-13 22:31:34 +02001887 } else {
1888 dst->updated = false;
1889 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001890 }
Tobin Ehlis56a30942016-05-19 08:00:00 -06001891
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001892 if (!(layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Mike Schuchardt2df08912020-12-15 16:28:09 -08001893 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT))) {
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06001894 Invalidate(false);
Jeff Bolzfdf96072018-04-10 14:32:18 -05001895 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001896}
Tobin Ehlis56a30942016-05-19 08:00:00 -06001897
John Zulauf6f3d2bd2018-10-29 17:08:42 -06001898// Update the drawing state for the affected descriptors.
1899// Set cb_node to this set and this set to cb_node.
1900// Add the bindings of the descriptor
1901// Set the layout based on the current descriptor layout (will mask subsequent layer mismatch errors)
1902// TODO: Modify the UpdateDrawState virtural functions to *only* set initial layout and not change layouts
Tobin Ehlisf9519102016-08-17 09:49:13 -06001903// Prereq: This should be called for a set that has been confirmed to be active for the given cb_node, meaning it's going
1904// to be used in a draw by the given cb_node
Jeremy Kniagere6827432020-04-01 09:05:56 -06001905void cvdescriptorset::DescriptorSet::UpdateDrawState(ValidationStateTracker *device_data, CMD_BUFFER_STATE *cb_node,
1906 CMD_TYPE cmd_type, const PIPELINE_STATE *pipe,
sfricke-samsung85584a72021-09-30 21:43:38 -07001907 const BindingReqMap &binding_req_map) {
Tony-LunarG77822802020-05-28 16:35:46 -06001908 if (!device_data->disabled[command_buffer_state] && !IsPushDescriptor()) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06001909 cb_node->AddChild(this);
Jeff Bolzafa429a2019-08-14 09:59:22 -05001910 }
Jeff Bolze18e7242019-08-12 20:55:22 -05001911
Jeremy Gebben5570abe2021-05-16 18:35:13 -06001912 // Descriptor UpdateDrawState only call image layout validation callbacks. If it is disabled, skip the entire loop.
1913 if (device_data->disabled[image_layout_validation]) {
Jeff Bolze18e7242019-08-12 20:55:22 -05001914 return;
1915 }
1916
Tobin Ehlisf9519102016-08-17 09:49:13 -06001917 // For the active slots, use set# to look up descriptorSet from boundDescriptorSets, and bind all of that descriptor set's
1918 // resources
locke-lunarg540b2252020-08-03 13:23:36 -06001919 CMD_BUFFER_STATE::CmdDrawDispatchInfo cmd_info = {};
John Zulauf79f06582021-02-27 18:38:39 -07001920 for (const auto &binding_req_pair : binding_req_map) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001921 auto index = layout_->GetIndexFromBinding(binding_req_pair.first);
locke-gb3ce08f2019-09-30 12:30:56 -06001922
Tony-LunarG62c5dba2018-12-20 14:27:23 -07001923 // 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 -07001924 auto flags = layout_->GetDescriptorBindingFlagsFromIndex(index);
Mike Schuchardt2df08912020-12-15 16:28:09 -08001925 if (flags & (VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT)) {
1926 if (!(flags & VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT)) {
locke-lunarg36045992020-08-20 16:54:37 -06001927 cmd_info.binding_infos.emplace_back(binding_req_pair);
locke-gb3ce08f2019-09-30 12:30:56 -06001928 }
Tony-LunarG62c5dba2018-12-20 14:27:23 -07001929 continue;
1930 }
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001931 auto range = layout_->GetGlobalIndexRangeFromIndex(index);
John Zulaufc483f442017-12-15 14:02:06 -07001932 for (uint32_t i = range.start; i < range.end; ++i) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06001933 const auto descriptor_class = descriptors_[i]->GetClass();
1934 switch (descriptor_class) {
1935 case DescriptorClass::Image:
1936 case DescriptorClass::ImageSampler: {
1937 auto *image_desc = static_cast<ImageDescriptor *>(descriptors_[i].get());
1938 image_desc->UpdateDrawState(device_data, cb_node);
1939 break;
1940 }
1941 default:
1942 break;
1943 }
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06001944 }
1945 }
locke-lunarg540b2252020-08-03 13:23:36 -06001946
1947 if (cmd_info.binding_infos.size() > 0) {
1948 cmd_info.cmd_type = cmd_type;
locke-lunarg540b2252020-08-03 13:23:36 -06001949 if (cb_node->activeFramebuffer) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001950 cmd_info.framebuffer = cb_node->activeFramebuffer->framebuffer();
locke-lunargfc78e932020-11-19 17:06:24 -07001951 cmd_info.attachments = cb_node->active_attachments;
1952 cmd_info.subpasses = cb_node->active_subpasses;
locke-lunarg540b2252020-08-03 13:23:36 -06001953 }
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001954 cb_node->validate_descriptorsets_in_queuesubmit[GetSet()].emplace_back(cmd_info);
locke-lunarg540b2252020-08-03 13:23:36 -06001955 }
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06001956}
1957
John Zulauffbf3c202019-07-17 14:57:14 -06001958void cvdescriptorset::DescriptorSet::FilterOneBindingReq(const BindingReqMap::value_type &binding_req_pair, BindingReqMap *out_req,
1959 const TrackedBindings &bindings, uint32_t limit) {
1960 if (bindings.size() < limit) {
1961 const auto it = bindings.find(binding_req_pair.first);
1962 if (it == bindings.cend()) out_req->emplace(binding_req_pair);
John Zulauf48a6a702017-12-22 17:14:54 -07001963 }
1964}
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06001965
John Zulauffbf3c202019-07-17 14:57:14 -06001966void cvdescriptorset::DescriptorSet::FilterBindingReqs(const CMD_BUFFER_STATE &cb_state, const PIPELINE_STATE &pipeline,
1967 const BindingReqMap &in_req, BindingReqMap *out_req) const {
1968 // For const cleanliness we have to find in the maps...
1969 const auto validated_it = cached_validation_.find(&cb_state);
1970 if (validated_it == cached_validation_.cend()) {
1971 // We have nothing validated, copy in to out
1972 for (const auto &binding_req_pair : in_req) {
1973 out_req->emplace(binding_req_pair);
John Zulauf48a6a702017-12-22 17:14:54 -07001974 }
John Zulauffbf3c202019-07-17 14:57:14 -06001975 return;
John Zulauf48a6a702017-12-22 17:14:54 -07001976 }
John Zulauffbf3c202019-07-17 14:57:14 -06001977 const auto &validated = validated_it->second;
John Zulauf48a6a702017-12-22 17:14:54 -07001978
John Zulauffbf3c202019-07-17 14:57:14 -06001979 const auto image_sample_version_it = validated.image_samplers.find(&pipeline);
1980 const VersionedBindings *image_sample_version = nullptr;
1981 if (image_sample_version_it != validated.image_samplers.cend()) {
1982 image_sample_version = &(image_sample_version_it->second);
1983 }
1984 const auto &dynamic_buffers = validated.dynamic_buffers;
1985 const auto &non_dynamic_buffers = validated.non_dynamic_buffers;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001986 const auto &stats = layout_->GetBindingTypeStats();
John Zulauf48a6a702017-12-22 17:14:54 -07001987 for (const auto &binding_req_pair : in_req) {
1988 auto binding = binding_req_pair.first;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001989 VkDescriptorSetLayoutBinding const *layout_binding = layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
John Zulauf48a6a702017-12-22 17:14:54 -07001990 if (!layout_binding) {
1991 continue;
1992 }
1993 // Caching criteria differs per type.
1994 // If image_layout have changed , the image descriptors need to be validated against them.
sfricke-samsung60f29ec2021-03-10 20:37:25 -08001995 if (IsBufferDescriptor(layout_binding->descriptorType)) {
1996 if (IsDynamicDescriptor(layout_binding->descriptorType)) {
1997 FilterOneBindingReq(binding_req_pair, out_req, dynamic_buffers, stats.dynamic_buffer_count);
1998 } else {
1999 FilterOneBindingReq(binding_req_pair, out_req, non_dynamic_buffers, stats.non_dynamic_buffer_count);
2000 }
John Zulauf48a6a702017-12-22 17:14:54 -07002001 } else {
2002 // This is rather crude, as the changed layouts may not impact the bound descriptors,
2003 // but the simple "versioning" is a simple "dirt" test.
John Zulauffbf3c202019-07-17 14:57:14 -06002004 bool stale = true;
2005 if (image_sample_version) {
2006 const auto version_it = image_sample_version->find(binding);
2007 if (version_it != image_sample_version->cend() && (version_it->second == cb_state.image_layout_change_count)) {
2008 stale = false;
2009 }
2010 }
2011 if (stale) {
John Zulauf48a6a702017-12-22 17:14:54 -07002012 out_req->emplace(binding_req_pair);
2013 }
2014 }
2015 }
2016}
Tobin Ehlis9252c2b2016-07-21 14:40:22 -06002017
John Zulauffbf3c202019-07-17 14:57:14 -06002018void cvdescriptorset::DescriptorSet::UpdateValidationCache(const CMD_BUFFER_STATE &cb_state, const PIPELINE_STATE &pipeline,
2019 const BindingReqMap &updated_bindings) {
2020 // For const cleanliness we have to find in the maps...
2021 auto &validated = cached_validation_[&cb_state];
2022
2023 auto &image_sample_version = validated.image_samplers[&pipeline];
2024 auto &dynamic_buffers = validated.dynamic_buffers;
2025 auto &non_dynamic_buffers = validated.non_dynamic_buffers;
2026 for (const auto &binding_req_pair : updated_bindings) {
2027 auto binding = binding_req_pair.first;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002028 VkDescriptorSetLayoutBinding const *layout_binding = layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
John Zulauffbf3c202019-07-17 14:57:14 -06002029 if (!layout_binding) {
2030 continue;
2031 }
2032 // Caching criteria differs per type.
sfricke-samsung60f29ec2021-03-10 20:37:25 -08002033 if (IsBufferDescriptor(layout_binding->descriptorType)) {
2034 if (IsDynamicDescriptor(layout_binding->descriptorType)) {
2035 dynamic_buffers.emplace(binding);
2036 } else {
2037 non_dynamic_buffers.emplace(binding);
2038 }
John Zulauffbf3c202019-07-17 14:57:14 -06002039 } else {
2040 // Save the layout change version...
2041 image_sample_version[binding] = cb_state.image_layout_change_count;
2042 }
2043 }
2044}
2045
John Zulaufd2c3dae2019-12-12 11:02:17 -07002046cvdescriptorset::SamplerDescriptor::SamplerDescriptor(const ValidationStateTracker *dev_data, const VkSampler *immut)
Jeremy Gebben059ab502021-04-26 11:25:02 -06002047 : Descriptor(PlainSampler), immutable_(false) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002048 if (immut) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002049 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(*immut);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002050 immutable_ = true;
2051 updated = true;
2052 }
2053}
Tobin Ehlise2f80292016-06-02 10:08:53 -06002054// Validate given sampler. Currently this only checks to make sure it exists in the samplerMap
John Zulaufc93c4252019-06-25 09:19:49 -06002055bool CoreChecks::ValidateSampler(const VkSampler sampler) const { return (GetSamplerState(sampler) != nullptr); }
Tobin Ehlis56a30942016-05-19 08:00:00 -06002056
John Zulaufc93c4252019-06-25 09:19:49 -06002057bool CoreChecks::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type,
John Zulaufbd9b3412019-08-22 17:16:11 -06002058 const char *func_name, std::string *error_code, std::string *error_msg) const {
John Zulaufc93c4252019-06-25 09:19:49 -06002059 auto iv_state = GetImageViewState(image_view);
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002060 assert(iv_state);
2061
Tobin Ehlis81280962016-07-20 14:04:20 -06002062 // 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 -06002063 // Validate that imageLayout is compatible with aspect_mask and image format
2064 // and validate that image usage bits are correct for given usage
Jeremy Gebbenb4d17012021-07-08 13:18:15 -06002065 VkImageAspectFlags aspect_mask = iv_state->normalized_subresource_range.aspectMask;
Tobin Ehlis8b26a382016-09-14 08:02:49 -06002066 VkImage image = iv_state->create_info.image;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002067 VkFormat format = VK_FORMAT_MAX_ENUM;
2068 VkImageUsageFlags usage = 0;
John Zulaufc93c4252019-06-25 09:19:49 -06002069 auto image_node = GetImageState(image);
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002070 assert(image_node);
Chris Forbes67757ff2017-07-21 13:59:01 -07002071
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002072 format = image_node->createInfo.format;
2073 usage = image_node->createInfo.usage;
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07002074 const auto stencil_usage_info = LvlFindInChain<VkImageStencilUsageCreateInfo>(image_node->createInfo.pNext);
Ricardo Garcia3f5984c2020-04-09 10:56:34 +02002075 if (stencil_usage_info) {
2076 usage |= stencil_usage_info->stencilUsage;
2077 }
Mark Lobodzinski03d00062020-06-15 14:35:45 -06002078
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002079 // Validate that memory is bound to image
sfricke-samsung52dbd082021-09-23 11:17:58 -07002080 if (ValidateMemoryIsBoundToImage(image_node, func_name, kVUID_Core_Bound_Resource_FreedMemoryAccess)) {
2081 *error_code = kVUID_Core_Bound_Resource_FreedMemoryAccess;
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002082 *error_msg = "No memory bound to image.";
Tobin Ehlis1809f912016-05-25 09:24:36 -06002083 return false;
2084 }
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002085
2086 // KHR_maintenance1 allows rendering into 2D or 2DArray views which slice a 3D image,
2087 // but not binding them to descriptor sets.
Jeremy Gebben11a68a32021-07-29 11:59:22 -06002088 if (iv_state->IsDepthSliced()) {
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06002089 *error_code = "VUID-VkDescriptorImageInfo-imageView-00343";
2090 *error_msg = "ImageView must not be a 2D or 2DArray view of a 3D image";
2091 return false;
2092 }
2093
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002094 // TODO : The various image aspect and format checks here are based on general spec language in 11.5 Image Views section under
2095 // vkCreateImageView(). What's the best way to create unique id for these cases?
sfricke-samsung52dbd082021-09-23 11:17:58 -07002096 *error_code = kVUID_Core_DrawState_InvalidImageView;
Dave Houlton1d2022c2017-03-29 11:43:58 -06002097 bool ds = FormatIsDepthOrStencil(format);
Tobin Ehlis1809f912016-05-25 09:24:36 -06002098 switch (image_layout) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002099 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
2100 // Only Color bit must be set
2101 if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
Tobin Ehlis1809f912016-05-25 09:24:36 -06002102 std::stringstream error_str;
Dave Houltona9df0ce2018-02-07 10:51:23 -07002103 error_str
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002104 << "ImageView (" << report_data->FormatHandle(image_view)
Dave Houltona9df0ce2018-02-07 10:51:23 -07002105 << ") 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 -06002106 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -06002107 return false;
2108 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002109 // format must NOT be DS
2110 if (ds) {
2111 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002112 error_str << "ImageView (" << report_data->FormatHandle(image_view)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002113 << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but the image format is "
2114 << string_VkFormat(format) << " which is not a color format.";
2115 *error_msg = error_str.str();
2116 return false;
2117 }
2118 break;
2119 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
2120 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2121 // Depth or stencil bit must be set, but both must NOT be set
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06002122 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
2123 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
2124 // both must NOT be set
2125 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002126 error_str << "ImageView (" << report_data->FormatHandle(image_view)
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002127 << ") has both STENCIL and DEPTH aspects set";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002128 *error_msg = error_str.str();
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06002129 return false;
2130 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002131 } else if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
2132 // Neither were set
2133 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002134 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002135 << string_VkImageLayout(image_layout) << " but does not have STENCIL or DEPTH aspects set";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002136 *error_msg = error_str.str();
2137 return false;
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06002138 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002139 // format must be DS
2140 if (!ds) {
2141 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002142 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002143 << string_VkImageLayout(image_layout) << " but the image format is " << string_VkFormat(format)
2144 << " which is not a depth/stencil format.";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002145 *error_msg = error_str.str();
2146 return false;
2147 }
2148 break;
2149 default:
2150 // For other layouts if the source is depth/stencil image, both aspect bits must not be set
2151 if (ds) {
2152 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
2153 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
2154 // both must NOT be set
2155 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002156 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002157 << string_VkImageLayout(image_layout) << " and is using depth/stencil image of format "
2158 << string_VkFormat(format)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002159 << " but it has both STENCIL and DEPTH aspects set, which is illegal. When using a depth/stencil "
2160 "image in a descriptor set, please only set either VK_IMAGE_ASPECT_DEPTH_BIT or "
2161 "VK_IMAGE_ASPECT_STENCIL_BIT depending on whether it will be used for depth reads or stencil "
2162 "reads respectively.";
Mark Lobodzinski4d05d7a2019-06-25 09:12:06 -06002163 *error_code = "VUID-VkDescriptorImageInfo-imageView-01976";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002164 *error_msg = error_str.str();
2165 return false;
2166 }
2167 }
2168 }
2169 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002170 }
2171 // Now validate that usage flags are correctly set for given type of update
Tobin Ehlisfb4cf712016-10-10 14:02:48 -06002172 // 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 -06002173 // TODO : The various image usage bit requirements are in general spec language for VkImageUsageFlags bit block in 11.3 Images
2174 // under vkCreateImage()
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002175 const char *error_usage_bit = nullptr;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002176 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002177 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
sfricke-samsung088f1242020-06-06 02:15:35 -07002178 if (iv_state->samplerConversion != VK_NULL_HANDLE) {
2179 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-01946";
2180 std::stringstream error_str;
2181 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ")"
2182 << "used as a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE can't be created with VkSamplerYcbcrConversion";
2183 *error_msg = error_str.str();
2184 return false;
2185 }
2186 // drop through
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002187 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
2188 if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
2189 error_usage_bit = "VK_IMAGE_USAGE_SAMPLED_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08002190 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00337";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002191 }
2192 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002193 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002194 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
2195 if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
2196 error_usage_bit = "VK_IMAGE_USAGE_STORAGE_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08002197 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00339";
sfricke-samsung45996a42021-09-16 13:45:27 -07002198 } else if ((VK_IMAGE_LAYOUT_GENERAL != image_layout) &&
2199 (!IsExtEnabled(device_extensions.vk_khr_shared_presentable_image) ||
2200 (VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR != image_layout))) {
sfricke-samsungf1058982020-09-10 22:36:49 -07002201 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04152";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002202 std::stringstream error_str;
sfricke-samsungada55a12020-08-15 03:39:41 -07002203 error_str << "Descriptor update with descriptorType VK_DESCRIPTOR_TYPE_STORAGE_IMAGE"
2204 << " is being updated with invalid imageLayout " << string_VkImageLayout(image_layout) << " for image "
2205 << report_data->FormatHandle(image) << " in imageView " << report_data->FormatHandle(image_view)
2206 << ". Allowed layouts are: VK_IMAGE_LAYOUT_GENERAL";
sfricke-samsung45996a42021-09-16 13:45:27 -07002207 if (IsExtEnabled(device_extensions.vk_khr_shared_presentable_image)) {
sfricke-samsungada55a12020-08-15 03:39:41 -07002208 error_str << " or VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR";
Tobin Ehlisbb03e5f2017-05-11 08:52:51 -06002209 }
sfricke-samsungada55a12020-08-15 03:39:41 -07002210 *error_msg = error_str.str();
2211 return false;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002212 }
2213 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002214 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002215 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
2216 if (!(usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
2217 error_usage_bit = "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08002218 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00338";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002219 }
2220 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002221 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002222 default:
2223 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002224 }
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002225 if (error_usage_bit) {
Tobin Ehlis1809f912016-05-25 09:24:36 -06002226 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002227 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") with usage mask " << std::hex << std::showbase
2228 << usage << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have "
2229 << error_usage_bit << " set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002230 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -06002231 return false;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002232 }
John Zulauff4c07882019-01-24 14:03:36 -07002233
sfricke-samsungada55a12020-08-15 03:39:41 -07002234 // All the following types share the same image layouts
2235 // checkf or Storage Images above
2236 if ((type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) || (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
2237 (type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
John Zulauff4c07882019-01-24 14:03:36 -07002238 // Test that the layout is compatible with the descriptorType for the two sampled image types
2239 const static std::array<VkImageLayout, 3> valid_layouts = {
Jeremy Hayesd0549f62019-06-05 10:15:36 -06002240 {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 -07002241
2242 struct ExtensionLayout {
2243 VkImageLayout layout;
Tony-LunarG2ec96bb2019-11-26 13:43:02 -07002244 ExtEnabled DeviceExtensions::*extension;
John Zulauff4c07882019-01-24 14:03:36 -07002245 };
Ricardo Garcia602c2022021-07-30 10:42:17 +02002246 const static std::array<ExtensionLayout, 7> extended_layouts{{
Jeremy Gebben579aaca2021-02-15 13:36:18 -07002247 // Note double brace req'd for aggregate initialization
2248 {VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR, &DeviceExtensions::vk_khr_shared_presentable_image},
2249 {VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, &DeviceExtensions::vk_khr_maintenance2},
2250 {VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, &DeviceExtensions::vk_khr_maintenance2},
Mike Schuchardtc57de4a2021-07-20 17:26:32 -07002251 {VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, &DeviceExtensions::vk_khr_synchronization2},
2252 {VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, &DeviceExtensions::vk_khr_synchronization2},
Ricardo Garcia602c2022021-07-30 10:42:17 +02002253 {VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, &DeviceExtensions::vk_khr_separate_depth_stencil_layouts},
2254 {VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, &DeviceExtensions::vk_khr_separate_depth_stencil_layouts},
Jeremy Gebben579aaca2021-02-15 13:36:18 -07002255 }};
John Zulaufc93c4252019-06-25 09:19:49 -06002256 auto is_layout = [image_layout, this](const ExtensionLayout &ext_layout) {
sfricke-samsung45996a42021-09-16 13:45:27 -07002257 return IsExtEnabled(device_extensions.*(ext_layout.extension)) && (ext_layout.layout == image_layout);
John Zulauff4c07882019-01-24 14:03:36 -07002258 };
2259
2260 bool valid_layout = (std::find(valid_layouts.cbegin(), valid_layouts.cend(), image_layout) != valid_layouts.cend()) ||
2261 std::any_of(extended_layouts.cbegin(), extended_layouts.cend(), is_layout);
2262
2263 if (!valid_layout) {
sfricke-samsungf1058982020-09-10 22:36:49 -07002264 // The following works as currently all 3 descriptor types share the same set of valid layouts
sfricke-samsungada55a12020-08-15 03:39:41 -07002265 switch (type) {
2266 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
Shannon McPherson2c793ba2020-08-28 12:13:24 -06002267 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04149";
sfricke-samsungada55a12020-08-15 03:39:41 -07002268 break;
2269 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
Shannon McPherson2c793ba2020-08-28 12:13:24 -06002270 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04150";
sfricke-samsungada55a12020-08-15 03:39:41 -07002271 break;
2272 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
sfricke-samsungf1058982020-09-10 22:36:49 -07002273 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04151";
sfricke-samsungada55a12020-08-15 03:39:41 -07002274 break;
2275 default:
2276 break;
2277 }
John Zulauff4c07882019-01-24 14:03:36 -07002278 std::stringstream error_str;
2279 error_str << "Descriptor update with descriptorType " << string_VkDescriptorType(type)
Mark Lobodzinski74eddba2019-06-21 14:16:33 -06002280 << " is being updated with invalid imageLayout " << string_VkImageLayout(image_layout) << " for image "
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002281 << report_data->FormatHandle(image) << " in imageView " << report_data->FormatHandle(image_view)
John Zulauff4c07882019-01-24 14:03:36 -07002282 << ". Allowed layouts are: VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "
2283 << "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL";
2284 for (auto &ext_layout : extended_layouts) {
sfricke-samsung45996a42021-09-16 13:45:27 -07002285 if (IsExtEnabled(device_extensions.*(ext_layout.extension))) {
John Zulauff4c07882019-01-24 14:03:36 -07002286 error_str << ", " << string_VkImageLayout(ext_layout.layout);
2287 }
2288 }
2289 *error_msg = error_str.str();
2290 return false;
2291 }
2292 }
2293
sfricke-samsungbd0e8052020-06-06 01:36:39 -07002294 if ((type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) || (type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
2295 const VkComponentMapping components = iv_state->create_info.components;
2296 if (IsIdentitySwizzle(components) == false) {
2297 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00336";
2298 std::stringstream error_str;
2299 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has a non-identiy swizzle component, "
2300 << " r swizzle = " << string_VkComponentSwizzle(components.r) << ","
2301 << " g swizzle = " << string_VkComponentSwizzle(components.g) << ","
2302 << " b swizzle = " << string_VkComponentSwizzle(components.b) << ","
2303 << " a swizzle = " << string_VkComponentSwizzle(components.a) << ".";
2304 *error_msg = error_str.str();
2305 return false;
2306 }
2307 }
2308
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002309 return true;
2310}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002311
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002312// Helper template to change shared pointer members of a Descriptor, while
2313// correctly managing links to the parent DescriptorSet.
2314// src and dst are shared pointers.
2315template <typename T>
2316static void ReplaceStatePtr(DescriptorSet *set_state, T &dst, const T &src) {
2317 if (dst) {
2318 dst->RemoveParent(set_state);
2319 }
2320 dst = src;
2321 if (dst) {
2322 dst->AddParent(set_state);
2323 }
2324}
2325
2326void cvdescriptorset::SamplerDescriptor::WriteUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2327 const VkWriteDescriptorSet *update, const uint32_t index) {
Chris Forbesfea2c542018-04-13 09:34:15 -07002328 if (!immutable_) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002329 ReplaceStatePtr(set_state, sampler_state_ , dev_data->GetConstCastShared<SAMPLER_STATE>(update->pImageInfo[index].sampler));
Chris Forbesfea2c542018-04-13 09:34:15 -07002330 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002331 updated = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002332}
2333
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002334void cvdescriptorset::SamplerDescriptor::CopyUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2335 const Descriptor *src) {
Tony-LunarG80358322021-04-16 07:58:13 -06002336 updated = true;
2337 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2338 if (src->descriptor_class == Mutable) {
2339 this->descriptor_class = Mutable;
2340 return;
2341 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002342 auto *sampler_src = static_cast<const SamplerDescriptor *>(src);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002343 if (!immutable_) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002344 ReplaceStatePtr(set_state, sampler_state_, sampler_src->sampler_state_);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002345 }
2346}
2347
John Zulaufd2c3dae2019-12-12 11:02:17 -07002348cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(const ValidationStateTracker *dev_data, const VkSampler *immut)
Jeremy Gebben059ab502021-04-26 11:25:02 -06002349 : ImageDescriptor(ImageSampler), immutable_(false) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002350 if (immut) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002351 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(*immut);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002352 immutable_ = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002353 }
2354}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002355
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002356void cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
John Zulaufd2c3dae2019-12-12 11:02:17 -07002357 const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002358 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002359 const auto &image_info = update->pImageInfo[index];
Chris Forbesfea2c542018-04-13 09:34:15 -07002360 if (!immutable_) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002361 ReplaceStatePtr(set_state, sampler_state_, dev_data->GetConstCastShared<SAMPLER_STATE>(image_info.sampler));
Chris Forbesfea2c542018-04-13 09:34:15 -07002362 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002363 image_layout_ = image_info.imageLayout;
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002364 ReplaceStatePtr(set_state, image_view_state_, dev_data->GetConstCastShared<IMAGE_VIEW_STATE>(image_info.imageView));
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002365}
2366
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002367void cvdescriptorset::ImageSamplerDescriptor::CopyUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2368 const Descriptor *src) {
Tony-LunarG80358322021-04-16 07:58:13 -06002369 updated = true;
2370 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2371 if (src->descriptor_class == Mutable) {
2372 this->descriptor_class = Mutable;
2373 return;
2374 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002375 auto *image_src = static_cast<const ImageSamplerDescriptor *>(src);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002376 if (!immutable_) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002377 ReplaceStatePtr(set_state, sampler_state_, image_src->sampler_state_);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002378 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002379 ImageDescriptor::CopyUpdate(set_state, dev_data, src);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002380}
2381
Jeremy Gebben059ab502021-04-26 11:25:02 -06002382cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type)
2383 : Descriptor(Image), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {}
2384
2385cvdescriptorset::ImageDescriptor::ImageDescriptor(DescriptorClass class_)
2386 : Descriptor(class_), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {}
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002387
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002388void cvdescriptorset::ImageDescriptor::WriteUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2389 const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002390 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002391 const auto &image_info = update->pImageInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06002392 image_layout_ = image_info.imageLayout;
Karl Schultz76d16a42020-11-11 05:05:33 -07002393 image_view_state_ = dev_data->GetConstCastShared<IMAGE_VIEW_STATE>(image_info.imageView);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002394}
2395
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002396void cvdescriptorset::ImageDescriptor::CopyUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2397 const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002398 updated = true;
Tony-LunarG80358322021-04-16 07:58:13 -06002399 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2400 if (src->descriptor_class == Mutable) {
2401 this->descriptor_class = Mutable;
2402 return;
2403 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002404 auto *image_src = static_cast<const ImageDescriptor *>(src);
Tony-LunarG80358322021-04-16 07:58:13 -06002405
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002406 image_layout_ = image_src->image_layout_;
2407 ReplaceStatePtr(set_state, image_view_state_, image_src->image_view_state_);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002408}
2409
John Zulauffbf3c202019-07-17 14:57:14 -06002410void cvdescriptorset::ImageDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Tobin Ehlis81e46372016-08-17 13:33:44 -06002411 // Add binding for image
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002412 auto iv_state = GetImageViewState();
Tobin Ehlis8b26a382016-09-14 08:02:49 -06002413 if (iv_state) {
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002414 dev_data->CallSetImageViewInitialLayoutCallback(cb_node, *iv_state, image_layout_);
Jeff Bolz148d94e2018-12-13 21:25:56 -06002415 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002416}
2417
Jeremy Gebben059ab502021-04-26 11:25:02 -06002418cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type)
2419 : Descriptor(GeneralBuffer), offset_(0), range_(0) {}
2420
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002421void cvdescriptorset::BufferDescriptor::WriteUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2422 const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002423 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002424 const auto &buffer_info = update->pBufferInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06002425 offset_ = buffer_info.offset;
2426 range_ = buffer_info.range;
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002427 ReplaceStatePtr(set_state, buffer_state_, dev_data->GetConstCastShared<BUFFER_STATE>(buffer_info.buffer));
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002428}
2429
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002430void cvdescriptorset::BufferDescriptor::CopyUpdate(DescriptorSet* set_state, const ValidationStateTracker *dev_data,
2431 const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002432 updated = true;
Tony-LunarG80358322021-04-16 07:58:13 -06002433 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2434 if (src->descriptor_class == Mutable) {
2435 this->descriptor_class = Mutable;
2436 return;
2437 }
Karl Schultz76d16a42020-11-11 05:05:33 -07002438 const auto buff_desc = static_cast<const BufferDescriptor *>(src);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002439 offset_ = buff_desc->offset_;
2440 range_ = buff_desc->range_;
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002441 ReplaceStatePtr(set_state, buffer_state_, buff_desc->buffer_state_);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002442}
2443
Jeremy Gebben059ab502021-04-26 11:25:02 -06002444cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type) : Descriptor(TexelBuffer) {}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002445
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002446void cvdescriptorset::TexelDescriptor::WriteUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2447 const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002448 updated = true;
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002449 ReplaceStatePtr(set_state, buffer_view_state_,
2450 dev_data->GetConstCastShared<BUFFER_VIEW_STATE>(update->pTexelBufferView[index]));
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002451}
2452
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002453void cvdescriptorset::TexelDescriptor::CopyUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2454 const Descriptor *src) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002455 updated = true;
Tony-LunarG80358322021-04-16 07:58:13 -06002456 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2457 if (src->descriptor_class == Mutable) {
2458 this->descriptor_class = Mutable;
2459 return;
2460 }
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002461 ReplaceStatePtr(set_state, buffer_view_state_, static_cast<const TexelDescriptor *>(src)->buffer_view_state_);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002462}
2463
Jeff Bolz95176d02020-04-01 00:36:16 -05002464cvdescriptorset::AccelerationStructureDescriptor::AccelerationStructureDescriptor(const VkDescriptorType type)
Jeremy Gebben059ab502021-04-26 11:25:02 -06002465 : Descriptor(AccelerationStructure), acc_(VK_NULL_HANDLE), acc_nv_(VK_NULL_HANDLE) {
sourav parmarcd5fb182020-07-17 12:58:44 -07002466 is_khr_ = false;
Jeff Bolz95176d02020-04-01 00:36:16 -05002467}
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002468void cvdescriptorset::AccelerationStructureDescriptor::WriteUpdate(DescriptorSet *set_state,
2469 const ValidationStateTracker *dev_data,
Jeff Bolz95176d02020-04-01 00:36:16 -05002470 const VkWriteDescriptorSet *update, const uint32_t index) {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07002471 const auto *acc_info = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureKHR>(update->pNext);
2472 const auto *acc_info_nv = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureNV>(update->pNext);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002473 assert(acc_info || acc_info_nv);
2474 is_khr_ = (acc_info != NULL);
Jeff Bolz95176d02020-04-01 00:36:16 -05002475 updated = true;
sourav parmarcd5fb182020-07-17 12:58:44 -07002476 if (is_khr_) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002477 acc_ = acc_info->pAccelerationStructures[index];
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002478 ReplaceStatePtr(set_state, acc_state_, dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE_KHR>(acc_));
sourav parmarcd5fb182020-07-17 12:58:44 -07002479 } else {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002480 acc_nv_ = acc_info_nv->pAccelerationStructures[index];
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002481 ReplaceStatePtr(set_state, acc_state_nv_, dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE>(acc_nv_));
sourav parmarcd5fb182020-07-17 12:58:44 -07002482 }
Jeff Bolz95176d02020-04-01 00:36:16 -05002483}
2484
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002485void cvdescriptorset::AccelerationStructureDescriptor::CopyUpdate(DescriptorSet *set_state,
2486 const ValidationStateTracker *dev_data, const Descriptor *src) {
Jeff Bolz95176d02020-04-01 00:36:16 -05002487 auto acc_desc = static_cast<const AccelerationStructureDescriptor *>(src);
2488 updated = true;
Tony-LunarG80358322021-04-16 07:58:13 -06002489 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2490 if (src->descriptor_class == Mutable) {
2491 this->descriptor_class = Mutable;
2492 return;
2493 }
sourav parmarcd5fb182020-07-17 12:58:44 -07002494 if (is_khr_) {
2495 acc_ = acc_desc->acc_;
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002496 ReplaceStatePtr(set_state, acc_state_, dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE_KHR>(acc_));
sourav parmarcd5fb182020-07-17 12:58:44 -07002497 } else {
2498 acc_nv_ = acc_desc->acc_nv_;
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002499 ReplaceStatePtr(set_state, acc_state_nv_, dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE>(acc_nv_));
sourav parmarcd5fb182020-07-17 12:58:44 -07002500 }
Jeff Bolz95176d02020-04-01 00:36:16 -05002501}
2502
Jeremy Gebben059ab502021-04-26 11:25:02 -06002503cvdescriptorset::MutableDescriptor::MutableDescriptor() : Descriptor(Mutable) { active_descriptor_class_ = NoDescriptorClass; }
Tony-LunarGf563b362021-03-18 16:13:18 -06002504
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002505void cvdescriptorset::MutableDescriptor::WriteUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
Tony-LunarGf563b362021-03-18 16:13:18 -06002506 const VkWriteDescriptorSet *update, const uint32_t index) {
2507 updated = true;
2508}
2509
Jeremy Gebben5570abe2021-05-16 18:35:13 -06002510void cvdescriptorset::MutableDescriptor::CopyUpdate(DescriptorSet *set_state, const ValidationStateTracker *dev_data,
2511 const Descriptor *src) {
Tony-LunarGf563b362021-03-18 16:13:18 -06002512 updated = true;
2513}
2514
Tobin Ehlis300888c2016-05-18 13:43:26 -06002515// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
2516// sets, and then calls their respective Validate[Write|Copy]Update functions.
2517// If the update hits an issue for which the callback returns "true", meaning that the call down the chain should
2518// be skipped, then true is returned.
2519// If there is no issue with the update, then false is returned.
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002520bool CoreChecks::ValidateUpdateDescriptorSets(uint32_t write_count, const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05002521 const VkCopyDescriptorSet *p_cds, const char *func_name) const {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002522 bool skip = false;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002523 // Validate Write updates
Tobin Ehlis56a30942016-05-19 08:00:00 -06002524 for (uint32_t i = 0; i < write_count; i++) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002525 auto dest_set = p_wds[i].dstSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002526 auto set_node = GetSetNode(dest_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002527 if (!set_node) {
sfricke-samsungbda4a852021-03-06 20:58:01 -08002528 skip |= LogError(dest_set, kVUID_Core_DrawState_InvalidDescriptorSet,
2529 "Cannot call %s on %s that has not been allocated in pDescriptorWrites[%u].", func_name,
2530 report_data->FormatHandle(dest_set).c_str(), i);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002531 } else {
Dave Houltond8ed0212018-05-16 17:18:24 -06002532 std::string error_code;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002533 std::string error_str;
ziga-lunarg6c46b242021-09-13 18:33:37 +02002534 if (!ValidateWriteUpdate(set_node, &p_wds[i], func_name, &error_code, &error_str, false)) {
sfricke-samsungbda4a852021-03-06 20:58:01 -08002535 skip |=
2536 LogError(dest_set, error_code, "%s pDescriptorWrites[%u] failed write update validation for %s with error: %s.",
2537 func_name, i, report_data->FormatHandle(dest_set).c_str(), error_str.c_str());
Tobin Ehlis300888c2016-05-18 13:43:26 -06002538 }
2539 }
sourav parmara24fb7b2020-05-26 10:50:04 -07002540 if (p_wds[i].pNext) {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07002541 const auto *pnext_struct = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureKHR>(p_wds[i].pNext);
Mark Lobodzinski17dc4602020-05-29 07:48:40 -06002542 if (pnext_struct) {
2543 for (uint32_t j = 0; j < pnext_struct->accelerationStructureCount; ++j) {
sourav parmarcd5fb182020-07-17 12:58:44 -07002544 const ACCELERATION_STRUCTURE_STATE_KHR *as_state =
2545 GetAccelerationStructureStateKHR(pnext_struct->pAccelerationStructures[j]);
2546 if (as_state && (as_state->create_infoKHR.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR &&
sourav parmar766e2a72020-12-03 16:17:11 -08002547 (as_state->create_infoKHR.type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR &&
2548 as_state->create_infoKHR.type != VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR))) {
sourav parmara24fb7b2020-05-26 10:50:04 -07002549 skip |=
sourav parmarcd5fb182020-07-17 12:58:44 -07002550 LogError(dest_set, "VUID-VkWriteDescriptorSetAccelerationStructureKHR-pAccelerationStructures-03579",
sfricke-samsungbda4a852021-03-06 20:58:01 -08002551 "%s: For pDescriptorWrites[%u] acceleration structure in pAccelerationStructures[%u] must "
2552 "have been created with "
sourav parmarbcee7512020-12-28 14:34:49 -08002553 "VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR or VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR.",
sfricke-samsungbda4a852021-03-06 20:58:01 -08002554 func_name, i, j);
sourav parmara24fb7b2020-05-26 10:50:04 -07002555 }
2556 }
2557 }
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07002558 const auto *pnext_struct_nv = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureNV>(p_wds[i].pNext);
sourav parmarcd5fb182020-07-17 12:58:44 -07002559 if (pnext_struct_nv) {
2560 for (uint32_t j = 0; j < pnext_struct_nv->accelerationStructureCount; ++j) {
2561 const ACCELERATION_STRUCTURE_STATE *as_state =
2562 GetAccelerationStructureStateNV(pnext_struct_nv->pAccelerationStructures[j]);
2563 if (as_state && (as_state->create_infoNV.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV &&
2564 as_state->create_infoNV.info.type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV)) {
2565 skip |= LogError(dest_set, "VUID-VkWriteDescriptorSetAccelerationStructureNV-pAccelerationStructures-03748",
sfricke-samsungbda4a852021-03-06 20:58:01 -08002566 "%s: For pDescriptorWrites[%u] acceleration structure in pAccelerationStructures[%u] must "
2567 "have been created with"
sourav parmarcd5fb182020-07-17 12:58:44 -07002568 " VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV.",
sfricke-samsungbda4a852021-03-06 20:58:01 -08002569 func_name, i, j);
sourav parmarcd5fb182020-07-17 12:58:44 -07002570 }
2571 }
2572 }
sourav parmara24fb7b2020-05-26 10:50:04 -07002573 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002574 }
2575 // Now validate copy updates
Tobin Ehlis56a30942016-05-19 08:00:00 -06002576 for (uint32_t i = 0; i < copy_count; ++i) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002577 auto dst_set = p_cds[i].dstSet;
2578 auto src_set = p_cds[i].srcSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002579 auto src_node = GetSetNode(src_set);
2580 auto dst_node = GetSetNode(dst_set);
Tobin Ehlisa1712752017-01-04 09:41:47 -07002581 // Object_tracker verifies that src & dest descriptor set are valid
2582 assert(src_node);
2583 assert(dst_node);
Dave Houltond8ed0212018-05-16 17:18:24 -06002584 std::string error_code;
Tobin Ehlisa1712752017-01-04 09:41:47 -07002585 std::string error_str;
John Zulaufc93c4252019-06-25 09:19:49 -06002586 if (!ValidateCopyUpdate(&p_cds[i], dst_node, src_node, func_name, &error_code, &error_str)) {
Mark Lobodzinski9d38ea22020-03-16 18:22:16 -06002587 LogObjectList objlist(dst_set);
2588 objlist.add(src_set);
sfricke-samsungbda4a852021-03-06 20:58:01 -08002589 skip |= LogError(objlist, error_code, "%s pDescriptorCopies[%u] failed copy update from %s to %s with error: %s.",
2590 func_name, i, report_data->FormatHandle(src_set).c_str(), report_data->FormatHandle(dst_set).c_str(),
2591 error_str.c_str());
Tobin Ehlis300888c2016-05-18 13:43:26 -06002592 }
2593 }
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002594 return skip;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002595}
2596// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
2597// sets, and then calls their respective Perform[Write|Copy]Update functions.
2598// Prerequisite : ValidateUpdateDescriptorSets() should be called and return "false" prior to calling PerformUpdateDescriptorSets()
2599// with the same set of updates.
2600// This is split from the validate code to allow validation prior to calling down the chain, and then update after
2601// calling down the chain.
John Zulaufe3b35f32019-06-25 14:21:21 -06002602void cvdescriptorset::PerformUpdateDescriptorSets(ValidationStateTracker *dev_data, uint32_t write_count,
2603 const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
2604 const VkCopyDescriptorSet *p_cds) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002605 // Write updates first
2606 uint32_t i = 0;
2607 for (i = 0; i < write_count; ++i) {
2608 auto dest_set = p_wds[i].dstSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002609 auto set_node = dev_data->GetSetNode(dest_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002610 if (set_node) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05002611 set_node->PerformWriteUpdate(dev_data, &p_wds[i]);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002612 }
2613 }
2614 // Now copy updates
2615 for (i = 0; i < copy_count; ++i) {
2616 auto dst_set = p_cds[i].dstSet;
2617 auto src_set = p_cds[i].srcSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002618 auto src_node = dev_data->GetSetNode(src_set);
2619 auto dst_node = dev_data->GetSetNode(dst_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002620 if (src_node && dst_node) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05002621 dst_node->PerformCopyUpdate(dev_data, &p_cds[i], src_node);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002622 }
2623 }
2624}
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002625
John Zulaufe3b35f32019-06-25 14:21:21 -06002626cvdescriptorset::DecodedTemplateUpdate::DecodedTemplateUpdate(const ValidationStateTracker *device_data,
2627 VkDescriptorSet descriptorSet, const TEMPLATE_STATE *template_state,
2628 const void *pData, VkDescriptorSetLayout push_layout) {
John Zulaufb845eb22018-10-12 11:41:06 -06002629 auto const &create_info = template_state->create_info;
2630 inline_infos.resize(create_info.descriptorUpdateEntryCount); // Make sure we have one if we need it
sourav parmar480d2772021-01-24 22:24:54 -08002631 inline_infos_khr.resize(create_info.descriptorUpdateEntryCount);
2632 inline_infos_nv.resize(create_info.descriptorUpdateEntryCount);
John Zulaufb845eb22018-10-12 11:41:06 -06002633 desc_writes.reserve(create_info.descriptorUpdateEntryCount); // emplaced, so reserved without initialization
John Zulauf1d27e0a2018-11-05 10:12:48 -07002634 VkDescriptorSetLayout effective_dsl = create_info.templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
2635 ? create_info.descriptorSetLayout
2636 : push_layout;
Jeff Bolz6ae39612019-10-11 20:57:36 -05002637 auto layout_obj = device_data->GetDescriptorSetLayoutShared(effective_dsl);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002638
2639 // Create a WriteDescriptorSet struct for each template update entry
2640 for (uint32_t i = 0; i < create_info.descriptorUpdateEntryCount; i++) {
2641 auto binding_count = layout_obj->GetDescriptorCountFromBinding(create_info.pDescriptorUpdateEntries[i].dstBinding);
2642 auto binding_being_updated = create_info.pDescriptorUpdateEntries[i].dstBinding;
2643 auto dst_array_element = create_info.pDescriptorUpdateEntries[i].dstArrayElement;
2644
John Zulaufb6d71202017-12-22 16:47:09 -07002645 desc_writes.reserve(desc_writes.size() + create_info.pDescriptorUpdateEntries[i].descriptorCount);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002646 for (uint32_t j = 0; j < create_info.pDescriptorUpdateEntries[i].descriptorCount; j++) {
2647 desc_writes.emplace_back();
2648 auto &write_entry = desc_writes.back();
2649
2650 size_t offset = create_info.pDescriptorUpdateEntries[i].offset + j * create_info.pDescriptorUpdateEntries[i].stride;
2651 char *update_entry = (char *)(pData) + offset;
2652
2653 if (dst_array_element >= binding_count) {
2654 dst_array_element = 0;
Mark Lobodzinski4aa479d2017-03-10 09:14:00 -07002655 binding_being_updated = layout_obj->GetNextValidBinding(binding_being_updated);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002656 }
2657
2658 write_entry.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2659 write_entry.pNext = NULL;
2660 write_entry.dstSet = descriptorSet;
2661 write_entry.dstBinding = binding_being_updated;
2662 write_entry.dstArrayElement = dst_array_element;
2663 write_entry.descriptorCount = 1;
2664 write_entry.descriptorType = create_info.pDescriptorUpdateEntries[i].descriptorType;
2665
2666 switch (create_info.pDescriptorUpdateEntries[i].descriptorType) {
2667 case VK_DESCRIPTOR_TYPE_SAMPLER:
2668 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2669 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2670 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2671 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2672 write_entry.pImageInfo = reinterpret_cast<VkDescriptorImageInfo *>(update_entry);
2673 break;
2674
2675 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2676 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2677 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2678 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2679 write_entry.pBufferInfo = reinterpret_cast<VkDescriptorBufferInfo *>(update_entry);
2680 break;
2681
2682 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2683 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2684 write_entry.pTexelBufferView = reinterpret_cast<VkBufferView *>(update_entry);
2685 break;
Dave Houlton142c4cb2018-10-17 15:04:41 -06002686 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: {
2687 VkWriteDescriptorSetInlineUniformBlockEXT *inline_info = &inline_infos[i];
2688 inline_info->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT;
2689 inline_info->pNext = nullptr;
2690 inline_info->dataSize = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2691 inline_info->pData = update_entry;
2692 write_entry.pNext = inline_info;
Ricardo Garciafee15732019-05-28 11:13:31 +02002693 // descriptorCount must match the dataSize member of the VkWriteDescriptorSetInlineUniformBlockEXT structure
2694 write_entry.descriptorCount = inline_info->dataSize;
Dave Houlton142c4cb2018-10-17 15:04:41 -06002695 // skip the rest of the array, they just represent bytes in the update
2696 j = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2697 break;
2698 }
sourav parmar480d2772021-01-24 22:24:54 -08002699 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: {
2700 VkWriteDescriptorSetAccelerationStructureKHR *inline_info_khr = &inline_infos_khr[i];
2701 inline_info_khr->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
2702 inline_info_khr->pNext = nullptr;
2703 inline_info_khr->accelerationStructureCount = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2704 inline_info_khr->pAccelerationStructures = reinterpret_cast<VkAccelerationStructureKHR *>(update_entry);
2705 write_entry.pNext = inline_info_khr;
2706 break;
2707 }
2708 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: {
2709 VkWriteDescriptorSetAccelerationStructureNV *inline_info_nv = &inline_infos_nv[i];
2710 inline_info_nv->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV;
2711 inline_info_nv->pNext = nullptr;
2712 inline_info_nv->accelerationStructureCount = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2713 inline_info_nv->pAccelerationStructures = reinterpret_cast<VkAccelerationStructureNV *>(update_entry);
2714 write_entry.pNext = inline_info_nv;
2715 break;
2716 }
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002717 default:
2718 assert(0);
2719 break;
2720 }
2721 dst_array_element++;
2722 }
2723 }
John Zulaufb845eb22018-10-12 11:41:06 -06002724}
John Zulaufb45fdc32018-10-12 15:14:17 -06002725// These helper functions carry out the validate and record descriptor updates peformed via update templates. They decode
2726// the templatized data and leverage the non-template UpdateDescriptor helper functions.
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002727bool CoreChecks::ValidateUpdateDescriptorSetsWithTemplateKHR(VkDescriptorSet descriptorSet, const TEMPLATE_STATE *template_state,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05002728 const void *pData) const {
John Zulaufb45fdc32018-10-12 15:14:17 -06002729 // Translate the templated update into a normal update for validation...
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002730 cvdescriptorset::DecodedTemplateUpdate decoded_update(this, descriptorSet, template_state, pData);
2731 return ValidateUpdateDescriptorSets(static_cast<uint32_t>(decoded_update.desc_writes.size()), decoded_update.desc_writes.data(),
2732 0, NULL, "vkUpdateDescriptorSetWithTemplate()");
John Zulaufb45fdc32018-10-12 15:14:17 -06002733}
John Zulaufb845eb22018-10-12 11:41:06 -06002734
John Zulauf4e7bcb52018-11-02 10:46:30 -06002735std::string cvdescriptorset::DescriptorSet::StringifySetAndLayout() const {
2736 std::string out;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002737 auto layout_handle = layout_->GetDescriptorSetLayout();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002738 if (IsPushDescriptor()) {
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002739 std::ostringstream str;
Tony-LunarG1d3ee2d2020-10-27 15:54:52 -06002740 str << "Push Descriptors defined with " << state_data_->report_data->FormatHandle(layout_handle);
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002741 out = str.str();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002742 } else {
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002743 std::ostringstream str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002744 str << state_data_->report_data->FormatHandle(GetSet()) << " allocated with "
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002745 << state_data_->report_data->FormatHandle(layout_handle);
2746 out = str.str();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002747 }
2748 return out;
2749};
2750
John Zulauf1d27e0a2018-11-05 10:12:48 -07002751// Loop through the write updates to validate for a push descriptor set, ignoring dstSet
John Zulaufc93c4252019-06-25 09:19:49 -06002752bool CoreChecks::ValidatePushDescriptorsUpdate(const DescriptorSet *push_set, uint32_t write_count,
John Zulaufbd9b3412019-08-22 17:16:11 -06002753 const VkWriteDescriptorSet *p_wds, const char *func_name) const {
John Zulaufd9435c32019-06-05 15:55:36 -06002754 assert(push_set->IsPushDescriptor());
John Zulauf1d27e0a2018-11-05 10:12:48 -07002755 bool skip = false;
2756 for (uint32_t i = 0; i < write_count; i++) {
2757 std::string error_code;
2758 std::string error_str;
ziga-lunarg6c46b242021-09-13 18:33:37 +02002759 if (!ValidateWriteUpdate(push_set, &p_wds[i], func_name, &error_code, &error_str, true)) {
sfricke-samsungbda4a852021-03-06 20:58:01 -08002760 skip |= LogError(push_set->GetDescriptorSetLayout(), error_code,
2761 "%s VkWriteDescriptorSet[%u] failed update validation: %s.", func_name, i, error_str.c_str());
John Zulauf1d27e0a2018-11-05 10:12:48 -07002762 }
2763 }
2764 return skip;
2765}
2766
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002767// For the given buffer, verify that its creation parameters are appropriate for the given type
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002768// 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 -06002769bool cvdescriptorset::ValidateBufferUsage(debug_report_data *report_data, BUFFER_STATE const *buffer_node, VkDescriptorType type,
2770 std::string *error_code, std::string *error_msg) {
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002771 // Verify that usage bits set correctly for given type
Tobin Ehlis94bc5d22016-06-02 07:46:52 -06002772 auto usage = buffer_node->createInfo.usage;
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002773 const char *error_usage_bit = nullptr;
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002774 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002775 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2776 if (!(usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002777 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00334";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002778 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT";
2779 }
2780 break;
2781 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2782 if (!(usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002783 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00335";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002784 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT";
2785 }
2786 break;
2787 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2788 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2789 if (!(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002790 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00330";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002791 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT";
2792 }
2793 break;
2794 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2795 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2796 if (!(usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002797 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00331";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002798 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT";
2799 }
2800 break;
2801 default:
2802 break;
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002803 }
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002804 if (error_usage_bit) {
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002805 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002806 error_str << "Buffer (" << report_data->FormatHandle(buffer_node->buffer()) << ") with usage mask " << std::hex
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002807 << std::showbase << usage << " being used for a descriptor update of type " << string_VkDescriptorType(type)
2808 << " does not have " << error_usage_bit << " set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002809 *error_msg = error_str.str();
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002810 return false;
2811 }
2812 return true;
2813}
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002814// For buffer descriptor updates, verify the buffer usage and VkDescriptorBufferInfo struct which includes:
2815// 1. buffer is valid
2816// 2. buffer was created with correct usage flags
2817// 3. offset is less than buffer size
2818// 4. range is either VK_WHOLE_SIZE or falls in (0, (buffer size - offset)]
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002819// 5. range and offset are within the device's limits
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002820// 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 -06002821bool CoreChecks::ValidateBufferUpdate(VkDescriptorBufferInfo const *buffer_info, VkDescriptorType type, const char *func_name,
John Zulaufbd9b3412019-08-22 17:16:11 -06002822 std::string *error_code, std::string *error_msg) const {
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002823 // First make sure that buffer is valid
John Zulaufc93c4252019-06-25 09:19:49 -06002824 auto buffer_node = GetBufferState(buffer_info->buffer);
Tobin Ehlisfa8b6182016-12-22 13:40:45 -07002825 // Any invalid buffer should already be caught by object_tracker
2826 assert(buffer_node);
John Zulaufc93c4252019-06-25 09:19:49 -06002827 if (ValidateMemoryIsBoundToBuffer(buffer_node, func_name, "VUID-VkWriteDescriptorSet-descriptorType-00329")) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002828 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00329";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002829 *error_msg = "No memory bound to buffer.";
Tobin Ehlis81280962016-07-20 14:04:20 -06002830 return false;
Tobin Ehlisfed999f2016-09-21 15:09:45 -06002831 }
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002832 // Verify usage bits
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002833 if (!cvdescriptorset::ValidateBufferUsage(report_data, buffer_node, type, error_code, error_msg)) {
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002834 // error_msg will have been updated by ValidateBufferUsage()
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002835 return false;
2836 }
2837 // offset must be less than buffer size
Jeremy Hayesd1a6a822017-03-09 14:39:45 -07002838 if (buffer_info->offset >= buffer_node->createInfo.size) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002839 *error_code = "VUID-VkDescriptorBufferInfo-offset-00340";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002840 std::stringstream error_str;
Jeremy Hayesd1a6a822017-03-09 14:39:45 -07002841 error_str << "VkDescriptorBufferInfo offset of " << buffer_info->offset << " is greater than or equal to buffer "
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002842 << report_data->FormatHandle(buffer_node->buffer()) << " size of " << buffer_node->createInfo.size;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002843 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002844 return false;
2845 }
2846 if (buffer_info->range != VK_WHOLE_SIZE) {
2847 // Range must be VK_WHOLE_SIZE or > 0
2848 if (!buffer_info->range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002849 *error_code = "VUID-VkDescriptorBufferInfo-range-00341";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002850 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002851 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer())
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002852 << " VkDescriptorBufferInfo range is not VK_WHOLE_SIZE and is zero, which is not allowed.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002853 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002854 return false;
2855 }
2856 // Range must be VK_WHOLE_SIZE or <= (buffer size - offset)
2857 if (buffer_info->range > (buffer_node->createInfo.size - buffer_info->offset)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002858 *error_code = "VUID-VkDescriptorBufferInfo-range-00342";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002859 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002860 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer()) << " VkDescriptorBufferInfo range is "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002861 << buffer_info->range << " which is greater than buffer size (" << buffer_node->createInfo.size
2862 << ") minus requested offset of " << buffer_info->offset;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002863 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002864 return false;
2865 }
2866 }
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002867 // Check buffer update sizes against device limits
John Zulaufc93c4252019-06-25 09:19:49 -06002868 const auto &limits = phys_dev_props.limits;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002869 if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == type || VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) {
John Zulaufd9435c32019-06-05 15:55:36 -06002870 auto max_ub_range = limits.maxUniformBufferRange;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002871 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_ub_range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002872 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00332";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002873 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002874 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer()) << " VkDescriptorBufferInfo range is "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002875 << buffer_info->range << " which is greater than this device's maxUniformBufferRange (" << max_ub_range
2876 << ")";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002877 *error_msg = error_str.str();
2878 return false;
Peter Kohaut2794a292018-07-13 11:13:47 +02002879 } else if (buffer_info->range == VK_WHOLE_SIZE && (buffer_node->createInfo.size - buffer_info->offset) > max_ub_range) {
2880 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00332";
2881 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002882 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer())
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002883 << " VkDescriptorBufferInfo range is VK_WHOLE_SIZE but effective range "
Peter Kohaut18f413d2018-07-16 13:15:42 +02002884 << "(" << (buffer_node->createInfo.size - buffer_info->offset) << ") is greater than this device's "
Peter Kohaut2794a292018-07-13 11:13:47 +02002885 << "maxUniformBufferRange (" << max_ub_range << ")";
2886 *error_msg = error_str.str();
2887 return false;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002888 }
2889 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type || VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) {
John Zulaufd9435c32019-06-05 15:55:36 -06002890 auto max_sb_range = limits.maxStorageBufferRange;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002891 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_sb_range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002892 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00333";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002893 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002894 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer()) << " VkDescriptorBufferInfo range is "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002895 << buffer_info->range << " which is greater than this device's maxStorageBufferRange (" << max_sb_range
2896 << ")";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002897 *error_msg = error_str.str();
2898 return false;
Peter Kohaut2794a292018-07-13 11:13:47 +02002899 } else if (buffer_info->range == VK_WHOLE_SIZE && (buffer_node->createInfo.size - buffer_info->offset) > max_sb_range) {
2900 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00333";
2901 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002902 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer())
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002903 << " VkDescriptorBufferInfo range is VK_WHOLE_SIZE but effective range "
Peter Kohaut18f413d2018-07-16 13:15:42 +02002904 << "(" << (buffer_node->createInfo.size - buffer_info->offset) << ") is greater than this device's "
Peter Kohaut2794a292018-07-13 11:13:47 +02002905 << "maxStorageBufferRange (" << max_sb_range << ")";
2906 *error_msg = error_str.str();
2907 return false;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002908 }
2909 }
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002910 return true;
2911}
sourav parmarcd5fb182020-07-17 12:58:44 -07002912template <typename T>
2913bool CoreChecks::ValidateAccelerationStructureUpdate(T acc_node, const char *func_name, std::string *error_code,
Jeff Bolz95176d02020-04-01 00:36:16 -05002914 std::string *error_msg) const {
Jeff Bolz95176d02020-04-01 00:36:16 -05002915 // Any invalid acc struct should already be caught by object_tracker
2916 assert(acc_node);
2917 if (ValidateMemoryIsBoundToAccelerationStructure(acc_node, func_name, kVUIDUndefined)) {
2918 *error_code = kVUIDUndefined;
2919 *error_msg = "No memory bound to acceleration structure.";
2920 return false;
2921 }
2922 return true;
2923}
2924
Tobin Ehlis300888c2016-05-18 13:43:26 -06002925// Verify that the contents of the update are ok, but don't perform actual update
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002926bool CoreChecks::VerifyCopyUpdateContents(const VkCopyDescriptorSet *update, const DescriptorSet *src_set,
2927 VkDescriptorType src_type, uint32_t src_index, const DescriptorSet *dst_set,
2928 VkDescriptorType dst_type, uint32_t dst_index, const char *func_name,
2929 std::string *error_code, std::string *error_msg) const {
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002930 // Note : Repurposing some Write update error codes here as specific details aren't called out for copy updates like they are
2931 // for write updates
John Zulaufc93c4252019-06-25 09:19:49 -06002932 using DescriptorClass = cvdescriptorset::DescriptorClass;
2933 using BufferDescriptor = cvdescriptorset::BufferDescriptor;
2934 using ImageDescriptor = cvdescriptorset::ImageDescriptor;
2935 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
2936 using SamplerDescriptor = cvdescriptorset::SamplerDescriptor;
2937 using TexelDescriptor = cvdescriptorset::TexelDescriptor;
2938
2939 auto device_data = this;
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002940
2941 if (dst_type == VK_DESCRIPTOR_TYPE_SAMPLER) {
2942 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
2943 const auto dst_desc = dst_set->GetDescriptorFromGlobalIndex(dst_index + di);
2944 if (!dst_desc->updated) continue;
2945 if (dst_desc->IsImmutableSampler()) {
2946 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02753";
2947 std::stringstream error_str;
2948 error_str << "Attempted copy update to an immutable sampler descriptor.";
2949 *error_msg = error_str.str();
2950 return false;
2951 }
2952 }
2953 }
2954
2955 switch (src_set->GetDescriptorFromGlobalIndex(src_index)->descriptor_class) {
John Zulaufc93c4252019-06-25 09:19:49 -06002956 case DescriptorClass::PlainSampler: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002957 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002958 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002959 if (!src_desc->updated) continue;
2960 if (!src_desc->IsImmutableSampler()) {
John Zulaufd9435c32019-06-05 15:55:36 -06002961 auto update_sampler = static_cast<const SamplerDescriptor *>(src_desc)->GetSampler();
John Zulaufc93c4252019-06-25 09:19:49 -06002962 if (!ValidateSampler(update_sampler)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002963 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002964 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002965 error_str << "Attempted copy update to sampler descriptor with invalid sampler: "
2966 << report_data->FormatHandle(update_sampler) << ".";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002967 *error_msg = error_str.str();
2968 return false;
2969 }
2970 } else {
2971 // TODO : Warn here
2972 }
2973 }
2974 break;
2975 }
John Zulaufc93c4252019-06-25 09:19:49 -06002976 case DescriptorClass::ImageSampler: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002977 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002978 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002979 if (!src_desc->updated) continue;
2980 auto img_samp_desc = static_cast<const ImageSamplerDescriptor *>(src_desc);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002981 // First validate sampler
2982 if (!img_samp_desc->IsImmutableSampler()) {
2983 auto update_sampler = img_samp_desc->GetSampler();
John Zulaufc93c4252019-06-25 09:19:49 -06002984 if (!ValidateSampler(update_sampler)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002985 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002986 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002987 error_str << "Attempted copy update to sampler descriptor with invalid sampler: "
2988 << report_data->FormatHandle(update_sampler) << ".";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002989 *error_msg = error_str.str();
2990 return false;
2991 }
2992 } else {
2993 // TODO : Warn here
2994 }
2995 // Validate image
2996 auto image_view = img_samp_desc->GetImageView();
2997 auto image_layout = img_samp_desc->GetImageLayout();
Jeff Bolz165818a2020-05-08 11:19:03 -05002998 if (image_view) {
2999 if (!ValidateImageUpdate(image_view, image_layout, src_type, func_name, error_code, error_msg)) {
3000 std::stringstream error_str;
3001 error_str << "Attempted copy update to combined image sampler descriptor failed due to: "
3002 << error_msg->c_str();
3003 *error_msg = error_str.str();
3004 return false;
3005 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06003006 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06003007 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003008 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06003009 }
John Zulaufc93c4252019-06-25 09:19:49 -06003010 case DescriptorClass::Image: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003011 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003012 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02003013 if (!src_desc->updated) continue;
3014 auto img_desc = static_cast<const ImageDescriptor *>(src_desc);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003015 auto image_view = img_desc->GetImageView();
3016 auto image_layout = img_desc->GetImageLayout();
Jeff Bolz165818a2020-05-08 11:19:03 -05003017 if (image_view) {
3018 if (!ValidateImageUpdate(image_view, image_layout, src_type, func_name, error_code, error_msg)) {
3019 std::stringstream error_str;
3020 error_str << "Attempted copy update to image descriptor failed due to: " << error_msg->c_str();
3021 *error_msg = error_str.str();
3022 return false;
3023 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06003024 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06003025 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003026 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06003027 }
John Zulaufc93c4252019-06-25 09:19:49 -06003028 case DescriptorClass::TexelBuffer: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003029 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003030 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02003031 if (!src_desc->updated) continue;
John Zulaufd9435c32019-06-05 15:55:36 -06003032 auto buffer_view = static_cast<const TexelDescriptor *>(src_desc)->GetBufferView();
Jeff Bolz165818a2020-05-08 11:19:03 -05003033 if (buffer_view) {
3034 auto bv_state = device_data->GetBufferViewState(buffer_view);
3035 if (!bv_state) {
3036 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
3037 std::stringstream error_str;
3038 error_str << "Attempted copy update to texel buffer descriptor with invalid buffer view: "
3039 << report_data->FormatHandle(buffer_view);
3040 *error_msg = error_str.str();
3041 return false;
3042 }
3043 auto buffer = bv_state->create_info.buffer;
3044 if (!cvdescriptorset::ValidateBufferUsage(report_data, GetBufferState(buffer), src_type, error_code,
3045 error_msg)) {
3046 std::stringstream error_str;
3047 error_str << "Attempted copy update to texel buffer descriptor failed due to: " << error_msg->c_str();
3048 *error_msg = error_str.str();
3049 return false;
3050 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003051 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06003052 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003053 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06003054 }
John Zulaufc93c4252019-06-25 09:19:49 -06003055 case DescriptorClass::GeneralBuffer: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003056 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003057 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02003058 if (!src_desc->updated) continue;
John Zulaufd9435c32019-06-05 15:55:36 -06003059 auto buffer = static_cast<const BufferDescriptor *>(src_desc)->GetBuffer();
Jeff Bolz165818a2020-05-08 11:19:03 -05003060 if (buffer) {
3061 if (!cvdescriptorset::ValidateBufferUsage(report_data, GetBufferState(buffer), src_type, error_code,
3062 error_msg)) {
3063 std::stringstream error_str;
3064 error_str << "Attempted copy update to buffer descriptor failed due to: " << error_msg->c_str();
3065 *error_msg = error_str.str();
3066 return false;
3067 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003068 }
Tobin Ehliscbcf2342016-05-24 13:07:12 -06003069 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003070 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06003071 }
John Zulaufc93c4252019-06-25 09:19:49 -06003072 case DescriptorClass::InlineUniform:
3073 case DescriptorClass::AccelerationStructure:
Ricardo Garcia14f4f762021-04-13 11:36:12 +02003074 case DescriptorClass::Mutable:
Jeff Bolze54ae892018-09-08 12:16:29 -05003075 break;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07003076 default:
3077 assert(0); // We've already verified update type so should never get here
3078 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06003079 }
3080 // All checks passed so update contents are good
3081 return true;
Chris Forbesb4e0bdb2016-05-31 16:34:40 +12003082}
Tobin Ehlisee471462016-05-26 11:21:59 -06003083// Verify that the state at allocate time is correct, but don't actually allocate the sets yet
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07003084bool CoreChecks::ValidateAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *p_alloc_info,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05003085 const cvdescriptorset::AllocateDescriptorSetsData *ds_data) const {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06003086 bool skip = false;
Mark Lobodzinski7804bd42019-03-06 11:28:48 -07003087 auto pool_state = GetDescriptorPoolState(p_alloc_info->descriptorPool);
Tobin Ehlisee471462016-05-26 11:21:59 -06003088
3089 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
Jeff Bolz6ae39612019-10-11 20:57:36 -05003090 auto layout = GetDescriptorSetLayoutShared(p_alloc_info->pSetLayouts[i]);
John Zulauf5562d062018-01-24 11:54:05 -07003091 if (layout) { // nullptr layout indicates no valid layout handle for this device, validated/logged in object_tracker
John Zulauf1d27e0a2018-11-05 10:12:48 -07003092 if (layout->IsPushDescriptor()) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003093 skip |= LogError(p_alloc_info->pSetLayouts[i], "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-00308",
3094 "%s specified at pSetLayouts[%" PRIu32
3095 "] in vkAllocateDescriptorSets() was created with invalid flag %s set.",
3096 report_data->FormatHandle(p_alloc_info->pSetLayouts[i]).c_str(), i,
3097 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR");
John Zulauf5562d062018-01-24 11:54:05 -07003098 }
Mike Schuchardt2df08912020-12-15 16:28:09 -08003099 if (layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT &&
3100 !(pool_state->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT)) {
sfricke-samsungbda4a852021-03-06 20:58:01 -08003101 skip |= LogError(
3102 device, "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-03044",
3103 "vkAllocateDescriptorSets(): Descriptor set layout create flags and pool create flags mismatch for index (%d)",
3104 i);
Jeff Bolzfdf96072018-04-10 14:32:18 -05003105 }
ziga-lunarg2ab96532021-07-19 11:06:41 +02003106 if (layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE &&
3107 !(pool_state->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE)) {
3108 skip |= LogError(device, "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-04610",
3109 "vkAllocateDescriptorSets(): pSetLayouts[%d].flags contain "
3110 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE bit, but the pool was not created "
3111 "with the VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE bit.",
3112 i);
3113 }
Tobin Ehlisee471462016-05-26 11:21:59 -06003114 }
3115 }
sfricke-samsung45996a42021-09-16 13:45:27 -07003116 if (!IsExtEnabled(device_extensions.vk_khr_maintenance1)) {
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06003117 // Track number of descriptorSets allowable in this pool
3118 if (pool_state->availableSets < p_alloc_info->descriptorSetCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003119 skip |= LogError(pool_state->pool, "VUID-VkDescriptorSetAllocateInfo-descriptorSetCount-00306",
sfricke-samsungbda4a852021-03-06 20:58:01 -08003120 "vkAllocateDescriptorSets(): Unable to allocate %u descriptorSets from %s"
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003121 ". This pool only has %d descriptorSets remaining.",
3122 p_alloc_info->descriptorSetCount, report_data->FormatHandle(pool_state->pool).c_str(),
3123 pool_state->availableSets);
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06003124 }
3125 // Determine whether descriptor counts are satisfiable
Jeff Bolze54ae892018-09-08 12:16:29 -05003126 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 -05003127 auto count_iter = pool_state->availableDescriptorTypeCount.find(it->first);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003128 uint32_t available_count = (count_iter != pool_state->availableDescriptorTypeCount.end()) ? count_iter->second : 0;
Jeff Bolz46c0ea02019-10-09 13:06:29 -05003129
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003130 if (ds_data->required_descriptors_by_type.at(it->first) > available_count) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003131 skip |= LogError(pool_state->pool, "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307",
sfricke-samsungbda4a852021-03-06 20:58:01 -08003132 "vkAllocateDescriptorSets(): Unable to allocate %u descriptors of type %s from %s"
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003133 ". This pool only has %d descriptors of this type remaining.",
3134 ds_data->required_descriptors_by_type.at(it->first),
3135 string_VkDescriptorType(VkDescriptorType(it->first)),
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003136 report_data->FormatHandle(pool_state->pool).c_str(), available_count);
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06003137 }
Tobin Ehlisee471462016-05-26 11:21:59 -06003138 }
3139 }
Tobin Ehlis5d749ea2016-07-18 13:14:01 -06003140
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07003141 const auto *count_allocate_info = LvlFindInChain<VkDescriptorSetVariableDescriptorCountAllocateInfo>(p_alloc_info->pNext);
Jeff Bolzfdf96072018-04-10 14:32:18 -05003142
3143 if (count_allocate_info) {
3144 if (count_allocate_info->descriptorSetCount != 0 &&
3145 count_allocate_info->descriptorSetCount != p_alloc_info->descriptorSetCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003146 skip |= LogError(device, "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfo-descriptorSetCount-03045",
sfricke-samsungbda4a852021-03-06 20:58:01 -08003147 "vkAllocateDescriptorSets(): VkDescriptorSetAllocateInfo::descriptorSetCount (%d) != "
Mike Schuchardt2df08912020-12-15 16:28:09 -08003148 "VkDescriptorSetVariableDescriptorCountAllocateInfo::descriptorSetCount (%d)",
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003149 p_alloc_info->descriptorSetCount, count_allocate_info->descriptorSetCount);
Jeff Bolzfdf96072018-04-10 14:32:18 -05003150 }
3151 if (count_allocate_info->descriptorSetCount == p_alloc_info->descriptorSetCount) {
3152 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
Jeff Bolz6ae39612019-10-11 20:57:36 -05003153 auto layout = GetDescriptorSetLayoutShared(p_alloc_info->pSetLayouts[i]);
Jeff Bolzfdf96072018-04-10 14:32:18 -05003154 if (count_allocate_info->pDescriptorCounts[i] > layout->GetDescriptorCountFromBinding(layout->GetMaxBinding())) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003155 skip |= LogError(device, "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfo-pSetLayouts-03046",
sfricke-samsungbda4a852021-03-06 20:58:01 -08003156 "vkAllocateDescriptorSets(): pDescriptorCounts[%d] = (%d), binding's descriptorCount = (%d)",
3157 i, count_allocate_info->pDescriptorCounts[i],
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003158 layout->GetDescriptorCountFromBinding(layout->GetMaxBinding()));
Jeff Bolzfdf96072018-04-10 14:32:18 -05003159 }
3160 }
3161 }
3162 }
3163
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06003164 return skip;
Tobin Ehlisee471462016-05-26 11:21:59 -06003165}
John Zulauf48a6a702017-12-22 17:14:54 -07003166
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05003167const BindingReqMap &cvdescriptorset::PrefilterBindRequestMap::FilteredMap(const CMD_BUFFER_STATE &cb_state,
3168 const PIPELINE_STATE &pipeline) {
John Zulauffbf3c202019-07-17 14:57:14 -06003169 if (IsManyDescriptors()) {
Karl Schultz7090a052020-11-10 08:54:21 -07003170 filtered_map_.reset(new BindingReqMap);
John Zulauffbf3c202019-07-17 14:57:14 -06003171 descriptor_set_.FilterBindingReqs(cb_state, pipeline, orig_map_, filtered_map_.get());
3172 return *filtered_map_;
John Zulauf48a6a702017-12-22 17:14:54 -07003173 }
John Zulauffbf3c202019-07-17 14:57:14 -06003174 return orig_map_;
Artem Kharytoniuk2456f992018-01-12 14:17:41 +01003175}
John Zulauf4a015c92019-06-04 09:50:05 -06003176
3177// Starting at offset descriptor of given binding, parse over update_count
3178// descriptor updates and verify that for any binding boundaries that are crossed, the next binding(s) are all consistent
3179// Consistency means that their type, stage flags, and whether or not they use immutable samplers matches
3180// If so, return true. If not, fill in error_msg and return false
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003181bool cvdescriptorset::VerifyUpdateConsistency(debug_report_data *report_data,
3182 DescriptorSetLayout::ConstBindingIterator current_binding, uint32_t offset,
John Zulauf4a015c92019-06-04 09:50:05 -06003183 uint32_t update_count, const char *type, const VkDescriptorSet set,
3184 std::string *error_msg) {
locke-lunarge46b7782019-09-10 01:44:20 -06003185 bool pass = true;
John Zulauf4a015c92019-06-04 09:50:05 -06003186 // Verify consecutive bindings match (if needed)
3187 auto orig_binding = current_binding;
locke-lunarge46b7782019-09-10 01:44:20 -06003188
3189 while (pass && update_count) {
3190 // First, it's legal to offset beyond your own binding so handle that case
3191 if (offset > 0) {
3192 const auto &index_range = current_binding.GetGlobalIndexRange();
3193 // index_range.start + offset is which descriptor is needed to update. If it > index_range.end, it means the descriptor
3194 // isn't in this binding, maybe in next binding.
3195 if ((index_range.start + offset) >= index_range.end) {
3196 // Advance to next binding, decrement offset by binding size
3197 offset -= current_binding.GetDescriptorCount();
3198 ++current_binding;
3199 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
3200 if (!orig_binding.IsConsistent(current_binding)) {
3201 pass = false;
3202 }
3203 continue;
John Zulauf4a015c92019-06-04 09:50:05 -06003204 }
John Zulauf4a015c92019-06-04 09:50:05 -06003205 }
locke-lunarge46b7782019-09-10 01:44:20 -06003206
3207 update_count -= std::min(update_count, current_binding.GetDescriptorCount() - offset);
3208 if (update_count) {
3209 // Starting offset is beyond the current binding. Check consistency, update counters and advance to the next binding,
3210 // looking for the start point. All bindings (even those skipped) must be consistent with the update and with the
3211 // original binding.
3212 offset = 0;
3213 ++current_binding;
3214 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
3215 if (!orig_binding.IsConsistent(current_binding)) {
3216 pass = false;
3217 }
3218 }
John Zulauf4a015c92019-06-04 09:50:05 -06003219 }
locke-lunarge46b7782019-09-10 01:44:20 -06003220
3221 if (!pass) {
3222 std::stringstream error_str;
3223 error_str << "Attempting " << type;
3224 if (current_binding.Layout()->IsPushDescriptor()) {
3225 error_str << " push descriptors";
3226 } else {
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003227 error_str << " descriptor set " << report_data->FormatHandle(set);
locke-lunarge46b7782019-09-10 01:44:20 -06003228 }
3229 error_str << " binding #" << orig_binding.Binding() << " with #" << update_count
3230 << " descriptors being updated but this update oversteps the bounds of this binding and the next binding is "
sfricke-samsung5de34882021-04-15 22:33:23 -07003231 "not consistent with current binding";
3232
3233 // Get what was not consistent in IsConsistent() as a more detailed error message
3234 const auto *binding_ci = orig_binding.GetDescriptorSetLayoutBindingPtr();
3235 const auto *other_binding_ci = current_binding.GetDescriptorSetLayoutBindingPtr();
3236 if (binding_ci == nullptr || other_binding_ci == nullptr) {
3237 error_str << " (No two valid DescriptorSetLayoutBinding to compare)";
3238 } else if (binding_ci->descriptorType != other_binding_ci->descriptorType) {
3239 error_str << " (" << string_VkDescriptorType(binding_ci->descriptorType)
3240 << " != " << string_VkDescriptorType(other_binding_ci->descriptorType) << ")";
3241 } else if (binding_ci->stageFlags != other_binding_ci->stageFlags) {
3242 error_str << " (" << string_VkShaderStageFlags(binding_ci->stageFlags)
3243 << " != " << string_VkShaderStageFlags(other_binding_ci->stageFlags) << ")";
3244 } else if (!hash_util::similar_for_nullity(binding_ci->pImmutableSamplers, other_binding_ci->pImmutableSamplers)) {
3245 error_str << " (pImmutableSamplers don't match)";
3246 } else if (orig_binding.GetDescriptorBindingFlags() != current_binding.GetDescriptorBindingFlags()) {
3247 error_str << " (" << string_VkDescriptorBindingFlags(orig_binding.GetDescriptorBindingFlags())
3248 << " != " << string_VkDescriptorBindingFlags(current_binding.GetDescriptorBindingFlags()) << ")";
3249 }
3250
3251 error_str << " so this update is invalid";
locke-lunarge46b7782019-09-10 01:44:20 -06003252 *error_msg = error_str.str();
3253 }
3254 return pass;
John Zulauf4a015c92019-06-04 09:50:05 -06003255}
John Zulauf4956fff2019-06-04 16:54:38 -06003256
3257// Validate the state for a given write update but don't actually perform the update
3258// 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 -06003259bool CoreChecks::ValidateWriteUpdate(const DescriptorSet *dest_set, const VkWriteDescriptorSet *update, const char *func_name,
ziga-lunarg6c46b242021-09-13 18:33:37 +02003260 std::string *error_code, std::string *error_msg, bool push) const {
Jeff Bolz6aad1742019-10-16 11:10:09 -05003261 const auto dest_layout = dest_set->GetLayout().get();
John Zulauf4956fff2019-06-04 16:54:38 -06003262
3263 // Verify dst layout still valid
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06003264 if (dest_layout->Destroyed()) {
John Zulauf4956fff2019-06-04 16:54:38 -06003265 *error_code = "VUID-VkWriteDescriptorSet-dstSet-00320";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06003266 std::ostringstream str;
3267 str << "Cannot call " << func_name << " to perform write update on " << dest_set->StringifySetAndLayout()
3268 << " which has been destroyed";
3269 *error_msg = str.str();
John Zulauf4956fff2019-06-04 16:54:38 -06003270 return false;
3271 }
3272 // Verify dst binding exists
3273 if (!dest_layout->HasBinding(update->dstBinding)) {
3274 *error_code = "VUID-VkWriteDescriptorSet-dstBinding-00315";
3275 std::stringstream error_str;
3276 error_str << dest_set->StringifySetAndLayout() << " does not have binding " << update->dstBinding;
3277 *error_msg = error_str.str();
3278 return false;
3279 }
3280
Jeff Bolz6aad1742019-10-16 11:10:09 -05003281 DescriptorSetLayout::ConstBindingIterator dest(dest_layout, update->dstBinding);
John Zulauf4956fff2019-06-04 16:54:38 -06003282 // Make sure binding isn't empty
3283 if (0 == dest.GetDescriptorCount()) {
3284 *error_code = "VUID-VkWriteDescriptorSet-dstBinding-00316";
3285 std::stringstream error_str;
3286 error_str << dest_set->StringifySetAndLayout() << " cannot updated binding " << update->dstBinding
3287 << " that has 0 descriptors";
3288 *error_msg = error_str.str();
3289 return false;
3290 }
3291
3292 // Verify idle ds
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06003293 if (dest_set->InUse() && !(dest.GetDescriptorBindingFlags() & (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT |
Mike Schuchardt2df08912020-12-15 16:28:09 -08003294 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT))) {
John Zulauf4956fff2019-06-04 16:54:38 -06003295 // TODO : Re-using Free Idle error code, need write update idle error code
3296 *error_code = "VUID-vkFreeDescriptorSets-pDescriptorSets-00309";
3297 std::stringstream error_str;
3298 error_str << "Cannot call " << func_name << " to perform write update on " << dest_set->StringifySetAndLayout()
3299 << " that is in use by a command buffer";
3300 *error_msg = error_str.str();
3301 return false;
3302 }
3303 // We know that binding is valid, verify update and do update on each descriptor
3304 auto start_idx = dest.GetGlobalIndexRange().start + update->dstArrayElement;
3305 auto type = dest.GetType();
Tony-LunarGf563b362021-03-18 16:13:18 -06003306 if ((type != VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) && (type != update->descriptorType)) {
John Zulauf4956fff2019-06-04 16:54:38 -06003307 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00319";
3308 std::stringstream error_str;
3309 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3310 << " with type " << string_VkDescriptorType(type) << " but update type is "
3311 << string_VkDescriptorType(update->descriptorType);
3312 *error_msg = error_str.str();
3313 return false;
3314 }
John Zulauf4956fff2019-06-04 16:54:38 -06003315 if (type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
3316 if ((update->dstArrayElement % 4) != 0) {
3317 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02219";
3318 std::stringstream error_str;
3319 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3320 << " with "
3321 << "dstArrayElement " << update->dstArrayElement << " not a multiple of 4";
3322 *error_msg = error_str.str();
3323 return false;
3324 }
3325 if ((update->descriptorCount % 4) != 0) {
3326 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02220";
3327 std::stringstream error_str;
3328 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3329 << " with "
3330 << "descriptorCount " << update->descriptorCount << " not a multiple of 4";
3331 *error_msg = error_str.str();
3332 return false;
3333 }
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07003334 const auto *write_inline_info = LvlFindInChain<VkWriteDescriptorSetInlineUniformBlockEXT>(update->pNext);
John Zulauf4956fff2019-06-04 16:54:38 -06003335 if (!write_inline_info || write_inline_info->dataSize != update->descriptorCount) {
3336 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02221";
3337 std::stringstream error_str;
3338 if (!write_inline_info) {
3339 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #"
3340 << update->dstBinding << " with "
3341 << "VkWriteDescriptorSetInlineUniformBlockEXT missing";
3342 } else {
3343 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #"
3344 << update->dstBinding << " with "
3345 << "VkWriteDescriptorSetInlineUniformBlockEXT dataSize " << write_inline_info->dataSize
3346 << " not equal to "
3347 << "VkWriteDescriptorSet descriptorCount " << update->descriptorCount;
3348 }
3349 *error_msg = error_str.str();
3350 return false;
3351 }
3352 // This error is probably unreachable due to the previous two errors
3353 if (write_inline_info && (write_inline_info->dataSize % 4) != 0) {
3354 *error_code = "VUID-VkWriteDescriptorSetInlineUniformBlockEXT-dataSize-02222";
3355 std::stringstream error_str;
3356 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3357 << " with "
3358 << "VkWriteDescriptorSetInlineUniformBlockEXT dataSize " << write_inline_info->dataSize
3359 << " not a multiple of 4";
3360 *error_msg = error_str.str();
3361 return false;
3362 }
3363 }
sfricke-samsung941d48b2020-02-10 00:20:01 -08003364 // Verify all bindings update share identical properties across all items
3365 if (update->descriptorCount > 0) {
3366 // Save first binding information and error if something different is found
3367 DescriptorSetLayout::ConstBindingIterator current_binding(dest_layout, update->dstBinding);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003368 VkShaderStageFlags stage_flags = current_binding.GetStageFlags();
3369 VkDescriptorType descriptor_type = current_binding.GetType();
3370 bool immutable_samplers = (current_binding.GetImmutableSamplerPtr() == nullptr);
3371 uint32_t dst_array_element = update->dstArrayElement;
sfricke-samsung941d48b2020-02-10 00:20:01 -08003372
Jeff Bolz9198e882020-03-18 13:03:30 -05003373 for (uint32_t i = 0; i < update->descriptorCount;) {
sfricke-samsung941d48b2020-02-10 00:20:01 -08003374 if (current_binding.AtEnd() == true) {
3375 break; // prevents setting error here if bindings don't exist
3376 }
3377
Quentin Huot-Marchand98d84dd2021-06-24 09:54:58 +02003378 // All consecutive bindings updated, except those with a descriptorCount of zero, must have identical descType and stageFlags
3379 if(current_binding.GetDescriptorCount() > 0) {
3380 // Check for consistent stageFlags and descriptorType
3381 if ((current_binding.GetStageFlags() != stage_flags) || (current_binding.GetType() != descriptor_type)) {
3382 *error_code = "VUID-VkWriteDescriptorSet-descriptorCount-00317";
3383 std::stringstream error_str;
3384 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3385 << current_binding.GetIndex() << " (" << i << " from dstBinding offset)"
3386 << " with a different stageFlag and/or descriptorType from previous bindings."
3387 << " All bindings must have consecutive stageFlag and/or descriptorType across a VkWriteDescriptorSet";
3388 *error_msg = error_str.str();
3389 return false;
3390 }
3391 // Check if all immutableSamplers or not
3392 if ((current_binding.GetImmutableSamplerPtr() == nullptr) != immutable_samplers) {
3393 *error_code = "VUID-VkWriteDescriptorSet-descriptorCount-00318";
3394 std::stringstream error_str;
3395 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3396 << current_binding.GetIndex() << " (" << i << " from dstBinding offset)"
3397 << " with a different usage of immutable samplers from previous bindings."
3398 << " All bindings must have all or none usage of immutable samplers across a VkWriteDescriptorSet";
3399 *error_msg = error_str.str();
3400 return false;
3401 }
sfricke-samsung941d48b2020-02-10 00:20:01 -08003402 }
Jeff Bolz9198e882020-03-18 13:03:30 -05003403
3404 // Skip the remaining descriptors for this binding, and move to the next binding
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003405 i += (current_binding.GetDescriptorCount() - dst_array_element);
3406 dst_array_element = 0;
sfricke-samsung941d48b2020-02-10 00:20:01 -08003407 ++current_binding;
3408 }
3409 }
3410
John Zulauf4956fff2019-06-04 16:54:38 -06003411 // Verify consecutive bindings match (if needed)
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003412 if (!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(dest_layout, update->dstBinding),
John Zulauf4956fff2019-06-04 16:54:38 -06003413 update->dstArrayElement, update->descriptorCount, "write update to", dest_set->GetSet(),
3414 error_msg)) {
John Zulauf4956fff2019-06-04 16:54:38 -06003415 *error_code = "VUID-VkWriteDescriptorSet-dstArrayElement-00321";
3416 return false;
3417 }
Tony-LunarG1f79c952020-10-27 15:55:51 -06003418 // Verify write to variable descriptor
3419 if (dest_set->IsVariableDescriptorCount(update->dstBinding)) {
3420 if ((update->dstArrayElement + update->descriptorCount) > dest_set->GetVariableDescriptorCount()) {
3421 std::stringstream error_str;
3422 *error_code = "VUID-VkWriteDescriptorSet-dstArrayElement-00321";
3423 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3424 << update->dstBinding << " array element " << update->dstArrayElement << " with " << update->descriptorCount
3425 << " writes but variable descriptor size is " << dest_set->GetVariableDescriptorCount();
3426 *error_msg = error_str.str();
3427 return false;
3428 }
3429 }
John Zulauf4956fff2019-06-04 16:54:38 -06003430 // Update is within bounds and consistent so last step is to validate update contents
ziga-lunarg6c46b242021-09-13 18:33:37 +02003431 if (!VerifyWriteUpdateContents(dest_set, update, start_idx, func_name, error_code, error_msg, push)) {
John Zulauf4956fff2019-06-04 16:54:38 -06003432 std::stringstream error_str;
3433 error_str << "Write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3434 << " failed with error message: " << error_msg->c_str();
3435 *error_msg = error_str.str();
3436 return false;
3437 }
3438 // All checks passed, update is clean
3439 return true;
3440}
John Zulaufadb3f542019-06-04 17:01:00 -06003441
3442// Verify that the contents of the update are ok, but don't perform actual update
John Zulaufc93c4252019-06-25 09:19:49 -06003443bool CoreChecks::VerifyWriteUpdateContents(const DescriptorSet *dest_set, const VkWriteDescriptorSet *update, const uint32_t index,
ziga-lunarg6c46b242021-09-13 18:33:37 +02003444 const char *func_name, std::string *error_code, std::string *error_msg,
3445 bool push) const {
John Zulaufc93c4252019-06-25 09:19:49 -06003446 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
Nathaniel Cesarioff521512020-12-11 16:00:26 -07003447 using Descriptor = cvdescriptorset::Descriptor;
John Zulaufc93c4252019-06-25 09:19:49 -06003448
John Zulaufadb3f542019-06-04 17:01:00 -06003449 switch (update->descriptorType) {
3450 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
3451 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3452 // Validate image
3453 auto image_view = update->pImageInfo[di].imageView;
3454 auto image_layout = update->pImageInfo[di].imageLayout;
Mark Lobodzinski3ca937b2020-02-14 14:56:06 -07003455 auto sampler = update->pImageInfo[di].sampler;
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003456 auto iv_state = GetImageViewState(image_view);
Nathaniel Cesarioff521512020-12-11 16:00:26 -07003457 const ImageSamplerDescriptor *desc =
3458 (const ImageSamplerDescriptor *)dest_set->GetDescriptorFromGlobalIndex(index + di);
Jeff Bolz165818a2020-05-08 11:19:03 -05003459 if (image_view) {
3460 auto image_state = iv_state->image_state.get();
3461 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, func_name, error_code, error_msg)) {
3462 std::stringstream error_str;
3463 error_str << "Attempted write update to combined image sampler descriptor failed due to: "
3464 << error_msg->c_str();
3465 *error_msg = error_str.str();
3466 return false;
3467 }
sfricke-samsung45996a42021-09-16 13:45:27 -07003468 if (IsExtEnabled(device_extensions.vk_khr_sampler_ycbcr_conversion)) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003469 if (desc->IsImmutableSampler()) {
3470 auto sampler_state = GetSamplerState(desc->GetSampler());
3471 if (iv_state && sampler_state) {
3472 if (iv_state->samplerConversion != sampler_state->samplerConversion) {
3473 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-01948";
3474 std::stringstream error_str;
3475 error_str
3476 << "Attempted write update to combined image sampler and image view and sampler ycbcr "
3477 "conversions are not identical, sampler: "
3478 << report_data->FormatHandle(desc->GetSampler())
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003479 << " image view: " << report_data->FormatHandle(iv_state->image_view()) << ".";
Jeff Bolz165818a2020-05-08 11:19:03 -05003480 *error_msg = error_str.str();
3481 return false;
3482 }
3483 }
3484 } else {
3485 if (iv_state && (iv_state->samplerConversion != VK_NULL_HANDLE)) {
3486 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02738";
John Zulaufadb3f542019-06-04 17:01:00 -06003487 std::stringstream error_str;
Jeff Bolz165818a2020-05-08 11:19:03 -05003488 error_str << "Because dstSet (" << report_data->FormatHandle(update->dstSet)
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003489 << ") is bound to image view (" << report_data->FormatHandle(iv_state->image_view())
Jeff Bolz165818a2020-05-08 11:19:03 -05003490 << ") that includes a YCBCR conversion, it must have been allocated with a layout that "
3491 "includes an immutable sampler.";
John Zulaufadb3f542019-06-04 17:01:00 -06003492 *error_msg = error_str.str();
3493 return false;
3494 }
3495 }
Jeff Bolz165818a2020-05-08 11:19:03 -05003496 }
John Baumanda8abff2020-10-19 21:25:21 +00003497 // If there is an immutable sampler then |sampler| isn't used, so the following VU does not apply.
3498 if (sampler && !desc->IsImmutableSampler() && FormatIsMultiplane(image_state->createInfo.format)) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003499 // multiplane formats must be created with mutable format bit
3500 if (0 == (image_state->createInfo.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) {
3501 *error_code = "VUID-VkDescriptorImageInfo-sampler-01564";
John Zulaufadb3f542019-06-04 17:01:00 -06003502 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003503 error_str << "image " << report_data->FormatHandle(image_state->image())
Jeff Bolz165818a2020-05-08 11:19:03 -05003504 << " combined image sampler is a multi-planar "
3505 << "format and was not was not created with the VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT";
John Zulaufadb3f542019-06-04 17:01:00 -06003506 *error_msg = error_str.str();
3507 return false;
3508 }
Jeff Bolz165818a2020-05-08 11:19:03 -05003509 // image view need aspect mask for only the planes supported of format
3510 VkImageAspectFlags legal_aspect_flags = (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT);
3511 legal_aspect_flags |=
3512 (FormatPlaneCount(image_state->createInfo.format) == 3) ? VK_IMAGE_ASPECT_PLANE_2_BIT : 0;
3513 if (0 != (iv_state->create_info.subresourceRange.aspectMask & (~legal_aspect_flags))) {
3514 *error_code = "VUID-VkDescriptorImageInfo-sampler-01564";
3515 std::stringstream error_str;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003516 error_str << "image " << report_data->FormatHandle(image_state->image())
Jeff Bolz165818a2020-05-08 11:19:03 -05003517 << " combined image sampler is a multi-planar "
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06003518 << "format and " << report_data->FormatHandle(iv_state->image_view())
Jeff Bolz165818a2020-05-08 11:19:03 -05003519 << " aspectMask must only include " << string_VkImageAspectFlags(legal_aspect_flags);
3520 *error_msg = error_str.str();
3521 return false;
3522 }
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003523 }
Nathaniel Cesario23afadd2020-11-17 12:51:45 -07003524
3525 // Verify portability
3526 auto sampler_state = GetSamplerState(sampler);
3527 if (sampler_state) {
sfricke-samsung45996a42021-09-16 13:45:27 -07003528 if (IsExtEnabled(device_extensions.vk_khr_portability_subset)) {
Nathaniel Cesario23afadd2020-11-17 12:51:45 -07003529 if ((VK_FALSE == enabled_features.portability_subset_features.mutableComparisonSamplers) &&
3530 (VK_FALSE != sampler_state->createInfo.compareEnable)) {
3531 LogError(device, "VUID-VkDescriptorImageInfo-mutableComparisonSamplers-04450",
3532 "%s (portability error): sampler comparison not available.", func_name);
3533 }
3534 }
3535 }
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003536 }
John Zulaufadb3f542019-06-04 17:01:00 -06003537 }
3538 }
Mark Lobodzinskiac727772020-01-08 10:47:30 -07003539 // Fall through
John Zulaufadb3f542019-06-04 17:01:00 -06003540 case VK_DESCRIPTOR_TYPE_SAMPLER: {
3541 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003542 const auto *desc = static_cast<const Descriptor *>(dest_set->GetDescriptorFromGlobalIndex(index + di));
John Zulaufadb3f542019-06-04 17:01:00 -06003543 if (!desc->IsImmutableSampler()) {
John Zulaufc93c4252019-06-25 09:19:49 -06003544 if (!ValidateSampler(update->pImageInfo[di].sampler)) {
John Zulaufadb3f542019-06-04 17:01:00 -06003545 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
3546 std::stringstream error_str;
3547 error_str << "Attempted write update to sampler descriptor with invalid sampler: "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003548 << report_data->FormatHandle(update->pImageInfo[di].sampler) << ".";
John Zulaufadb3f542019-06-04 17:01:00 -06003549 *error_msg = error_str.str();
3550 return false;
3551 }
ziga-lunarg6c46b242021-09-13 18:33:37 +02003552 } else if (update->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER && !push) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003553 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02752";
3554 std::stringstream error_str;
3555 error_str << "Attempted write update to an immutable sampler descriptor.";
3556 *error_msg = error_str.str();
3557 return false;
John Zulaufadb3f542019-06-04 17:01:00 -06003558 }
3559 }
3560 break;
3561 }
3562 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
3563 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
3564 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
3565 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3566 auto image_view = update->pImageInfo[di].imageView;
3567 auto image_layout = update->pImageInfo[di].imageLayout;
Jeff Bolz165818a2020-05-08 11:19:03 -05003568 if (image_view) {
3569 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, func_name, error_code, error_msg)) {
3570 std::stringstream error_str;
3571 error_str << "Attempted write update to image descriptor failed due to: " << error_msg->c_str();
3572 *error_msg = error_str.str();
3573 return false;
3574 }
John Zulaufadb3f542019-06-04 17:01:00 -06003575 }
3576 }
3577 break;
3578 }
3579 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
3580 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
3581 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3582 auto buffer_view = update->pTexelBufferView[di];
Jeff Bolz165818a2020-05-08 11:19:03 -05003583 if (buffer_view) {
3584 auto bv_state = GetBufferViewState(buffer_view);
3585 if (!bv_state) {
3586 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
3587 std::stringstream error_str;
3588 error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: "
3589 << report_data->FormatHandle(buffer_view);
3590 *error_msg = error_str.str();
3591 return false;
3592 }
3593 auto buffer = bv_state->create_info.buffer;
3594 auto buffer_state = GetBufferState(buffer);
3595 // Verify that buffer underlying the view hasn't been destroyed prematurely
3596 if (!buffer_state) {
3597 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
3598 std::stringstream error_str;
3599 error_str << "Attempted write update to texel buffer descriptor failed because underlying buffer ("
3600 << report_data->FormatHandle(buffer) << ") has been destroyed: " << error_msg->c_str();
3601 *error_msg = error_str.str();
3602 return false;
3603 } else if (!cvdescriptorset::ValidateBufferUsage(report_data, buffer_state, update->descriptorType, error_code,
3604 error_msg)) {
3605 std::stringstream error_str;
3606 error_str << "Attempted write update to texel buffer descriptor failed due to: " << error_msg->c_str();
3607 *error_msg = error_str.str();
3608 return false;
3609 }
John Zulaufadb3f542019-06-04 17:01:00 -06003610 }
3611 }
3612 break;
3613 }
3614 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
3615 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
3616 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
3617 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
3618 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003619 if (update->pBufferInfo[di].buffer) {
3620 if (!ValidateBufferUpdate(update->pBufferInfo + di, update->descriptorType, func_name, error_code, error_msg)) {
3621 std::stringstream error_str;
3622 error_str << "Attempted write update to buffer descriptor failed due to: " << error_msg->c_str();
3623 *error_msg = error_str.str();
3624 return false;
3625 }
John Zulaufadb3f542019-06-04 17:01:00 -06003626 }
3627 }
3628 break;
3629 }
3630 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
3631 break;
Jeff Bolz95176d02020-04-01 00:36:16 -05003632 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07003633 const auto *acc_info = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureNV>(update->pNext);
Jeff Bolz95176d02020-04-01 00:36:16 -05003634 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003635 if (!ValidateAccelerationStructureUpdate(GetAccelerationStructureStateNV(acc_info->pAccelerationStructures[di]),
Mark Lobodzinski85ebd402020-12-03 12:56:07 -07003636 func_name, error_code, error_msg)) {
Jeff Bolz95176d02020-04-01 00:36:16 -05003637 std::stringstream error_str;
3638 error_str << "Attempted write update to acceleration structure descriptor failed due to: "
3639 << error_msg->c_str();
3640 *error_msg = error_str.str();
3641 return false;
3642 }
3643 }
3644
3645 } break;
sourav parmarcd5fb182020-07-17 12:58:44 -07003646 // KHR acceleration structures don't require memory to be bound manually to them.
3647 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
3648 break;
John Zulaufadb3f542019-06-04 17:01:00 -06003649 default:
3650 assert(0); // We've already verified update type so should never get here
3651 break;
3652 }
3653 // All checks passed so update contents are good
3654 return true;
3655}