blob: 511d80b0b3fb47efe922eff1ce18c2e27aa57cac [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)
Jeff Bolz6ae39612019-10-11 20:57:36 -0500332 : layout_(layout), 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,
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600340 const VkPhysicalDeviceInlineUniformBlockPropertiesEXT *inline_uniform_block_props, const DeviceExtensions *device_extensions) {
Tobin Ehlis154c2692016-10-25 09:36:53 -0600341 bool skip = false;
Jeremy Gebbencbf22862021-03-03 12:01:22 -0700342 layer_data::unordered_set<uint32_t> bindings;
John Zulauf0fdeab32018-01-23 11:27:35 -0700343 uint64_t total_descriptors = 0;
344
Mark Lobodzinski1f887d32020-12-30 15:31:33 -0700345 const auto *flags_create_info = LvlFindInChain<VkDescriptorSetLayoutBindingFlagsCreateInfo>(create_info->pNext);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500346
347 const bool push_descriptor_set = !!(create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR);
John Zulauf0fdeab32018-01-23 11:27:35 -0700348 if (push_descriptor_set && !push_descriptor_ext) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800349 skip |= val_obj->LogError(
350 val_obj->device, kVUID_Core_DrawState_ExtensionNotEnabled,
351 "vkCreateDescriptorSetLayout(): Attempted to use %s in %s but its required extension %s has not been enabled.\n",
352 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR", "VkDescriptorSetLayoutCreateInfo::flags",
353 VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
John Zulauf0fdeab32018-01-23 11:27:35 -0700354 }
355
Mike Schuchardt2df08912020-12-15 16:28:09 -0800356 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 -0500357 if (update_after_bind_set && !descriptor_indexing_ext) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800358 skip |= val_obj->LogError(
359 val_obj->device, kVUID_Core_DrawState_ExtensionNotEnabled,
360 "vkCreateDescriptorSetLayout(): Attemped to use %s in %s but its required extension %s has not been enabled.\n",
361 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT", "VkDescriptorSetLayoutCreateInfo::flags",
362 VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500363 }
364
John Zulauf0fdeab32018-01-23 11:27:35 -0700365 auto valid_type = [push_descriptor_set](const VkDescriptorType type) {
366 return !push_descriptor_set ||
Dave Houlton142c4cb2018-10-17 15:04:41 -0600367 ((type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) && (type != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) &&
Jeff Bolze54ae892018-09-08 12:16:29 -0500368 (type != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT));
John Zulauf0fdeab32018-01-23 11:27:35 -0700369 };
370
Jeff Bolzfdf96072018-04-10 14:32:18 -0500371 uint32_t max_binding = 0;
372
Tobin Ehlis154c2692016-10-25 09:36:53 -0600373 for (uint32_t i = 0; i < create_info->bindingCount; ++i) {
John Zulauf0fdeab32018-01-23 11:27:35 -0700374 const auto &binding_info = create_info->pBindings[i];
Jeff Bolzfdf96072018-04-10 14:32:18 -0500375 max_binding = std::max(max_binding, binding_info.binding);
376
John Zulauf0fdeab32018-01-23 11:27:35 -0700377 if (!bindings.insert(binding_info.binding).second) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700378 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-binding-00279",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800379 "vkCreateDescriptorSetLayout(): pBindings[%u] has duplicated binding number (%u).", i,
380 binding_info.binding);
Tobin Ehlis154c2692016-10-25 09:36:53 -0600381 }
John Zulauf0fdeab32018-01-23 11:27:35 -0700382 if (!valid_type(binding_info.descriptorType)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700383 skip |= val_obj->LogError(val_obj->device,
384 (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
385 ? "VUID-VkDescriptorSetLayoutCreateInfo-flags-02208"
386 : "VUID-VkDescriptorSetLayoutCreateInfo-flags-00280",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800387 "vkCreateDescriptorSetLayout(): pBindings[%u] has invalid type %s , for push descriptors.", i,
388 string_VkDescriptorType(binding_info.descriptorType));
John Zulauf0fdeab32018-01-23 11:27:35 -0700389 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500390
391 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
sfricke-samsungc1e27c32021-01-16 09:32:49 -0800392 if (!inline_uniform_block_features->inlineUniformBlock) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800393 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-04604",
394 "vkCreateDescriptorSetLayout(): pBindings[%u] is creating VkDescriptorSetLayout with "
395 "descriptor type VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT "
396 "but inlineUniformBlock is not enabled",
397 i, VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME);
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600398 } else {
399 if ((binding_info.descriptorCount % 4) != 0) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800400 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-02209",
401 "vkCreateDescriptorSetLayout(): pBindings[%u] has descriptorCount =(%" PRIu32
402 ") but must be a multiple of 4",
403 i, binding_info.descriptorCount);
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600404 }
405 if (binding_info.descriptorCount > inline_uniform_block_props->maxInlineUniformBlockSize) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700406 skip |=
407 val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBinding-descriptorType-02210",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800408 "vkCreateDescriptorSetLayout(): pBindings[%u] has descriptorCount =(%" PRIu32
409 ") but must be less than or equal to maxInlineUniformBlockSize (%u)",
410 i, binding_info.descriptorCount, inline_uniform_block_props->maxInlineUniformBlockSize);
Tony-LunarGd6744bc2019-08-23 09:57:10 -0600411 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500412 }
413 }
414
Tony-LunarG7337b312020-04-15 16:40:25 -0600415 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
416 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
417 binding_info.pImmutableSamplers && device_extensions->vk_ext_custom_border_color) {
418 const CoreChecks *core_checks = reinterpret_cast<const CoreChecks *>(val_obj);
419 for (uint32_t j = 0; j < binding_info.descriptorCount; j++) {
420 const SAMPLER_STATE *sampler_state = core_checks->GetSamplerState(binding_info.pImmutableSamplers[j]);
421 if (sampler_state && (sampler_state->createInfo.borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT ||
422 sampler_state->createInfo.borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT)) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800423 skip |= val_obj->LogError(
424 val_obj->device, "VUID-VkDescriptorSetLayoutBinding-pImmutableSamplers-04009",
425 "vkCreateDescriptorSetLayout(): pBindings[%u].pImmutableSamplers[%u] has VkSampler %" PRIu64
426 " presented as immutable has a custom border color",
427 i, j, binding_info.pImmutableSamplers[j]);
Tony-LunarG7337b312020-04-15 16:40:25 -0600428 }
429 }
430 }
431
John Zulauf0fdeab32018-01-23 11:27:35 -0700432 total_descriptors += binding_info.descriptorCount;
Tobin Ehlis154c2692016-10-25 09:36:53 -0600433 }
John Zulauf0fdeab32018-01-23 11:27:35 -0700434
Jeff Bolzfdf96072018-04-10 14:32:18 -0500435 if (flags_create_info) {
436 if (flags_create_info->bindingCount != 0 && flags_create_info->bindingCount != create_info->bindingCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700437 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-bindingCount-03002",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800438 "vkCreateDescriptorSetLayout(): VkDescriptorSetLayoutCreateInfo::bindingCount (%d) != "
Mike Schuchardt2df08912020-12-15 16:28:09 -0800439 "VkDescriptorSetLayoutBindingFlagsCreateInfo::bindingCount (%d)",
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700440 create_info->bindingCount, flags_create_info->bindingCount);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500441 }
442
443 if (flags_create_info->bindingCount == create_info->bindingCount) {
444 for (uint32_t i = 0; i < create_info->bindingCount; ++i) {
445 const auto &binding_info = create_info->pBindings[i];
446
Mike Schuchardt2df08912020-12-15 16:28:09 -0800447 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT) {
Jeff Bolzfdf96072018-04-10 14:32:18 -0500448 if (!update_after_bind_set) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700449 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-flags-03000",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800450 "vkCreateDescriptorSetLayout(): pBindings[%u] does not have "
451 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT.",
452 i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500453 }
454
455 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700456 !core12_features->descriptorBindingUniformBufferUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800457 skip |= val_obj->LogError(
458 val_obj->device,
459 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
460 "descriptorBindingUniformBufferUpdateAfterBind-03005",
461 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
462 "for %s since descriptorBindingUniformBufferUpdateAfterBind is not enabled.",
463 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500464 }
465 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
466 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
467 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700468 !core12_features->descriptorBindingSampledImageUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800469 skip |= val_obj->LogError(
470 val_obj->device,
471 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
472 "descriptorBindingSampledImageUpdateAfterBind-03006",
473 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
474 "for %s since descriptorBindingSampledImageUpdateAfterBind is not enabled.",
475 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500476 }
477 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700478 !core12_features->descriptorBindingStorageImageUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800479 skip |= val_obj->LogError(
480 val_obj->device,
481 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
482 "descriptorBindingStorageImageUpdateAfterBind-03007",
483 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
484 "for %s since descriptorBindingStorageImageUpdateAfterBind is not enabled.",
485 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500486 }
487 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700488 !core12_features->descriptorBindingStorageBufferUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800489 skip |= val_obj->LogError(
490 val_obj->device,
491 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
492 "descriptorBindingStorageBufferUpdateAfterBind-03008",
493 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
494 "for %s since descriptorBindingStorageBufferUpdateAfterBind is not enabled.",
495 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500496 }
497 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700498 !core12_features->descriptorBindingUniformTexelBufferUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800499 skip |= val_obj->LogError(
500 val_obj->device,
501 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
502 "descriptorBindingUniformTexelBufferUpdateAfterBind-03009",
503 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
504 "for %s since descriptorBindingUniformTexelBufferUpdateAfterBind is not enabled.",
505 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500506 }
507 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER &&
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700508 !core12_features->descriptorBindingStorageTexelBufferUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800509 skip |= val_obj->LogError(
510 val_obj->device,
511 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
512 "descriptorBindingStorageTexelBufferUpdateAfterBind-03010",
513 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
514 "for %s since descriptorBindingStorageTexelBufferUpdateAfterBind is not enabled.",
515 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500516 }
517 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ||
518 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
519 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700520 skip |= val_obj->LogError(val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-None-03011",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800521 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have "
522 "VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT for %s.",
523 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500524 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500525
526 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT &&
527 !inline_uniform_block_features->descriptorBindingInlineUniformBlockUpdateAfterBind) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800528 skip |= val_obj->LogError(
529 val_obj->device,
530 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-"
531 "descriptorBindingInlineUniformBlockUpdateAfterBind-02211",
532 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT "
533 "for %s since descriptorBindingInlineUniformBlockUpdateAfterBind is not enabled.",
534 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolze54ae892018-09-08 12:16:29 -0500535 }
Jeff Bolzfdf96072018-04-10 14:32:18 -0500536 }
537
Mike Schuchardt2df08912020-12-15 16:28:09 -0800538 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT) {
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700539 if (!core12_features->descriptorBindingUpdateUnusedWhilePending) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700540 skip |= val_obj->LogError(
541 val_obj->device,
Mike Schuchardt65847d92019-12-20 13:50:47 -0800542 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingUpdateUnusedWhilePending-03012",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800543 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have "
544 "VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT for %s since "
545 "descriptorBindingUpdateUnusedWhilePending is not enabled.",
546 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500547 }
548 }
549
Mike Schuchardt2df08912020-12-15 16:28:09 -0800550 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT) {
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700551 if (!core12_features->descriptorBindingPartiallyBound) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700552 skip |= val_obj->LogError(
553 val_obj->device,
554 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingPartiallyBound-03013",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800555 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT for "
556 "%s since descriptorBindingPartiallyBound is not enabled.",
557 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500558 }
559 }
560
Mike Schuchardt2df08912020-12-15 16:28:09 -0800561 if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT) {
Jeff Bolzfdf96072018-04-10 14:32:18 -0500562 if (binding_info.binding != max_binding) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800563 skip |= val_obj->LogError(
564 val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03004",
565 "vkCreateDescriptorSetLayout(): pBindings[%u] has VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT "
566 "but %u is the largest value of all the bindings.",
567 i, binding_info.binding);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500568 }
569
Piers Daniell41b8c5d2020-01-10 15:42:00 -0700570 if (!core12_features->descriptorBindingVariableDescriptorCount) {
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-descriptorBindingVariableDescriptorCount-03014",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800574 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have "
575 "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT for %s since "
576 "descriptorBindingVariableDescriptorCount is not enabled.",
577 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500578 }
sfricke-samsung4ba7d6e2021-03-06 20:56:35 -0800579 if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
580 (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700581 skip |= val_obj->LogError(val_obj->device,
582 "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03015",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800583 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have "
584 "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT for %s.",
585 i, string_VkDescriptorType(binding_info.descriptorType));
Jeff Bolzfdf96072018-04-10 14:32:18 -0500586 }
587 }
588
589 if (push_descriptor_set &&
590 (flags_create_info->pBindingFlags[i] &
Mike Schuchardt2df08912020-12-15 16:28:09 -0800591 (VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT |
592 VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT))) {
sfricke-samsungbda4a852021-03-06 20:58:01 -0800593 skip |= val_obj->LogError(
594 val_obj->device, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-flags-03003",
595 "vkCreateDescriptorSetLayout(): pBindings[%u] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT, "
596 "VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, or "
597 "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT for with "
598 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR.",
599 i);
Jeff Bolzfdf96072018-04-10 14:32:18 -0500600 }
601 }
602 }
603 }
604
John Zulauf0fdeab32018-01-23 11:27:35 -0700605 if ((push_descriptor_set) && (total_descriptors > max_push_descriptors)) {
606 const char *undefined = push_descriptor_ext ? "" : " -- undefined";
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700607 skip |= val_obj->LogError(
608 val_obj->device, "VUID-VkDescriptorSetLayoutCreateInfo-flags-00281",
sfricke-samsungbda4a852021-03-06 20:58:01 -0800609 "vkCreateDescriptorSetLayout(): for push descriptor, total descriptor count in layout (%" PRIu64
Mark Lobodzinskid18de902020-01-15 12:20:37 -0700610 ") must not be greater than VkPhysicalDevicePushDescriptorPropertiesKHR::maxPushDescriptors (%" PRIu32 "%s).",
611 total_descriptors, max_push_descriptors, undefined);
John Zulauf0fdeab32018-01-23 11:27:35 -0700612 }
613
Tobin Ehlis154c2692016-10-25 09:36:53 -0600614 return skip;
615}
616
Mark Lobodzinskie12b6e32020-06-29 11:44:15 -0600617void cvdescriptorset::AllocateDescriptorSetsData::Init(uint32_t count) {
618 layout_nodes.resize(count);
Mark Lobodzinskie12b6e32020-06-29 11:44:15 -0600619}
Tobin Ehlis68d0adf2016-06-01 11:33:50 -0600620
Jeff Bolz41a1ced2019-10-11 11:40:49 -0500621cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, DESCRIPTOR_POOL_STATE *pool_state,
Jeff Bolzfdf96072018-04-10 14:32:18 -0500622 const std::shared_ptr<DescriptorSetLayout const> &layout, uint32_t variable_count,
John Zulaufd2c3dae2019-12-12 11:02:17 -0700623 const cvdescriptorset::DescriptorSet::StateTracker *state_data)
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -0700624 : some_update_(false),
625 set_(set),
Jeff Bolz41a1ced2019-10-11 11:40:49 -0500626 pool_state_(pool_state),
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700627 layout_(layout),
John Zulaufd2c3dae2019-12-12 11:02:17 -0700628 state_data_(state_data),
Jeff Bolzdd4cfa12019-08-11 20:57:51 -0500629 variable_count_(variable_count),
630 change_count_(0) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600631 // Foreach binding, create default descriptors of given type
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700632 descriptors_.reserve(layout_->GetTotalDescriptorCount());
633 descriptor_store_.resize(layout_->GetTotalDescriptorCount());
John Zulaufe4850d42019-12-30 16:10:55 -0700634 auto free_descriptor = descriptor_store_.data();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700635 for (uint32_t i = 0; i < layout_->GetBindingCount(); ++i) {
636 auto type = layout_->GetTypeFromIndex(i);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600637 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700638 case VK_DESCRIPTOR_TYPE_SAMPLER: {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700639 auto immut_sampler = layout_->GetImmutableSamplerPtrFromIndex(i);
640 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
Tobin Ehlis082c7512017-05-08 11:24:57 -0600641 if (immut_sampler) {
John Zulaufe4850d42019-12-30 16:10:55 -0700642 descriptors_.emplace_back(new ((free_descriptor++)->Sampler())
643 SamplerDescriptor(state_data, immut_sampler + di));
Tobin Ehlis082c7512017-05-08 11:24:57 -0600644 some_update_ = true; // Immutable samplers are updated at creation
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700645 } else {
John Zulaufe4850d42019-12-30 16:10:55 -0700646 descriptors_.emplace_back(new ((free_descriptor++)->Sampler()) SamplerDescriptor(state_data, nullptr));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700647 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700648 }
649 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600650 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700651 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700652 auto immut = layout_->GetImmutableSamplerPtrFromIndex(i);
653 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
Tobin Ehlis082c7512017-05-08 11:24:57 -0600654 if (immut) {
John Zulaufe4850d42019-12-30 16:10:55 -0700655 descriptors_.emplace_back(new ((free_descriptor++)->ImageSampler())
656 ImageSamplerDescriptor(state_data, immut + di));
Tobin Ehlis082c7512017-05-08 11:24:57 -0600657 some_update_ = true; // Immutable samplers are updated at creation
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700658 } else {
John Zulaufe4850d42019-12-30 16:10:55 -0700659 descriptors_.emplace_back(new ((free_descriptor++)->ImageSampler())
660 ImageSamplerDescriptor(state_data, nullptr));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700661 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700662 }
663 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600664 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700665 // ImageDescriptors
666 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
667 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
668 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700669 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700670 descriptors_.emplace_back(new ((free_descriptor++)->Image()) ImageDescriptor(type));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700671 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700672 break;
673 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
674 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700675 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700676 descriptors_.emplace_back(new ((free_descriptor++)->Texel()) TexelDescriptor(type));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700677 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700678 break;
sfricke-samsung4ca35652021-03-05 02:22:10 -0800679 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
680 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
681 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700682 descriptors_.emplace_back(new ((free_descriptor++)->Buffer()) BufferDescriptor(type));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700683 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700684 break;
Jeff Bolze54ae892018-09-08 12:16:29 -0500685 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700686 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700687 descriptors_.emplace_back(new ((free_descriptor++)->InlineUniform()) InlineUniformDescriptor(type));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700688 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500689 break;
Eric Werness30127fd2018-10-31 21:01:03 -0700690 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
sourav parmarcd5fb182020-07-17 12:58:44 -0700691 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700692 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
John Zulaufe4850d42019-12-30 16:10:55 -0700693 descriptors_.emplace_back(new ((free_descriptor++)->AccelerationStructure())
694 AccelerationStructureDescriptor(type));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700695 }
Jeff Bolzfbe51582018-09-13 10:01:35 -0500696 break;
Tony-LunarGf563b362021-03-18 16:13:18 -0600697 case VK_DESCRIPTOR_TYPE_MUTABLE_VALVE:
698 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
699 descriptors_.emplace_back(new ((free_descriptor++)->InlineUniform()) MutableDescriptor());
700 }
701 break;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700702 default:
sfricke-samsung60f29ec2021-03-10 20:37:25 -0800703 if (IsDynamicDescriptor(type) && IsBufferDescriptor(type)) {
704 for (uint32_t di = 0; di < layout_->GetDescriptorCountFromIndex(i); ++di) {
705 dynamic_offset_idx_to_descriptor_list_.push_back(descriptors_.size());
706 descriptors_.emplace_back(new ((free_descriptor++)->Buffer()) BufferDescriptor(type));
707 }
708 } else {
709 assert(0); // Bad descriptor type specified
710 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700711 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600712 }
713 }
714}
Tobin Ehlis56a30942016-05-19 08:00:00 -0600715
Jeff Bolz41a1ced2019-10-11 11:40:49 -0500716cvdescriptorset::DescriptorSet::~DescriptorSet() {}
Chris Forbes57989132016-07-26 17:06:10 +1200717
Shannon McPhersonc06c33d2018-06-28 17:21:12 -0600718static std::string StringDescriptorReqViewType(descriptor_req req) {
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700719 std::string result("");
Mark Lobodzinski29f451a2020-02-10 16:15:30 -0700720 for (unsigned i = 0; i <= VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; i++) {
Chris Forbes57989132016-07-26 17:06:10 +1200721 if (req & (1 << i)) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700722 if (result.size()) result += ", ";
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700723 result += string_VkImageViewType(VkImageViewType(i));
Chris Forbes57989132016-07-26 17:06:10 +1200724 }
725 }
726
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700727 if (!result.size()) result = "(none)";
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700728
729 return result;
Chris Forbes57989132016-07-26 17:06:10 +1200730}
731
Chris Forbesda01e8d2018-08-27 15:36:57 -0700732static char const *StringDescriptorReqComponentType(descriptor_req req) {
733 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_SINT) return "SINT";
734 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_UINT) return "UINT";
735 if (req & DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT) return "FLOAT";
736 return "(none)";
737}
738
Jeff Bolz6cede832019-08-09 23:30:39 -0500739unsigned DescriptorRequirementsBitsFromFormat(VkFormat fmt) {
Chris Forbesda01e8d2018-08-27 15:36:57 -0700740 if (FormatIsSInt(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_SINT;
741 if (FormatIsUInt(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_UINT;
742 if (FormatIsDepthAndStencil(fmt)) return DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT | DESCRIPTOR_REQ_COMPONENT_TYPE_UINT;
743 if (fmt == VK_FORMAT_UNDEFINED) return 0;
744 // everything else -- UNORM/SNORM/FLOAT/USCALED/SSCALED is all float in the shader.
745 return DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT;
746}
747
Tobin Ehlis3066db62016-08-22 08:12:23 -0600748// 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 -0600749// This includes validating that all descriptors in the given bindings are updated,
750// that any update buffers are valid, and that any dynamic offsets are within the bounds of their buffers.
751// Return true if state is acceptable, or false and write an error message into error string
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600752bool CoreChecks::ValidateDrawState(const DescriptorSet *descriptor_set, const BindingReqMap &bindings,
753 const std::vector<uint32_t> &dynamic_offsets, const CMD_BUFFER_STATE *cb_node,
locke-lunargfc78e932020-11-19 17:06:24 -0700754 const std::vector<IMAGE_VIEW_STATE *> *attachments, const std::vector<SUBPASS_INFO> &subpasses,
755 const char *caller, const DrawDispatchVuid &vuids) const {
Karl Schultz2171f932021-03-19 10:47:01 -0600756 Optional<layer_data::unordered_map<VkImageView, VkImageLayout>> checked_layouts;
757 if (descriptor_set->GetTotalDescriptorCount() > cvdescriptorset::PrefilterBindRequestMap::kManyDescriptors_) {
758 checked_layouts.emplace();
759 }
Tony-LunarGace473a2020-05-06 12:48:04 -0600760 bool result = false;
locke-lunarg540b2252020-08-03 13:23:36 -0600761 VkFramebuffer framebuffer = cb_node->activeFramebuffer ? cb_node->activeFramebuffer->framebuffer : VK_NULL_HANDLE;
John Zulauf79f06582021-02-27 18:38:39 -0700762 for (const auto &binding_pair : bindings) {
763 const auto binding = binding_pair.first;
John Zulauf382e1912019-06-10 15:27:44 -0600764 DescriptorSetLayout::ConstBindingIterator binding_it(descriptor_set->GetLayout().get(), binding);
765 if (binding_it.AtEnd()) { // End at construction is the condition for an invalid binding.
Tony-LunarGace473a2020-05-06 12:48:04 -0600766 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600767 result |= LogError(set, vuids.descriptor_valid,
Tony-LunarGace473a2020-05-06 12:48:04 -0600768 "%s encountered the following validation error at %s time: Attempting to "
769 "validate DrawState for binding #%u which is an invalid binding for this descriptor set.",
770 report_data->FormatHandle(set).c_str(), caller, binding);
771 return result;
Tobin Ehlis58c59582016-06-21 12:34:33 -0600772 }
Jeff Bolz6cede832019-08-09 23:30:39 -0500773
774 if (binding_it.GetDescriptorBindingFlags() &
Mike Schuchardt2df08912020-12-15 16:28:09 -0800775 (VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT)) {
Jeff Bolz6cede832019-08-09 23:30:39 -0500776 // Can't validate the descriptor because it may not have been updated,
777 // or the view could have been destroyed
778 continue;
779 }
John Zulauf81dd1f12021-01-26 16:49:16 -0700780 // // This is a record time only path
781 const bool record_time_validate = true;
locke-lunargfc78e932020-11-19 17:06:24 -0700782 result |= ValidateDescriptorSetBindingData(cb_node, descriptor_set, dynamic_offsets, binding_pair, framebuffer, attachments,
Karl Schultz2171f932021-03-19 10:47:01 -0600783 subpasses, record_time_validate, caller, vuids, checked_layouts);
unknown3087a642019-09-26 17:21:05 -0600784 }
Tony-LunarGace473a2020-05-06 12:48:04 -0600785 return result;
unknown3087a642019-09-26 17:21:05 -0600786}
Jeff Bolz6cede832019-08-09 23:30:39 -0500787
locke-lunargb8be8222020-10-20 00:34:37 -0600788bool CoreChecks::ValidateDescriptorSetBindingData(const CMD_BUFFER_STATE *cb_node, const DescriptorSet *descriptor_set,
789 const std::vector<uint32_t> &dynamic_offsets,
John Zulauf79f06582021-02-27 18:38:39 -0700790 const std::pair<const uint32_t, DescriptorRequirement> &binding_info,
Mark Lobodzinski85ebd402020-12-03 12:56:07 -0700791 VkFramebuffer framebuffer, const std::vector<IMAGE_VIEW_STATE *> *attachments,
John Zulauf81dd1f12021-01-26 16:49:16 -0700792 const std::vector<SUBPASS_INFO> &subpasses, bool record_time_validate,
Karl Schultz2171f932021-03-19 10:47:01 -0600793 const char *caller, const DrawDispatchVuid &vuids,
794 Optional<layer_data::unordered_map<VkImageView, VkImageLayout>> &checked_layouts) const {
unknown3087a642019-09-26 17:21:05 -0600795 using DescriptorClass = cvdescriptorset::DescriptorClass;
796 using BufferDescriptor = cvdescriptorset::BufferDescriptor;
797 using ImageDescriptor = cvdescriptorset::ImageDescriptor;
798 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
799 using SamplerDescriptor = cvdescriptorset::SamplerDescriptor;
800 using TexelDescriptor = cvdescriptorset::TexelDescriptor;
Jeff Bolz95176d02020-04-01 00:36:16 -0500801 using AccelerationStructureDescriptor = cvdescriptorset::AccelerationStructureDescriptor;
locke-lunarg36045992020-08-20 16:54:37 -0600802 const auto reqs = binding_info.second.reqs;
803 const auto binding = binding_info.first;
unknown3087a642019-09-26 17:21:05 -0600804 DescriptorSetLayout::ConstBindingIterator binding_it(descriptor_set->GetLayout().get(), binding);
805 {
John Zulauf382e1912019-06-10 15:27:44 -0600806 // Copy the range, the end range is subject to update based on variable length descriptor arrays.
807 cvdescriptorset::IndexRange index_range = binding_it.GetGlobalIndexRange();
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700808 auto array_idx = 0; // Track array idx if we're dealing with array descriptors
Jeff Bolzfdf96072018-04-10 14:32:18 -0500809
John Zulauf382e1912019-06-10 15:27:44 -0600810 if (binding_it.IsVariableDescriptorCount()) {
Jeff Bolzfdf96072018-04-10 14:32:18 -0500811 // Only validate the first N descriptors if it uses variable_count
John Zulauf382e1912019-06-10 15:27:44 -0600812 index_range.end = index_range.start + descriptor_set->GetVariableDescriptorCount();
Jeff Bolzfdf96072018-04-10 14:32:18 -0500813 }
814
John Zulaufc483f442017-12-15 14:02:06 -0700815 for (uint32_t i = index_range.start; i < index_range.end; ++i, ++array_idx) {
Lockeb994adf2019-03-29 23:52:31 -0600816 uint32_t index = i - index_range.start;
John Zulauf382e1912019-06-10 15:27:44 -0600817 const auto *descriptor = descriptor_set->GetDescriptorFromGlobalIndex(i);
Jeremy Gebben550ebbd2021-03-11 05:04:52 -0700818 const auto descriptor_class = descriptor->GetClass();
Lockeb994adf2019-03-29 23:52:31 -0600819
Jeremy Gebben550ebbd2021-03-11 05:04:52 -0700820 if (descriptor_class == DescriptorClass::InlineUniform) {
Jeff Bolz6cede832019-08-09 23:30:39 -0500821 // Can't validate the descriptor because it may not have been updated.
Jeff Bolzfdf96072018-04-10 14:32:18 -0500822 continue;
John Zulauf382e1912019-06-10 15:27:44 -0600823 } else if (!descriptor->updated) {
Tony-LunarGace473a2020-05-06 12:48:04 -0600824 auto set = descriptor_set->GetSet();
sfricke-samsungbda4a852021-03-06 20:58:01 -0800825 return LogError(
826 set, vuids.descriptor_valid,
827 "Descriptor set %s encountered the following validation error at %s time: Descriptor in binding #%" PRIu32
828 " index %" PRIu32
829 " is being used in draw but has never been updated via vkUpdateDescriptorSets() or a similar call.",
830 report_data->FormatHandle(set).c_str(), caller, binding, index);
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700831 } else {
John Zulaufc93c4252019-06-25 09:19:49 -0600832 if (descriptor_class == DescriptorClass::GeneralBuffer) {
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700833 // Verify that buffers are valid
John Zulauf382e1912019-06-10 15:27:44 -0600834 auto buffer = static_cast<const BufferDescriptor *>(descriptor)->GetBuffer();
Jeff Bolzfaffeb32019-10-04 12:47:16 -0500835 auto buffer_node = static_cast<const BufferDescriptor *>(descriptor)->GetBufferState();
Karl Schultz76d16a42020-11-11 05:05:33 -0700836 if ((!buffer_node && !enabled_features.robustness2_features.nullDescriptor) ||
837 (buffer_node && buffer_node->destroyed)) {
838 auto set = descriptor_set->GetSet();
839 return LogError(set, vuids.descriptor_valid,
sfricke-samsungbda4a852021-03-06 20:58:01 -0800840 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
Karl Schultz76d16a42020-11-11 05:05:33 -0700841 "binding #%" PRIu32 " index %" PRIu32
842 " is using buffer %s that is invalid or has been destroyed.",
843 report_data->FormatHandle(set).c_str(), caller, binding, index,
844 report_data->FormatHandle(buffer).c_str());
845 }
Jeff Bolz165818a2020-05-08 11:19:03 -0500846 if (buffer) {
Karl Schultz76d16a42020-11-11 05:05:33 -0700847 if (!buffer_node->sparse) {
John Zulauf79f06582021-02-27 18:38:39 -0700848 for (const auto *mem_binding : buffer_node->GetBoundMemory()) {
Jeff Bolz165818a2020-05-08 11:19:03 -0500849 if (mem_binding->destroyed) {
850 auto set = descriptor_set->GetSet();
sfricke-samsungbda4a852021-03-06 20:58:01 -0800851 return LogError(
852 set, vuids.descriptor_valid,
853 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
854 "binding #%" PRIu32 " index %" PRIu32
855 " is uses buffer %s that references invalid memory %s.",
856 report_data->FormatHandle(set).c_str(), caller, binding, index,
857 report_data->FormatHandle(buffer).c_str(),
858 report_data->FormatHandle(mem_binding->mem).c_str());
Jeff Bolz165818a2020-05-08 11:19:03 -0500859 }
Tobin Ehlisc8266452017-04-07 12:20:30 -0600860 }
861 }
locke-lunarg351c9d82020-10-23 14:43:21 -0600862 if (enabled_features.core11.protectedMemory == VK_TRUE) {
863 if (ValidateProtectedBuffer(cb_node, buffer_node, caller, vuids.unprotected_command_buffer,
864 "Buffer is in a descriptorSet")) {
865 return true;
866 }
867 if (binding_info.second.is_writable &&
868 ValidateUnprotectedBuffer(cb_node, buffer_node, caller, vuids.protected_command_buffer,
869 "Buffer is in a descriptorSet")) {
870 return true;
871 }
872 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700873 }
John Zulaufc93c4252019-06-25 09:19:49 -0600874 } else if (descriptor_class == DescriptorClass::ImageSampler || descriptor_class == DescriptorClass::Image) {
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700875 VkImageView image_view;
876 VkImageLayout image_layout;
Jeff Bolzfaffeb32019-10-04 12:47:16 -0500877 const IMAGE_VIEW_STATE *image_view_state;
locke-lunarg4e1e4632020-10-26 01:52:19 -0600878 std::vector<const SAMPLER_STATE *> sampler_states;
locke-lunarg36045992020-08-20 16:54:37 -0600879
John Zulaufc93c4252019-06-25 09:19:49 -0600880 if (descriptor_class == DescriptorClass::ImageSampler) {
locke-lunarg36045992020-08-20 16:54:37 -0600881 const ImageSamplerDescriptor *image_descriptor = static_cast<const ImageSamplerDescriptor *>(descriptor);
882 image_view = image_descriptor->GetImageView();
883 image_view_state = image_descriptor->GetImageViewState();
884 image_layout = image_descriptor->GetImageLayout();
locke-lunarg4e1e4632020-10-26 01:52:19 -0600885 sampler_states.emplace_back(image_descriptor->GetSamplerState());
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700886 } else {
locke-lunarg36045992020-08-20 16:54:37 -0600887 const ImageDescriptor *image_descriptor = static_cast<const ImageDescriptor *>(descriptor);
888 image_view = image_descriptor->GetImageView();
889 image_view_state = image_descriptor->GetImageViewState();
890 image_layout = image_descriptor->GetImageLayout();
locke-lunarg4e1e4632020-10-26 01:52:19 -0600891
892 if (binding_info.second.samplers_used_by_image.size() > index) {
893 for (auto &sampler : binding_info.second.samplers_used_by_image[index]) {
Nathaniel Cesarioaa8dd222021-02-17 23:45:11 -0700894 // NOTE: This check _shouldn't_ be necessary due to the checks made in IsSpecificDescriptorType in
895 // shader_validation.cpp. However, without this check some traces still crash.
896 if (sampler.second &&
897 (sampler.second->GetClass() == cvdescriptorset::DescriptorClass::PlainSampler)) {
locke-lunarg4e1e4632020-10-26 01:52:19 -0600898 const auto *sampler_state =
899 static_cast<const cvdescriptorset::SamplerDescriptor *>(sampler.second)->GetSamplerState();
900 if (sampler_state) sampler_states.emplace_back(sampler_state);
901 }
902 }
903 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700904 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700905
Karl Schultz76d16a42020-11-11 05:05:33 -0700906 if ((!image_view_state && !enabled_features.robustness2_features.nullDescriptor) ||
907 (image_view_state && image_view_state->destroyed)) {
908 // Image view must have been destroyed since initial update. Could potentially flag the descriptor
909 // as "invalid" (updated = false) at DestroyImageView() time and detect this error at bind time
910
911 auto set = descriptor_set->GetSet();
912 return LogError(set, vuids.descriptor_valid,
sfricke-samsungbda4a852021-03-06 20:58:01 -0800913 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
Karl Schultz76d16a42020-11-11 05:05:33 -0700914 "binding #%" PRIu32 " index %" PRIu32
915 " is using imageView %s that is invalid or has been destroyed.",
916 report_data->FormatHandle(set).c_str(), caller, binding, index,
917 report_data->FormatHandle(image_view).c_str());
918 }
Jeff Bolz165818a2020-05-08 11:19:03 -0500919 if (image_view) {
Jeff Bolz165818a2020-05-08 11:19:03 -0500920 const auto &image_view_ci = image_view_state->create_info;
locke-lunarg4e1e4632020-10-26 01:52:19 -0600921 const auto *image_state = image_view_state->image_state.get();
922
Jeff Bolz165818a2020-05-08 11:19:03 -0500923 if (reqs & DESCRIPTOR_REQ_ALL_VIEW_TYPE_BITS) {
924 if (~reqs & (1 << image_view_ci.viewType)) {
925 auto set = descriptor_set->GetSet();
926 return LogError(
locke-lunarg1328e8e2020-08-20 12:40:08 -0600927 set, vuids.descriptor_valid,
sfricke-samsungbda4a852021-03-06 20:58:01 -0800928 "Descriptor set %s encountered the following validation error at %s time: Descriptor "
Jeff Bolz165818a2020-05-08 11:19:03 -0500929 "in binding #%" PRIu32 " index %" PRIu32 " requires an image view of type %s but got %s.",
930 report_data->FormatHandle(set).c_str(), caller, binding, index,
931 StringDescriptorReqViewType(reqs).c_str(), string_VkImageViewType(image_view_ci.viewType));
932 }
933
934 if (!(reqs & image_view_state->descriptor_format_bits)) {
935 // bad component type
936 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -0600937 return LogError(set, vuids.descriptor_valid,
sfricke-samsungbda4a852021-03-06 20:58:01 -0800938 "Descriptor set %s encountered the following validation error at %s time: "
939 "Descriptor in binding "
Jeff Bolz165818a2020-05-08 11:19:03 -0500940 "#%" PRIu32 " index %" PRIu32
941 " requires %s component type, but bound descriptor format is %s.",
942 report_data->FormatHandle(set).c_str(), caller, binding, index,
943 StringDescriptorReqComponentType(reqs), string_VkFormat(image_view_ci.format));
944 }
945 }
946
John Zulauf81dd1f12021-01-26 16:49:16 -0700947 // NOTE: Submit time validation of UPDATE_AFTER_BIND image layout is not possible with the
948 // image layout tracking as currently implemented, so only record_time_validation is done
949 if (!disabled[image_layout_validation] && record_time_validate) {
Jeff Bolz165818a2020-05-08 11:19:03 -0500950 auto image_node = image_view_state->image_state.get();
951 assert(image_node);
952 // Verify Image Layout
953 // No "invalid layout" VUID required for this call, since the optimal_layout parameter is UNDEFINED.
Karl Schultz2171f932021-03-19 10:47:01 -0600954 // The caller provides a checked_layouts map when there are a large number of layouts to check,
955 // making it worthwhile to keep track of verified layouts and not recheck them.
956 bool already_validated = false;
957 if (checked_layouts) {
958 auto search = checked_layouts->find(image_view);
959 if (search != checked_layouts->end() && search->second == image_layout) {
960 already_validated = true;
961 }
962 }
963 if (!already_validated) {
964 bool hit_error = false;
965 VerifyImageLayout(cb_node, image_node, image_view_state->normalized_subresource_range,
966 image_view_ci.subresourceRange.aspectMask, image_layout, VK_IMAGE_LAYOUT_UNDEFINED,
967 caller, kVUIDUndefined, "VUID-VkDescriptorImageInfo-imageLayout-00344", &hit_error);
968 if (hit_error) {
969 auto set = descriptor_set->GetSet();
970 return LogError(
971 set, vuids.descriptor_valid,
972 "Descriptor set %s encountered the following validation error at %s time: Image layout "
973 "specified "
974 "at vkUpdateDescriptorSet* or vkCmdPushDescriptorSet* time "
975 "doesn't match actual image layout at time descriptor is used. See previous error callback for "
976 "specific details.",
977 report_data->FormatHandle(set).c_str(), caller);
978 }
979 if (checked_layouts) {
980 checked_layouts->emplace(image_view, image_layout);
981 }
Jeff Bolz165818a2020-05-08 11:19:03 -0500982 }
983 }
984
985 // Verify Sample counts
986 if ((reqs & DESCRIPTOR_REQ_SINGLE_SAMPLE) && image_view_state->samples != VK_SAMPLE_COUNT_1_BIT) {
987 auto set = descriptor_set->GetSet();
sfricke-samsungbda4a852021-03-06 20:58:01 -0800988 return LogError(
989 set, vuids.descriptor_valid,
990 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
991 "binding #%" PRIu32 " index %" PRIu32
992 " requires bound image to have VK_SAMPLE_COUNT_1_BIT but got %s.",
993 report_data->FormatHandle(set).c_str(), caller, binding, index,
994 string_VkSampleCountFlagBits(image_view_state->samples));
Jeff Bolz165818a2020-05-08 11:19:03 -0500995 }
996 if ((reqs & DESCRIPTOR_REQ_MULTI_SAMPLE) && image_view_state->samples == VK_SAMPLE_COUNT_1_BIT) {
Tony-LunarGace473a2020-05-06 12:48:04 -0600997 auto set = descriptor_set->GetSet();
sfricke-samsungbda4a852021-03-06 20:58:01 -0800998 return LogError(set, vuids.descriptor_valid,
999 "Descriptor set %s encountered the following validation error at %s time: Descriptor "
1000 "in binding #%" PRIu32 " index %" PRIu32
1001 " requires bound image to have multiple samples, but got VK_SAMPLE_COUNT_1_BIT.",
1002 report_data->FormatHandle(set).c_str(), caller, binding, index);
Jeff Bolz6cede832019-08-09 23:30:39 -05001003 }
locke-lunarg25b6c352020-08-06 17:44:18 -06001004
John Zulauf79f06582021-02-27 18:38:39 -07001005 const VkDescriptorType descriptor_type = binding_it.GetType();
locke-lunarg540b2252020-08-03 13:23:36 -06001006
locke-lunarg25b6c352020-08-06 17:44:18 -06001007 // Verify VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
1008 if ((reqs & DESCRIPTOR_REQ_VIEW_ATOMIC_OPERATION) &&
locke-lunarg540b2252020-08-03 13:23:36 -06001009 (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) &&
locke-lunarg25b6c352020-08-06 17:44:18 -06001010 !(image_view_state->format_features & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)) {
1011 auto set = descriptor_set->GetSet();
1012 LogObjectList objlist(set);
1013 objlist.add(image_view);
sfricke-samsungbda4a852021-03-06 20:58:01 -08001014 return LogError(objlist, vuids.imageview_atomic,
1015 "Descriptor set %s encountered the following validation error at %s time: Descriptor "
1016 "in binding #%" PRIu32 " index %" PRIu32
1017 ", %s, format %s, doesn't "
1018 "contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT.",
1019 report_data->FormatHandle(set).c_str(), caller, binding, index,
1020 report_data->FormatHandle(image_view).c_str(), string_VkFormat(image_view_ci.format));
locke-lunarg25b6c352020-08-06 17:44:18 -06001021 }
locke-lunarg540b2252020-08-03 13:23:36 -06001022
1023 // Verify if attachments are used in DescriptorSet
locke-lunargfc78e932020-11-19 17:06:24 -07001024 if (attachments && attachments->size() > 0 && (descriptor_type != VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
locke-lunarg5e1bdde2020-11-16 17:08:44 -07001025 bool ds_aspect = (image_view_state->create_info.subresourceRange.aspectMask &
1026 (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
1027 ? true
1028 : false;
locke-lunargfc78e932020-11-19 17:06:24 -07001029 uint32_t att_index = 0;
1030 for (const auto &view_state : *attachments) {
1031 if (!subpasses[att_index].used || !view_state || view_state->destroyed) {
locke-lunarg1ae57d62020-11-18 10:49:19 -07001032 continue;
1033 }
locke-lunargfc78e932020-11-19 17:06:24 -07001034 if (ds_aspect && subpasses[att_index].usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
locke-lunarg5e1bdde2020-11-16 17:08:44 -07001035 if ((image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ||
1036 image_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
1037 image_layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL) &&
locke-lunargfc78e932020-11-19 17:06:24 -07001038 (subpasses[att_index].layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ||
1039 subpasses[att_index].layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
1040 subpasses[att_index].layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL)) {
locke-lunarg5e1bdde2020-11-16 17:08:44 -07001041 continue;
1042 }
1043 if ((image_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL &&
locke-lunargfc78e932020-11-19 17:06:24 -07001044 subpasses[att_index].layout ==
1045 VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL) ||
1046 (subpasses[att_index].layout ==
1047 VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL &&
locke-lunarg5e1bdde2020-11-16 17:08:44 -07001048 image_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)) {
1049 continue;
1050 }
1051 }
locke-lunargfc78e932020-11-19 17:06:24 -07001052 if (view_state->image_view == image_view) {
locke-lunarg540b2252020-08-03 13:23:36 -06001053 auto set = descriptor_set->GetSet();
1054 LogObjectList objlist(set);
1055 objlist.add(image_view);
1056 objlist.add(framebuffer);
sfricke-samsungbda4a852021-03-06 20:58:01 -08001057 return LogError(
1058 objlist, vuids.image_subresources,
1059 "Descriptor set %s encountered the following validation error at %s time: %s is used in "
1060 "Descriptor in binding #%" PRIu32 " index %" PRIu32 " and %s attachment # %" PRIu32 ".",
1061 report_data->FormatHandle(set).c_str(), caller,
1062 report_data->FormatHandle(image_view).c_str(), binding, index,
1063 report_data->FormatHandle(framebuffer).c_str(), att_index);
locke-lunargfc78e932020-11-19 17:06:24 -07001064 } else {
1065 if (image_view_state->OverlapSubresource(*view_state)) {
locke-lunarg540b2252020-08-03 13:23:36 -06001066 auto set = descriptor_set->GetSet();
1067 LogObjectList objlist(set);
1068 objlist.add(image_view);
1069 objlist.add(framebuffer);
locke-lunargfc78e932020-11-19 17:06:24 -07001070 objlist.add(view_state->image_view);
sfricke-samsungbda4a852021-03-06 20:58:01 -08001071 return LogError(objlist, vuids.image_subresources,
1072 "Descriptor set %s encountered the following validation error at %s time: "
1073 "Image subresources of %s in "
1074 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1075 " and %s in %s attachment # %" PRIu32 " overlap.",
1076 report_data->FormatHandle(set).c_str(), caller,
1077 report_data->FormatHandle(image_view).c_str(), binding, index,
1078 report_data->FormatHandle(view_state->image_view).c_str(),
1079 report_data->FormatHandle(framebuffer).c_str(), att_index);
locke-lunarg540b2252020-08-03 13:23:36 -06001080 }
1081 }
locke-lunargfc78e932020-11-19 17:06:24 -07001082 ++att_index;
locke-lunarg540b2252020-08-03 13:23:36 -06001083 }
locke-lunarg351c9d82020-10-23 14:43:21 -06001084 if (enabled_features.core11.protectedMemory == VK_TRUE) {
1085 if (ValidateProtectedImage(cb_node, image_view_state->image_state.get(), caller,
1086 vuids.unprotected_command_buffer, "Image is in a descriptorSet")) {
1087 return true;
1088 }
1089 if (binding_info.second.is_writable &&
1090 ValidateUnprotectedImage(cb_node, image_view_state->image_state.get(), caller,
1091 vuids.protected_command_buffer, "Image is in a descriptorSet")) {
1092 return true;
1093 }
1094 }
locke-lunarg540b2252020-08-03 13:23:36 -06001095 }
locke-lunarg36045992020-08-20 16:54:37 -06001096
locke-lunarg4e1e4632020-10-26 01:52:19 -06001097 for (const auto *sampler_state : sampler_states) {
1098 if (!sampler_state || sampler_state->destroyed) {
1099 continue;
1100 }
locke-lunarg654a9052020-10-13 16:28:42 -06001101
locke-lunarg4e1e4632020-10-26 01:52:19 -06001102 // TODO: Validate 04015 for DescriptorClass::PlainSampler
1103 if ((sampler_state->createInfo.borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT ||
1104 sampler_state->createInfo.borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT) &&
1105 (sampler_state->customCreateInfo.format == VK_FORMAT_UNDEFINED)) {
1106 if (image_view_state->create_info.format == VK_FORMAT_B4G4R4A4_UNORM_PACK16 ||
1107 image_view_state->create_info.format == VK_FORMAT_B5G6R5_UNORM_PACK16 ||
1108 image_view_state->create_info.format == VK_FORMAT_B5G5R5A1_UNORM_PACK16) {
1109 auto set = descriptor_set->GetSet();
1110 LogObjectList objlist(set);
1111 objlist.add(sampler_state->sampler);
1112 objlist.add(image_view_state->image_view);
sfricke-samsungbda4a852021-03-06 20:58:01 -08001113 return LogError(
1114 objlist, "VUID-VkSamplerCustomBorderColorCreateInfoEXT-format-04015",
1115 "Descriptor set %s encountered the following validation error at %s time: Sampler %s in "
1116 "binding #%" PRIu32 " index %" PRIu32
1117 " has a custom border color with format = VK_FORMAT_UNDEFINED and is used to "
1118 "sample an image view %s with format %s",
1119 report_data->FormatHandle(set).c_str(), caller,
1120 report_data->FormatHandle(sampler_state->sampler).c_str(), binding, index,
1121 report_data->FormatHandle(image_view_state->image_view).c_str(),
1122 string_VkFormat(image_view_state->create_info.format));
locke-lunarg4e1e4632020-10-26 01:52:19 -06001123 }
1124 }
1125 VkFilter sampler_mag_filter = sampler_state->createInfo.magFilter;
1126 VkFilter sampler_min_filter = sampler_state->createInfo.minFilter;
1127 VkBool32 sampler_compare_enable = sampler_state->createInfo.compareEnable;
1128 if ((sampler_mag_filter == VK_FILTER_LINEAR || sampler_min_filter == VK_FILTER_LINEAR) &&
1129 (sampler_compare_enable == VK_FALSE) &&
1130 !(image_view_state->format_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
locke-lunarg36045992020-08-20 16:54:37 -06001131 auto set = descriptor_set->GetSet();
1132 LogObjectList objlist(set);
locke-lunarg36045992020-08-20 16:54:37 -06001133 objlist.add(sampler_state->sampler);
locke-lunarg4e1e4632020-10-26 01:52:19 -06001134 objlist.add(image_view_state->image_view);
1135 return LogError(objlist, vuids.linear_sampler,
sfricke-samsungbda4a852021-03-06 20:58:01 -08001136 "Descriptor set %s encountered the following validation error at %s time: Sampler "
1137 "(%s) is set to use VK_FILTER_LINEAR with "
sfricke-samsung691299b2021-01-01 20:48:48 -08001138 "compareEnable is set to VK_TRUE, but image view's (%s) format (%s) does not "
locke-lunarg4e1e4632020-10-26 01:52:19 -06001139 "contain VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT in its format features.",
sfricke-samsungbda4a852021-03-06 20:58:01 -08001140 report_data->FormatHandle(set).c_str(), caller,
locke-lunarg4e1e4632020-10-26 01:52:19 -06001141 report_data->FormatHandle(sampler_state->sampler).c_str(),
locke-lunarg4e1e4632020-10-26 01:52:19 -06001142 report_data->FormatHandle(image_view_state->image_view).c_str(),
1143 string_VkFormat(image_view_state->create_info.format));
locke-lunarg36045992020-08-20 16:54:37 -06001144 }
locke-lunarg9939d4b2020-10-26 20:11:08 -06001145 if (sampler_mag_filter == VK_FILTER_CUBIC_EXT || sampler_min_filter == VK_FILTER_CUBIC_EXT) {
1146 if (!(image_view_state->format_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) {
1147 auto set = descriptor_set->GetSet();
1148 LogObjectList objlist(set);
1149 objlist.add(sampler_state->sampler);
1150 objlist.add(image_view_state->image_view);
1151 return LogError(objlist, vuids.cubic_sampler,
sfricke-samsungbda4a852021-03-06 20:58:01 -08001152 "Descriptor set %s encountered the following validation error at %s time: "
1153 "Sampler (%s) is set to use VK_FILTER_CUBIC_EXT, then "
Mark Lobodzinski45034452020-11-30 16:56:48 -07001154 "image view's (%s) format (%s) MUST contain "
1155 "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT in its format features.",
sfricke-samsungbda4a852021-03-06 20:58:01 -08001156 report_data->FormatHandle(set).c_str(), caller,
locke-lunarg9939d4b2020-10-26 20:11:08 -06001157 report_data->FormatHandle(sampler_state->sampler).c_str(),
locke-lunarg9939d4b2020-10-26 20:11:08 -06001158 report_data->FormatHandle(image_view_state->image_view).c_str(),
1159 string_VkFormat(image_view_state->create_info.format));
1160 }
1161
Mark Lobodzinski45034452020-11-30 16:56:48 -07001162 if (IsExtEnabled(device_extensions.vk_ext_filter_cubic)) {
1163 const auto reduction_mode_info =
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07001164 LvlFindInChain<VkSamplerReductionModeCreateInfo>(sampler_state->createInfo.pNext);
Mark Lobodzinski45034452020-11-30 16:56:48 -07001165 if (reduction_mode_info &&
1166 (reduction_mode_info->reductionMode == VK_SAMPLER_REDUCTION_MODE_MIN ||
1167 reduction_mode_info->reductionMode == VK_SAMPLER_REDUCTION_MODE_MAX) &&
1168 !image_view_state->filter_cubic_props.filterCubicMinmax) {
1169 auto set = descriptor_set->GetSet();
1170 LogObjectList objlist(set);
1171 objlist.add(sampler_state->sampler);
1172 objlist.add(image_view_state->image_view);
sfricke-samsungbda4a852021-03-06 20:58:01 -08001173 return LogError(objlist, vuids.filter_cubic_min_max,
1174 "Descriptor set %s encountered the following validation error at %s time: "
1175 "Sampler (%s) is set to use VK_FILTER_CUBIC_EXT & %s, "
1176 "but image view (%s) doesn't support filterCubicMinmax.",
1177 report_data->FormatHandle(set).c_str(), caller,
1178 report_data->FormatHandle(sampler_state->sampler).c_str(),
1179 string_VkSamplerReductionMode(reduction_mode_info->reductionMode),
1180 report_data->FormatHandle(image_view_state->image_view).c_str());
Mark Lobodzinski45034452020-11-30 16:56:48 -07001181 }
1182
1183 if (!image_view_state->filter_cubic_props.filterCubic) {
1184 auto set = descriptor_set->GetSet();
1185 LogObjectList objlist(set);
1186 objlist.add(sampler_state->sampler);
1187 objlist.add(image_view_state->image_view);
1188 return LogError(objlist, vuids.filter_cubic,
sfricke-samsungbda4a852021-03-06 20:58:01 -08001189 "Descriptor set %s encountered the following validation error at %s time: "
1190 "Sampler (%s) is set to use VK_FILTER_CUBIC_EXT, "
Mark Lobodzinski45034452020-11-30 16:56:48 -07001191 "but image view (%s) doesn't support filterCubic.",
sfricke-samsungbda4a852021-03-06 20:58:01 -08001192 report_data->FormatHandle(set).c_str(), caller,
Mark Lobodzinski45034452020-11-30 16:56:48 -07001193 report_data->FormatHandle(sampler_state->sampler).c_str(),
Mark Lobodzinski45034452020-11-30 16:56:48 -07001194 report_data->FormatHandle(image_view_state->image_view).c_str());
1195 }
locke-lunarg9939d4b2020-10-26 20:11:08 -06001196 }
1197
Mark Lobodzinski45034452020-11-30 16:56:48 -07001198 if (IsExtEnabled(device_extensions.vk_img_filter_cubic)) {
1199 if (image_view_state->create_info.viewType &
1200 (VK_IMAGE_VIEW_TYPE_3D | VK_IMAGE_VIEW_TYPE_CUBE | VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)) {
1201 auto set = descriptor_set->GetSet();
1202 LogObjectList objlist(set);
1203 objlist.add(sampler_state->sampler);
1204 objlist.add(image_view_state->image_view);
sfricke-samsungbda4a852021-03-06 20:58:01 -08001205 return LogError(
1206 objlist, vuids.img_filter_cubic,
1207 "Descriptor set %s encountered the following validation error at %s time: Sampler "
1208 "(%s)is set to use VK_FILTER_CUBIC_EXT while the VK_IMG_filter_cubic extension "
1209 "is enabled, but image view (%s) has an invalid imageViewType (%s).",
1210 report_data->FormatHandle(set).c_str(), caller,
1211 report_data->FormatHandle(sampler_state->sampler).c_str(),
1212 report_data->FormatHandle(image_view_state->image_view).c_str(),
1213 string_VkImageViewType(image_view_state->create_info.viewType));
Mark Lobodzinski45034452020-11-30 16:56:48 -07001214 }
locke-lunarg9939d4b2020-10-26 20:11:08 -06001215 }
locke-lunarg654a9052020-10-13 16:28:42 -06001216 }
1217
locke-lunarg4e1e4632020-10-26 01:52:19 -06001218 if ((image_state->createInfo.flags & VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV) &&
1219 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ||
1220 sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ||
1221 sampler_state->createInfo.addressModeW != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)) {
1222 std::string address_mode_letter =
locke-lunarg9939d4b2020-10-26 20:11:08 -06001223 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1224 ? "U"
1225 : (sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE) ? "V"
1226 : "W";
locke-lunarg4e1e4632020-10-26 01:52:19 -06001227 VkSamplerAddressMode address_mode =
1228 (sampler_state->createInfo.addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1229 ? sampler_state->createInfo.addressModeU
locke-lunarg9939d4b2020-10-26 20:11:08 -06001230 : (sampler_state->createInfo.addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1231 ? sampler_state->createInfo.addressModeV
1232 : sampler_state->createInfo.addressModeW;
locke-lunargae2a43c2020-09-22 17:21:57 -06001233 auto set = descriptor_set->GetSet();
1234 LogObjectList objlist(set);
locke-lunargae2a43c2020-09-22 17:21:57 -06001235 objlist.add(sampler_state->sampler);
locke-lunarg4e1e4632020-10-26 01:52:19 -06001236 objlist.add(image_state->image);
1237 objlist.add(image_view_state->image_view);
1238 return LogError(objlist, vuids.corner_sampled_address_mode,
sfricke-samsungbda4a852021-03-06 20:58:01 -08001239 "Descriptor set %s encountered the following validation error at %s time: Image "
1240 "(%s) in image view (%s) is created with flag "
locke-lunarg4e1e4632020-10-26 01:52:19 -06001241 "VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV and can only be sampled using "
1242 "VK_SAMPLER_ADDRESS_MODE_CLAMP_EDGE, but sampler (%s) has "
1243 "createInfo.addressMode%s set to %s.",
sfricke-samsungbda4a852021-03-06 20:58:01 -08001244 report_data->FormatHandle(set).c_str(), caller,
locke-lunarg4e1e4632020-10-26 01:52:19 -06001245 report_data->FormatHandle(image_state->image).c_str(),
1246 report_data->FormatHandle(image_view_state->image_view).c_str(),
locke-lunarg4e1e4632020-10-26 01:52:19 -06001247 report_data->FormatHandle(sampler_state->sampler).c_str(),
1248 address_mode_letter.c_str(), string_VkSamplerAddressMode(address_mode));
1249 }
1250
1251 // UnnormalizedCoordinates sampler validations
1252 if (sampler_state->createInfo.unnormalizedCoordinates) {
1253 // If ImageView is used by a unnormalizedCoordinates sampler, it needs to check ImageView type
1254 if (image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_3D ||
1255 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
1256 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY ||
1257 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY ||
1258 image_view_ci.viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
1259 auto set = descriptor_set->GetSet();
1260 LogObjectList objlist(set);
1261 objlist.add(image_view);
1262 objlist.add(sampler_state->sampler);
sfricke-samsungbda4a852021-03-06 20:58:01 -08001263 return LogError(
1264 objlist, vuids.sampler_imageview_type,
1265 "Descriptor set %s encountered the following validation error at %s time: %s, type: %s in "
1266 "Descriptor in binding #%" PRIu32 " index %" PRIu32 "is used by %s.",
1267 report_data->FormatHandle(set).c_str(), caller,
1268 report_data->FormatHandle(image_view).c_str(),
1269 string_VkImageViewType(image_view_ci.viewType), binding, index,
1270 report_data->FormatHandle(sampler_state->sampler).c_str());
locke-lunarg4e1e4632020-10-26 01:52:19 -06001271 }
1272
1273 // sampler must not be used with any of the SPIR-V OpImageSample* or OpImageSparseSample*
1274 // instructions with ImplicitLod, Dref or Proj in their name
1275 if (reqs & DESCRIPTOR_REQ_SAMPLER_IMPLICITLOD_DREF_PROJ) {
1276 auto set = descriptor_set->GetSet();
1277 LogObjectList objlist(set);
1278 objlist.add(image_view);
1279 objlist.add(sampler_state->sampler);
sfricke-samsungbda4a852021-03-06 20:58:01 -08001280 return LogError(
1281 objlist, vuids.sampler_implicitLod_dref_proj,
1282 "Descriptor set %s encountered the following validation error at %s time: %s in "
1283 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1284 " is used by %s that uses invalid operator.",
1285 report_data->FormatHandle(set).c_str(), caller,
1286 report_data->FormatHandle(image_view).c_str(), binding, index,
1287 report_data->FormatHandle(sampler_state->sampler).c_str());
locke-lunarg4e1e4632020-10-26 01:52:19 -06001288 }
1289
1290 // sampler must not be used with any of the SPIR-V OpImageSample* or OpImageSparseSample*
1291 // instructions that includes a LOD bias or any offset values
1292 if (reqs & DESCRIPTOR_REQ_SAMPLER_BIAS_OFFSET) {
1293 auto set = descriptor_set->GetSet();
1294 LogObjectList objlist(set);
1295 objlist.add(image_view);
1296 objlist.add(sampler_state->sampler);
sfricke-samsungbda4a852021-03-06 20:58:01 -08001297 return LogError(
1298 objlist, vuids.sampler_bias_offset,
1299 "Descriptor set %s encountered the following validation error at %s time: %s in "
1300 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1301 " is used by %s that uses invalid bias or offset operator.",
1302 report_data->FormatHandle(set).c_str(), caller,
1303 report_data->FormatHandle(image_view).c_str(), binding, index,
1304 report_data->FormatHandle(sampler_state->sampler).c_str());
locke-lunarg4e1e4632020-10-26 01:52:19 -06001305 }
locke-lunargae2a43c2020-09-22 17:21:57 -06001306 }
locke-lunarg36045992020-08-20 16:54:37 -06001307 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -07001308 }
John Zulaufc93c4252019-06-25 09:19:49 -06001309 } else if (descriptor_class == DescriptorClass::TexelBuffer) {
John Zulauf382e1912019-06-10 15:27:44 -06001310 auto texel_buffer = static_cast<const TexelDescriptor *>(descriptor);
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001311 auto buffer_view = texel_buffer->GetBufferView();
1312 auto buffer_view_state = texel_buffer->GetBufferViewState();
Chris Forbese92dd1d2019-01-21 15:58:57 -08001313
Karl Schultz76d16a42020-11-11 05:05:33 -07001314 if ((!buffer_view_state && !enabled_features.robustness2_features.nullDescriptor) ||
1315 (buffer_view_state && buffer_view_state->destroyed)) {
1316 auto set = descriptor_set->GetSet();
1317 return LogError(set, vuids.descriptor_valid,
sfricke-samsungbda4a852021-03-06 20:58:01 -08001318 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
Karl Schultz76d16a42020-11-11 05:05:33 -07001319 "binding #%" PRIu32 " index %" PRIu32
1320 " is using bufferView %s that is invalid or has been destroyed.",
1321 report_data->FormatHandle(set).c_str(), caller, binding, index,
1322 report_data->FormatHandle(buffer_view).c_str());
1323 }
Jeff Bolz165818a2020-05-08 11:19:03 -05001324 if (buffer_view) {
Jeff Bolz165818a2020-05-08 11:19:03 -05001325 auto buffer = buffer_view_state->create_info.buffer;
1326 auto buffer_state = buffer_view_state->buffer_state.get();
1327 if (buffer_state->destroyed) {
1328 auto set = descriptor_set->GetSet();
sfricke-samsungbda4a852021-03-06 20:58:01 -08001329 return LogError(
1330 set, vuids.descriptor_valid,
1331 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1332 "binding #%" PRIu32 " index %" PRIu32 " is using buffer %s that has been destroyed.",
1333 report_data->FormatHandle(set).c_str(), caller, binding, index,
1334 report_data->FormatHandle(buffer).c_str());
Jeff Bolz165818a2020-05-08 11:19:03 -05001335 }
1336 auto format_bits = DescriptorRequirementsBitsFromFormat(buffer_view_state->create_info.format);
Chris Forbese92dd1d2019-01-21 15:58:57 -08001337
Jeff Bolz165818a2020-05-08 11:19:03 -05001338 if (!(reqs & format_bits)) {
1339 // bad component type
1340 auto set = descriptor_set->GetSet();
sfricke-samsungbda4a852021-03-06 20:58:01 -08001341 return LogError(
1342 set, vuids.descriptor_valid,
1343 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1344 "binding #%" PRIu32 " index %" PRIu32
1345 " requires %s component type, but bound descriptor format is %s.",
1346 report_data->FormatHandle(set).c_str(), caller, binding, index,
1347 StringDescriptorReqComponentType(reqs), string_VkFormat(buffer_view_state->create_info.format));
Jeff Bolz165818a2020-05-08 11:19:03 -05001348 }
locke-lunarg25b6c352020-08-06 17:44:18 -06001349
1350 // Verify VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT
1351 if ((reqs & DESCRIPTOR_REQ_VIEW_ATOMIC_OPERATION) &&
locke-lunarge4bf18f2020-08-21 10:23:08 -06001352 (descriptor_set->GetTypeFromBinding(binding) == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) &&
locke-lunarg25b6c352020-08-06 17:44:18 -06001353 !(buffer_view_state->format_features & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT)) {
1354 auto set = descriptor_set->GetSet();
1355 LogObjectList objlist(set);
1356 objlist.add(buffer_view);
sfricke-samsungbda4a852021-03-06 20:58:01 -08001357 return LogError(objlist, "UNASSIGNED-None-MismatchAtomicBufferFeature",
1358 "Descriptor set %s encountered the following validation error at %s time: Descriptor "
1359 "in binding #%" PRIu32 " index %" PRIu32
1360 ", %s, format %s, doesn't "
1361 "contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT.",
1362 report_data->FormatHandle(set).c_str(), caller, binding, index,
1363 report_data->FormatHandle(buffer_view).c_str(),
1364 string_VkFormat(buffer_view_state->create_info.format));
locke-lunarg25b6c352020-08-06 17:44:18 -06001365 }
locke-lunarg351c9d82020-10-23 14:43:21 -06001366 if (enabled_features.core11.protectedMemory == VK_TRUE) {
1367 if (ValidateProtectedBuffer(cb_node, buffer_view_state->buffer_state.get(), caller,
1368 vuids.unprotected_command_buffer, "Buffer is in a descriptorSet")) {
1369 return true;
1370 }
1371 if (binding_info.second.is_writable &&
1372 ValidateUnprotectedBuffer(cb_node, buffer_view_state->buffer_state.get(), caller,
1373 vuids.protected_command_buffer, "Buffer is in a descriptorSet")) {
1374 return true;
1375 }
1376 }
Chris Forbese92dd1d2019-01-21 15:58:57 -08001377 }
Jeff Bolz95176d02020-04-01 00:36:16 -05001378 } else if (descriptor_class == DescriptorClass::AccelerationStructure) {
1379 // Verify that acceleration structures are valid
sourav parmarcd51aa82020-11-17 12:04:52 -08001380 bool is_khr = (*((cvdescriptorset::AccelerationStructureDescriptor *)(descriptor))).is_khr();
1381 if (is_khr) {
1382 auto acc = static_cast<const AccelerationStructureDescriptor *>(descriptor)->GetAccelerationStructure();
1383 auto acc_node =
1384 static_cast<const AccelerationStructureDescriptor *>(descriptor)->GetAccelerationStructureStateKHR();
1385 if (!acc_node || acc_node->destroyed) {
1386 if (acc != VK_NULL_HANDLE || !enabled_features.robustness2_features.nullDescriptor) {
1387 auto set = descriptor_set->GetSet();
sfricke-samsungbda4a852021-03-06 20:58:01 -08001388 return LogError(set, vuids.descriptor_valid,
1389 "Descriptor set %s encountered the following validation error at %s time: "
1390 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1391 " is using acceleration structure %s that is invalid or has been destroyed.",
1392 report_data->FormatHandle(set).c_str(), caller, binding, index,
1393 report_data->FormatHandle(acc).c_str());
sourav parmarcd51aa82020-11-17 12:04:52 -08001394 }
1395 } else {
John Zulauf79f06582021-02-27 18:38:39 -07001396 for (const auto *mem_binding : acc_node->GetBoundMemory()) {
sourav parmarcd51aa82020-11-17 12:04:52 -08001397 if (mem_binding->destroyed) {
1398 auto set = descriptor_set->GetSet();
sfricke-samsungbda4a852021-03-06 20:58:01 -08001399 return LogError(
1400 set, vuids.descriptor_valid,
1401 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1402 "binding #%" PRIu32 " index %" PRIu32
1403 " is using acceleration structure %s that references invalid memory %s.",
1404 report_data->FormatHandle(set).c_str(), caller, binding, index,
1405 report_data->FormatHandle(acc).c_str(),
1406 report_data->FormatHandle(mem_binding->mem).c_str());
sourav parmarcd51aa82020-11-17 12:04:52 -08001407 }
1408 }
Ricardo Garcia3f145ae2020-10-28 16:53:35 +01001409 }
Jeff Bolz95176d02020-04-01 00:36:16 -05001410 } else {
sourav parmarcd51aa82020-11-17 12:04:52 -08001411 auto acc = static_cast<const AccelerationStructureDescriptor *>(descriptor)->GetAccelerationStructureNV();
1412 auto acc_node =
1413 static_cast<const AccelerationStructureDescriptor *>(descriptor)->GetAccelerationStructureStateNV();
1414 if (!acc_node || acc_node->destroyed) {
1415 if (acc != VK_NULL_HANDLE || !enabled_features.robustness2_features.nullDescriptor) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001416 auto set = descriptor_set->GetSet();
sfricke-samsungbda4a852021-03-06 20:58:01 -08001417 return LogError(set, vuids.descriptor_valid,
1418 "Descriptor set %s encountered the following validation error at %s time: "
1419 "Descriptor in binding #%" PRIu32 " index %" PRIu32
1420 " is using acceleration structure %s that is invalid or has been destroyed.",
1421 report_data->FormatHandle(set).c_str(), caller, binding, index,
1422 report_data->FormatHandle(acc).c_str());
sourav parmarcd51aa82020-11-17 12:04:52 -08001423 }
1424 } else {
John Zulauf79f06582021-02-27 18:38:39 -07001425 for (const auto *mem_binding : acc_node->GetBoundMemory()) {
sourav parmarcd51aa82020-11-17 12:04:52 -08001426 if (mem_binding->destroyed) {
1427 auto set = descriptor_set->GetSet();
sfricke-samsungbda4a852021-03-06 20:58:01 -08001428 return LogError(
1429 set, vuids.descriptor_valid,
1430 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
1431 "binding #%" PRIu32 " index %" PRIu32
1432 " is using acceleration structure %s that references invalid memory %s.",
1433 report_data->FormatHandle(set).c_str(), caller, binding, index,
1434 report_data->FormatHandle(acc).c_str(),
1435 report_data->FormatHandle(mem_binding->mem).c_str());
sourav parmarcd51aa82020-11-17 12:04:52 -08001436 }
Jeff Bolz95176d02020-04-01 00:36:16 -05001437 }
1438 }
1439 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001440 }
locke-lunarg4e1e4632020-10-26 01:52:19 -06001441
1442 // If the validation is related to both of image and sampler,
locke-lunarg9939d4b2020-10-26 20:11:08 -06001443 // please leave it in (descriptor_class == DescriptorClass::ImageSampler || descriptor_class ==
1444 // DescriptorClass::Image) Here is to validate for only sampler.
John Zulaufc93c4252019-06-25 09:19:49 -06001445 if (descriptor_class == DescriptorClass::ImageSampler || descriptor_class == DescriptorClass::PlainSampler) {
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001446 // Verify Sampler still valid
1447 VkSampler sampler;
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001448 const SAMPLER_STATE *sampler_state;
John Zulaufc93c4252019-06-25 09:19:49 -06001449 if (descriptor_class == DescriptorClass::ImageSampler) {
John Zulauf382e1912019-06-10 15:27:44 -06001450 sampler = static_cast<const ImageSamplerDescriptor *>(descriptor)->GetSampler();
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001451 sampler_state = static_cast<const ImageSamplerDescriptor *>(descriptor)->GetSamplerState();
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001452 } else {
John Zulauf382e1912019-06-10 15:27:44 -06001453 sampler = static_cast<const SamplerDescriptor *>(descriptor)->GetSampler();
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001454 sampler_state = static_cast<const SamplerDescriptor *>(descriptor)->GetSamplerState();
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001455 }
Jeff Bolzfaffeb32019-10-04 12:47:16 -05001456 if (!sampler_state || sampler_state->destroyed) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001457 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -06001458 return LogError(set, vuids.descriptor_valid,
sfricke-samsungbda4a852021-03-06 20:58:01 -08001459 "Descriptor set %s encountered the following validation error at %s time: Descriptor in "
Tony-LunarGace473a2020-05-06 12:48:04 -06001460 "binding #%" PRIu32 " index %" PRIu32
1461 " is using sampler %s that is invalid or has been destroyed.",
1462 report_data->FormatHandle(set).c_str(), caller, binding, index,
1463 report_data->FormatHandle(sampler).c_str());
Lockea223c102019-04-05 00:38:24 -06001464 } else {
John Zulauf382e1912019-06-10 15:27:44 -06001465 if (sampler_state->samplerConversion && !descriptor->IsImmutableSampler()) {
Tony-LunarGace473a2020-05-06 12:48:04 -06001466 auto set = descriptor_set->GetSet();
locke-lunarg1328e8e2020-08-20 12:40:08 -06001467 return LogError(set, vuids.descriptor_valid,
sfricke-samsungbda4a852021-03-06 20:58:01 -08001468 "Descriptor set %s encountered the following validation error at %s time: sampler (%s) "
Zach Johnston0480f132021-03-21 23:58:57 -04001469 "in the descriptor set (%s) contains a YCBCR conversion (%s), then the sampler MUST "
Tony-LunarGace473a2020-05-06 12:48:04 -06001470 "also exist as an immutable sampler.",
1471 report_data->FormatHandle(set).c_str(), caller,
1472 report_data->FormatHandle(sampler).c_str(),
1473 report_data->FormatHandle(descriptor_set->GetSet()).c_str(),
1474 report_data->FormatHandle(sampler_state->samplerConversion).c_str());
Lockea223c102019-04-05 00:38:24 -06001475 }
Tobin Ehlisb1a2e4b2018-03-16 07:54:24 -06001476 }
1477 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001478 }
1479 }
1480 }
Tony-LunarGace473a2020-05-06 12:48:04 -06001481 return false;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001482}
Chris Forbes57989132016-07-26 17:06:10 +12001483
Tobin Ehlis9906d9d2016-05-17 14:23:46 -06001484// Set is being deleted or updates so invalidate all bound cmd buffers
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001485void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers(ValidationStateTracker *state_data) {
1486 state_data->InvalidateCommandBuffers(cb_bindings, VulkanTypedHandle(set_, kVulkanObjectTypeDescriptorSet), /*unlink*/ false);
Tobin Ehlis9906d9d2016-05-17 14:23:46 -06001487}
John Zulauf1d27e0a2018-11-05 10:12:48 -07001488
1489// Loop through the write updates to do for a push descriptor set, ignoring dstSet
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001490void cvdescriptorset::DescriptorSet::PerformPushDescriptorsUpdate(ValidationStateTracker *dev_data, uint32_t write_count,
1491 const VkWriteDescriptorSet *p_wds) {
John Zulauf1d27e0a2018-11-05 10:12:48 -07001492 assert(IsPushDescriptor());
1493 for (uint32_t i = 0; i < write_count; i++) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001494 PerformWriteUpdate(dev_data, &p_wds[i]);
John Zulauf1d27e0a2018-11-05 10:12:48 -07001495 }
Jason Macnak83cfd582019-07-31 10:14:24 -07001496
1497 push_descriptor_set_writes.clear();
1498 push_descriptor_set_writes.reserve(static_cast<std::size_t>(write_count));
1499 for (uint32_t i = 0; i < write_count; i++) {
1500 push_descriptor_set_writes.push_back(safe_VkWriteDescriptorSet(&p_wds[i]));
1501 }
John Zulauf1d27e0a2018-11-05 10:12:48 -07001502}
1503
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001504// Perform write update in given update struct
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001505void cvdescriptorset::DescriptorSet::PerformWriteUpdate(ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update) {
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001506 // Perform update on a per-binding basis as consecutive updates roll over to next binding
1507 auto descriptors_remaining = update->descriptorCount;
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001508 auto offset = update->dstArrayElement;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001509 auto orig_binding = DescriptorSetLayout::ConstBindingIterator(layout_.get(), update->dstBinding);
locke-lunarge46b7782019-09-10 01:44:20 -06001510 auto current_binding = orig_binding;
1511
Tobin Ehlise16805c2017-08-09 09:10:37 -06001512 uint32_t update_index = 0;
locke-lunarge46b7782019-09-10 01:44:20 -06001513 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
1514 while (descriptors_remaining && orig_binding.IsConsistent(current_binding)) {
1515 const auto &index_range = current_binding.GetGlobalIndexRange();
1516 auto global_idx = index_range.start + offset;
1517 // global_idx is which descriptor is needed to update. If global_idx > index_range.end, it means the descriptor isn't in
1518 // this binding, maybe in next binding.
1519 if (global_idx >= index_range.end) {
1520 offset -= current_binding.GetDescriptorCount();
1521 ++current_binding;
1522 continue;
1523 }
1524
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001525 // Loop over the updates for a single binding at a time
locke-lunarge46b7782019-09-10 01:44:20 -06001526 uint32_t update_count = std::min(descriptors_remaining, current_binding.GetDescriptorCount() - offset);
Tobin Ehlise16805c2017-08-09 09:10:37 -06001527 for (uint32_t di = 0; di < update_count; ++di, ++update_index) {
John Zulaufd2c3dae2019-12-12 11:02:17 -07001528 descriptors_[global_idx + di]->WriteUpdate(state_data_, update, update_index);
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001529 }
1530 // Roll over to next binding in case of consecutive update
1531 descriptors_remaining -= update_count;
locke-lunarge46b7782019-09-10 01:44:20 -06001532 if (descriptors_remaining) {
1533 // Starting offset is beyond the current binding. Check consistency, update counters and advance to the next binding,
1534 // looking for the start point. All bindings (even those skipped) must be consistent with the update and with the
1535 // original binding.
1536 offset = 0;
1537 ++current_binding;
1538 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001539 }
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05001540 if (update->descriptorCount) {
1541 some_update_ = true;
1542 change_count_++;
1543 }
Tobin Ehlis56a30942016-05-19 08:00:00 -06001544
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001545 if (!(layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Mike Schuchardt2df08912020-12-15 16:28:09 -08001546 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT))) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001547 InvalidateBoundCmdBuffers(dev_data);
Jeff Bolzfdf96072018-04-10 14:32:18 -05001548 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001549}
Tobin Ehlis300888c2016-05-18 13:43:26 -06001550// Validate Copy update
John Zulaufc93c4252019-06-25 09:19:49 -06001551bool CoreChecks::ValidateCopyUpdate(const VkCopyDescriptorSet *update, const DescriptorSet *dst_set, const DescriptorSet *src_set,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05001552 const char *func_name, std::string *error_code, std::string *error_msg) const {
Jeff Bolz6aad1742019-10-16 11:10:09 -05001553 auto dst_layout = dst_set->GetLayout().get();
1554 auto src_layout = src_set->GetLayout().get();
John Zulaufd9435c32019-06-05 15:55:36 -06001555
John Zulauf5dfd45c2018-01-17 11:06:34 -07001556 // Verify dst layout still valid
Jeff Bolz6ae39612019-10-11 20:57:36 -05001557 if (dst_layout->destroyed) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001558 *error_code = "VUID-VkCopyDescriptorSet-dstSet-parameter";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06001559 std::ostringstream str;
1560 str << "Cannot call " << func_name << " to perform copy update on dstSet " << report_data->FormatHandle(dst_set->GetSet())
1561 << " created with destroyed " << report_data->FormatHandle(dst_layout->GetDescriptorSetLayout()) << ".";
1562 *error_msg = str.str();
John Zulauf5dfd45c2018-01-17 11:06:34 -07001563 return false;
1564 }
1565
1566 // Verify src layout still valid
Jeff Bolz6ae39612019-10-11 20:57:36 -05001567 if (src_layout->destroyed) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001568 *error_code = "VUID-VkCopyDescriptorSet-srcSet-parameter";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06001569 std::ostringstream str;
1570 str << "Cannot call " << func_name << " to perform copy update on dstSet " << report_data->FormatHandle(dst_set->GetSet())
1571 << " from srcSet " << report_data->FormatHandle(src_set->GetSet()) << " created with destroyed "
1572 << report_data->FormatHandle(src_layout->GetDescriptorSetLayout()) << ".";
1573 *error_msg = str.str();
John Zulauf5dfd45c2018-01-17 11:06:34 -07001574 return false;
1575 }
1576
John Zulaufd9435c32019-06-05 15:55:36 -06001577 if (!dst_layout->HasBinding(update->dstBinding)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001578 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-00347";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001579 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001580 error_str << "DescriptorSet " << report_data->FormatHandle(dst_set->GetSet())
1581 << " does not have copy update dest binding of " << update->dstBinding;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001582 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001583 return false;
1584 }
1585 if (!src_set->HasBinding(update->srcBinding)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001586 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-00345";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001587 std::stringstream error_str;
sourav parmarf4a78252020-04-10 13:04:21 -07001588 error_str << "DescriptorSet " << report_data->FormatHandle(src_set->GetSet())
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001589 << " does not have copy update src binding of " << update->srcBinding;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001590 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001591 return false;
1592 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001593 // Verify idle ds
John Zulaufd9435c32019-06-05 15:55:36 -06001594 if (dst_set->in_use.load() &&
1595 !(dst_layout->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Mike Schuchardt2df08912020-12-15 16:28:09 -08001596 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT))) {
Jeff Bolzfdf96072018-04-10 14:32:18 -05001597 // TODO : Re-using Free Idle error code, need copy update idle error code
Dave Houlton00c154e2018-05-24 13:20:50 -06001598 *error_code = "VUID-vkFreeDescriptorSets-pDescriptorSets-00309";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001599 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001600 error_str << "Cannot call " << func_name << " to perform copy update on descriptor set "
1601 << report_data->FormatHandle(dst_set->GetSet()) << " that is in use by a command buffer";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001602 *error_msg = error_str.str();
1603 return false;
1604 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001605 // src & dst set bindings are valid
1606 // Check bounds of src & dst
John Zulaufc483f442017-12-15 14:02:06 -07001607 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001608 if ((src_start_idx + update->descriptorCount) > src_set->GetTotalDescriptorCount()) {
1609 // SRC update out of bounds
Dave Houlton00c154e2018-05-24 13:20:50 -06001610 *error_code = "VUID-VkCopyDescriptorSet-srcArrayElement-00346";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001611 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001612 error_str << "Attempting copy update from descriptorSet " << report_data->FormatHandle(update->srcSet) << " binding#"
1613 << update->srcBinding << " with offset index of "
1614 << src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start << " plus update array offset of "
1615 << update->srcArrayElement << " and update of " << update->descriptorCount
Tobin Ehlis1d81edd2016-11-21 09:50:49 -07001616 << " descriptors oversteps total number of descriptors in set: " << src_set->GetTotalDescriptorCount();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001617 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001618 return false;
1619 }
John Zulaufd9435c32019-06-05 15:55:36 -06001620 auto dst_start_idx = dst_layout->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
1621 if ((dst_start_idx + update->descriptorCount) > dst_layout->GetTotalDescriptorCount()) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001622 // DST update out of bounds
Dave Houlton00c154e2018-05-24 13:20:50 -06001623 *error_code = "VUID-VkCopyDescriptorSet-dstArrayElement-00348";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001624 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001625 error_str << "Attempting copy update to descriptorSet " << report_data->FormatHandle(dst_set->GetSet()) << " binding#"
1626 << update->dstBinding << " with offset index of "
1627 << dst_layout->GetGlobalIndexRangeFromBinding(update->dstBinding).start << " plus update array offset of "
1628 << update->dstArrayElement << " and update of " << update->descriptorCount
John Zulaufd9435c32019-06-05 15:55:36 -06001629 << " descriptors oversteps total number of descriptors in set: " << dst_layout->GetTotalDescriptorCount();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001630 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001631 return false;
1632 }
1633 // Check that types match
Shannon McPhersonafe55122020-05-25 16:20:19 -06001634 // TODO : Base default error case going from here is "VUID-VkAcquireNextImageInfoKHR-semaphore-parameter" 2ba which covers all
Dave Houltond8ed0212018-05-16 17:18:24 -06001635 // consistency issues, need more fine-grained error codes
Dave Houlton00c154e2018-05-24 13:20:50 -06001636 *error_code = "VUID-VkCopyDescriptorSet-srcSet-00349";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001637 auto src_type = src_set->GetTypeFromBinding(update->srcBinding);
John Zulaufd9435c32019-06-05 15:55:36 -06001638 auto dst_type = dst_layout->GetTypeFromBinding(update->dstBinding);
Ricardo Garcia14f4f762021-04-13 11:36:12 +02001639 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 -07001640 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02632";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001641 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001642 error_str << "Attempting copy update to descriptorSet " << report_data->FormatHandle(dst_set->GetSet()) << " binding #"
1643 << update->dstBinding << " with type " << string_VkDescriptorType(dst_type) << " from descriptorSet "
1644 << report_data->FormatHandle(src_set->GetSet()) << " binding #" << update->srcBinding << " with type "
1645 << string_VkDescriptorType(src_type) << ". Types do not match";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001646 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001647 return false;
1648 }
1649 // Verify consistency of src & dst bindings if update crosses binding boundaries
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001650 if ((!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(src_layout, update->srcBinding),
John Zulauf4a015c92019-06-04 09:50:05 -06001651 update->srcArrayElement, update->descriptorCount, "copy update from", src_set->GetSet(),
1652 error_msg)) ||
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001653 (!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(dst_layout, update->dstBinding),
John Zulaufd9435c32019-06-05 15:55:36 -06001654 update->dstArrayElement, update->descriptorCount, "copy update to", dst_set->GetSet(),
1655 error_msg))) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001656 return false;
1657 }
Jeff Bolzfdf96072018-04-10 14:32:18 -05001658
Mike Schuchardt2df08912020-12-15 16:28:09 -08001659 if ((src_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT) &&
1660 !(dst_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001661 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01918";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001662 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001663 error_str << "If pname:srcSet's (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001664 << ") layout was created with the "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001665 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag "
Jeff Bolzfdf96072018-04-10 14:32:18 -05001666 "set, then pname:dstSet's ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001667 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001668 << ") layout must: also have been created with the "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001669 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag set";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001670 *error_msg = error_str.str();
1671 return false;
1672 }
1673
Mike Schuchardt2df08912020-12-15 16:28:09 -08001674 if (!(src_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT) &&
1675 (dst_layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001676 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01919";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001677 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001678 error_str << "If pname:srcSet's (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001679 << ") layout was created without the "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001680 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag "
Jeff Bolzfdf96072018-04-10 14:32:18 -05001681 "set, then pname:dstSet's ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001682 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001683 << ") layout must: also have been created without the "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001684 "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT flag set";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001685 *error_msg = error_str.str();
1686 return false;
1687 }
1688
Mike Schuchardt2df08912020-12-15 16:28:09 -08001689 if ((src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT) &&
1690 !(dst_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001691 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01920";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001692 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001693 error_str << "If the descriptor pool from which pname:srcSet (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001694 << ") was allocated was created "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001695 "with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag "
Jeff Bolzfdf96072018-04-10 14:32:18 -05001696 "set, then the descriptor pool from which pname:dstSet ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001697 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001698 << ") was allocated must: "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001699 "also have been created with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag set";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001700 *error_msg = error_str.str();
1701 return false;
1702 }
1703
Mike Schuchardt2df08912020-12-15 16:28:09 -08001704 if (!(src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT) &&
1705 (dst_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06001706 *error_code = "VUID-VkCopyDescriptorSet-srcSet-01921";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001707 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001708 error_str << "If the descriptor pool from which pname:srcSet (" << report_data->FormatHandle(update->srcSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001709 << ") was allocated was created "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001710 "without the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag "
Jeff Bolzfdf96072018-04-10 14:32:18 -05001711 "set, then the descriptor pool from which pname:dstSet ("
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06001712 << report_data->FormatHandle(update->dstSet)
Jeff Bolzfdf96072018-04-10 14:32:18 -05001713 << ") was allocated must: "
Mike Schuchardt2df08912020-12-15 16:28:09 -08001714 "also have been created without the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT flag set";
Jeff Bolzfdf96072018-04-10 14:32:18 -05001715 *error_msg = error_str.str();
1716 return false;
1717 }
1718
Jeff Bolze54ae892018-09-08 12:16:29 -05001719 if (src_type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
1720 if ((update->srcArrayElement % 4) != 0) {
1721 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-02223";
1722 std::stringstream error_str;
1723 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1724 << "srcArrayElement " << update->srcArrayElement << " not a multiple of 4";
1725 *error_msg = error_str.str();
1726 return false;
1727 }
1728 if ((update->dstArrayElement % 4) != 0) {
1729 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02224";
1730 std::stringstream error_str;
1731 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1732 << "dstArrayElement " << update->dstArrayElement << " not a multiple of 4";
1733 *error_msg = error_str.str();
1734 return false;
1735 }
1736 if ((update->descriptorCount % 4) != 0) {
1737 *error_code = "VUID-VkCopyDescriptorSet-srcBinding-02225";
1738 std::stringstream error_str;
1739 error_str << "Attempting copy update to VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT binding with "
1740 << "descriptorCount " << update->descriptorCount << " not a multiple of 4";
1741 *error_msg = error_str.str();
1742 return false;
1743 }
1744 }
1745
Tobin Ehlisd41e7b62016-05-19 07:56:18 -06001746 // Update parameters all look good and descriptor updated so verify update contents
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07001747 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 -07001748 error_msg)) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07001749 return false;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001750 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06001751
1752 // All checks passed so update is good
1753 return true;
1754}
1755// Perform Copy update
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001756void cvdescriptorset::DescriptorSet::PerformCopyUpdate(ValidationStateTracker *dev_data, const VkCopyDescriptorSet *update,
1757 const DescriptorSet *src_set) {
John Zulaufc483f442017-12-15 14:02:06 -07001758 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001759 auto dst_start_idx = layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001760 // Update parameters all look good so perform update
1761 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Józef Kucia5297e372017-10-13 22:31:34 +02001762 auto src = src_set->descriptors_[src_start_idx + di].get();
1763 auto dst = descriptors_[dst_start_idx + di].get();
1764 if (src->updated) {
John Zulaufd2c3dae2019-12-12 11:02:17 -07001765 dst->CopyUpdate(state_data_, src);
Józef Kucia5297e372017-10-13 22:31:34 +02001766 some_update_ = true;
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05001767 change_count_++;
Józef Kucia5297e372017-10-13 22:31:34 +02001768 } else {
1769 dst->updated = false;
1770 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001771 }
Tobin Ehlis56a30942016-05-19 08:00:00 -06001772
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001773 if (!(layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
Mike Schuchardt2df08912020-12-15 16:28:09 -08001774 (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT))) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05001775 InvalidateBoundCmdBuffers(dev_data);
Jeff Bolzfdf96072018-04-10 14:32:18 -05001776 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001777}
Tobin Ehlis56a30942016-05-19 08:00:00 -06001778
John Zulauf6f3d2bd2018-10-29 17:08:42 -06001779// Update the drawing state for the affected descriptors.
1780// Set cb_node to this set and this set to cb_node.
1781// Add the bindings of the descriptor
1782// Set the layout based on the current descriptor layout (will mask subsequent layer mismatch errors)
1783// TODO: Modify the UpdateDrawState virtural functions to *only* set initial layout and not change layouts
Tobin Ehlisf9519102016-08-17 09:49:13 -06001784// Prereq: This should be called for a set that has been confirmed to be active for the given cb_node, meaning it's going
1785// to be used in a draw by the given cb_node
Jeremy Kniagere6827432020-04-01 09:05:56 -06001786void cvdescriptorset::DescriptorSet::UpdateDrawState(ValidationStateTracker *device_data, CMD_BUFFER_STATE *cb_node,
1787 CMD_TYPE cmd_type, const PIPELINE_STATE *pipe,
Karl Schultz7090a052020-11-10 08:54:21 -07001788 const BindingReqMap &binding_req_map, const char *function) {
Tony-LunarG77822802020-05-28 16:35:46 -06001789 if (!device_data->disabled[command_buffer_state] && !IsPushDescriptor()) {
Jeff Bolzafa429a2019-08-14 09:59:22 -05001790 // bind cb to this descriptor set
1791 // Add bindings for descriptor set, the set's pool, and individual objects in the set
Jeff Bolzadbfa852019-10-04 13:53:30 -05001792 if (device_data->AddCommandBufferBinding(cb_bindings, VulkanTypedHandle(set_, kVulkanObjectTypeDescriptorSet, this),
1793 cb_node)) {
1794 device_data->AddCommandBufferBinding(pool_state_->cb_bindings,
1795 VulkanTypedHandle(pool_state_->pool, kVulkanObjectTypeDescriptorPool, pool_state_),
1796 cb_node);
Jeff Bolzafa429a2019-08-14 09:59:22 -05001797 }
1798 }
Jeff Bolze18e7242019-08-12 20:55:22 -05001799
1800 // Descriptor UpdateDrawState functions do two things - associate resources to the command buffer,
1801 // and call image layout validation callbacks. If both are disabled, skip the entire loop.
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -06001802 if (device_data->disabled[command_buffer_state] && device_data->disabled[image_layout_validation]) {
Jeff Bolze18e7242019-08-12 20:55:22 -05001803 return;
1804 }
1805
Tobin Ehlisf9519102016-08-17 09:49:13 -06001806 // For the active slots, use set# to look up descriptorSet from boundDescriptorSets, and bind all of that descriptor set's
1807 // resources
locke-lunarg540b2252020-08-03 13:23:36 -06001808 CMD_BUFFER_STATE::CmdDrawDispatchInfo cmd_info = {};
John Zulauf79f06582021-02-27 18:38:39 -07001809 for (const auto &binding_req_pair : binding_req_map) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001810 auto index = layout_->GetIndexFromBinding(binding_req_pair.first);
locke-gb3ce08f2019-09-30 12:30:56 -06001811
Tony-LunarG62c5dba2018-12-20 14:27:23 -07001812 // 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 -07001813 auto flags = layout_->GetDescriptorBindingFlagsFromIndex(index);
Mike Schuchardt2df08912020-12-15 16:28:09 -08001814 if (flags & (VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT)) {
1815 if (!(flags & VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT)) {
locke-lunarg36045992020-08-20 16:54:37 -06001816 cmd_info.binding_infos.emplace_back(binding_req_pair);
locke-gb3ce08f2019-09-30 12:30:56 -06001817 }
Tony-LunarG62c5dba2018-12-20 14:27:23 -07001818 continue;
1819 }
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001820 auto range = layout_->GetGlobalIndexRangeFromIndex(index);
John Zulaufc483f442017-12-15 14:02:06 -07001821 for (uint32_t i = range.start; i < range.end; ++i) {
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07001822 descriptors_[i]->UpdateDrawState(device_data, cb_node);
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06001823 }
1824 }
locke-lunarg540b2252020-08-03 13:23:36 -06001825
1826 if (cmd_info.binding_infos.size() > 0) {
1827 cmd_info.cmd_type = cmd_type;
1828 cmd_info.function = function;
1829 if (cb_node->activeFramebuffer) {
1830 cmd_info.framebuffer = cb_node->activeFramebuffer->framebuffer;
locke-lunargfc78e932020-11-19 17:06:24 -07001831 cmd_info.attachments = cb_node->active_attachments;
1832 cmd_info.subpasses = cb_node->active_subpasses;
locke-lunarg540b2252020-08-03 13:23:36 -06001833 }
1834 cb_node->validate_descriptorsets_in_queuesubmit[set_].emplace_back(cmd_info);
1835 }
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06001836}
1837
John Zulauffbf3c202019-07-17 14:57:14 -06001838void cvdescriptorset::DescriptorSet::FilterOneBindingReq(const BindingReqMap::value_type &binding_req_pair, BindingReqMap *out_req,
1839 const TrackedBindings &bindings, uint32_t limit) {
1840 if (bindings.size() < limit) {
1841 const auto it = bindings.find(binding_req_pair.first);
1842 if (it == bindings.cend()) out_req->emplace(binding_req_pair);
John Zulauf48a6a702017-12-22 17:14:54 -07001843 }
1844}
Mark Lobodzinski2872f4a2018-09-03 17:00:53 -06001845
John Zulauffbf3c202019-07-17 14:57:14 -06001846void cvdescriptorset::DescriptorSet::FilterBindingReqs(const CMD_BUFFER_STATE &cb_state, const PIPELINE_STATE &pipeline,
1847 const BindingReqMap &in_req, BindingReqMap *out_req) const {
1848 // For const cleanliness we have to find in the maps...
1849 const auto validated_it = cached_validation_.find(&cb_state);
1850 if (validated_it == cached_validation_.cend()) {
1851 // We have nothing validated, copy in to out
1852 for (const auto &binding_req_pair : in_req) {
1853 out_req->emplace(binding_req_pair);
John Zulauf48a6a702017-12-22 17:14:54 -07001854 }
John Zulauffbf3c202019-07-17 14:57:14 -06001855 return;
John Zulauf48a6a702017-12-22 17:14:54 -07001856 }
John Zulauffbf3c202019-07-17 14:57:14 -06001857 const auto &validated = validated_it->second;
John Zulauf48a6a702017-12-22 17:14:54 -07001858
John Zulauffbf3c202019-07-17 14:57:14 -06001859 const auto image_sample_version_it = validated.image_samplers.find(&pipeline);
1860 const VersionedBindings *image_sample_version = nullptr;
1861 if (image_sample_version_it != validated.image_samplers.cend()) {
1862 image_sample_version = &(image_sample_version_it->second);
1863 }
1864 const auto &dynamic_buffers = validated.dynamic_buffers;
1865 const auto &non_dynamic_buffers = validated.non_dynamic_buffers;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001866 const auto &stats = layout_->GetBindingTypeStats();
John Zulauf48a6a702017-12-22 17:14:54 -07001867 for (const auto &binding_req_pair : in_req) {
1868 auto binding = binding_req_pair.first;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001869 VkDescriptorSetLayoutBinding const *layout_binding = layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
John Zulauf48a6a702017-12-22 17:14:54 -07001870 if (!layout_binding) {
1871 continue;
1872 }
1873 // Caching criteria differs per type.
1874 // If image_layout have changed , the image descriptors need to be validated against them.
sfricke-samsung60f29ec2021-03-10 20:37:25 -08001875 if (IsBufferDescriptor(layout_binding->descriptorType)) {
1876 if (IsDynamicDescriptor(layout_binding->descriptorType)) {
1877 FilterOneBindingReq(binding_req_pair, out_req, dynamic_buffers, stats.dynamic_buffer_count);
1878 } else {
1879 FilterOneBindingReq(binding_req_pair, out_req, non_dynamic_buffers, stats.non_dynamic_buffer_count);
1880 }
John Zulauf48a6a702017-12-22 17:14:54 -07001881 } else {
1882 // This is rather crude, as the changed layouts may not impact the bound descriptors,
1883 // but the simple "versioning" is a simple "dirt" test.
John Zulauffbf3c202019-07-17 14:57:14 -06001884 bool stale = true;
1885 if (image_sample_version) {
1886 const auto version_it = image_sample_version->find(binding);
1887 if (version_it != image_sample_version->cend() && (version_it->second == cb_state.image_layout_change_count)) {
1888 stale = false;
1889 }
1890 }
1891 if (stale) {
John Zulauf48a6a702017-12-22 17:14:54 -07001892 out_req->emplace(binding_req_pair);
1893 }
1894 }
1895 }
1896}
Tobin Ehlis9252c2b2016-07-21 14:40:22 -06001897
John Zulauffbf3c202019-07-17 14:57:14 -06001898void cvdescriptorset::DescriptorSet::UpdateValidationCache(const CMD_BUFFER_STATE &cb_state, const PIPELINE_STATE &pipeline,
1899 const BindingReqMap &updated_bindings) {
1900 // For const cleanliness we have to find in the maps...
1901 auto &validated = cached_validation_[&cb_state];
1902
1903 auto &image_sample_version = validated.image_samplers[&pipeline];
1904 auto &dynamic_buffers = validated.dynamic_buffers;
1905 auto &non_dynamic_buffers = validated.non_dynamic_buffers;
1906 for (const auto &binding_req_pair : updated_bindings) {
1907 auto binding = binding_req_pair.first;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001908 VkDescriptorSetLayoutBinding const *layout_binding = layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
John Zulauffbf3c202019-07-17 14:57:14 -06001909 if (!layout_binding) {
1910 continue;
1911 }
1912 // Caching criteria differs per type.
sfricke-samsung60f29ec2021-03-10 20:37:25 -08001913 if (IsBufferDescriptor(layout_binding->descriptorType)) {
1914 if (IsDynamicDescriptor(layout_binding->descriptorType)) {
1915 dynamic_buffers.emplace(binding);
1916 } else {
1917 non_dynamic_buffers.emplace(binding);
1918 }
John Zulauffbf3c202019-07-17 14:57:14 -06001919 } else {
1920 // Save the layout change version...
1921 image_sample_version[binding] = cb_state.image_layout_change_count;
1922 }
1923 }
1924}
1925
John Zulaufd2c3dae2019-12-12 11:02:17 -07001926cvdescriptorset::SamplerDescriptor::SamplerDescriptor(const ValidationStateTracker *dev_data, const VkSampler *immut)
Karl Schultz76d16a42020-11-11 05:05:33 -07001927 : immutable_(false) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001928 updated = false;
1929 descriptor_class = PlainSampler;
1930 if (immut) {
Karl Schultz76d16a42020-11-11 05:05:33 -07001931 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(*immut);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001932 immutable_ = true;
1933 updated = true;
1934 }
1935}
Tobin Ehlise2f80292016-06-02 10:08:53 -06001936// Validate given sampler. Currently this only checks to make sure it exists in the samplerMap
John Zulaufc93c4252019-06-25 09:19:49 -06001937bool CoreChecks::ValidateSampler(const VkSampler sampler) const { return (GetSamplerState(sampler) != nullptr); }
Tobin Ehlis56a30942016-05-19 08:00:00 -06001938
John Zulaufc93c4252019-06-25 09:19:49 -06001939bool CoreChecks::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type,
John Zulaufbd9b3412019-08-22 17:16:11 -06001940 const char *func_name, std::string *error_code, std::string *error_msg) const {
John Zulaufc93c4252019-06-25 09:19:49 -06001941 auto iv_state = GetImageViewState(image_view);
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001942 assert(iv_state);
1943
Tobin Ehlis81280962016-07-20 14:04:20 -06001944 // 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 -06001945 // Validate that imageLayout is compatible with aspect_mask and image format
1946 // and validate that image usage bits are correct for given usage
Tobin Ehlis8b26a382016-09-14 08:02:49 -06001947 VkImageAspectFlags aspect_mask = iv_state->create_info.subresourceRange.aspectMask;
1948 VkImage image = iv_state->create_info.image;
Tobin Ehlis1809f912016-05-25 09:24:36 -06001949 VkFormat format = VK_FORMAT_MAX_ENUM;
1950 VkImageUsageFlags usage = 0;
John Zulaufc93c4252019-06-25 09:19:49 -06001951 auto image_node = GetImageState(image);
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001952 assert(image_node);
Chris Forbes67757ff2017-07-21 13:59:01 -07001953
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001954 format = image_node->createInfo.format;
1955 usage = image_node->createInfo.usage;
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07001956 const auto stencil_usage_info = LvlFindInChain<VkImageStencilUsageCreateInfo>(image_node->createInfo.pNext);
Ricardo Garcia3f5984c2020-04-09 10:56:34 +02001957 if (stencil_usage_info) {
1958 usage |= stencil_usage_info->stencilUsage;
1959 }
Mark Lobodzinski03d00062020-06-15 14:35:45 -06001960
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001961 // Validate that memory is bound to image
Mark Lobodzinski03d00062020-06-15 14:35:45 -06001962 if (ValidateMemoryIsBoundToImage(image_node, func_name, "UNASSIGNED-CoreValidation-BoundResourceFreedMemoryAccess")) {
1963 *error_code = "UNASSIGNED-CoreValidation-BoundResourceFreedMemoryAccess";
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001964 *error_msg = "No memory bound to image.";
Tobin Ehlis1809f912016-05-25 09:24:36 -06001965 return false;
1966 }
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001967
1968 // KHR_maintenance1 allows rendering into 2D or 2DArray views which slice a 3D image,
1969 // but not binding them to descriptor sets.
1970 if (image_node->createInfo.imageType == VK_IMAGE_TYPE_3D && (iv_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_2D ||
1971 iv_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)) {
1972 *error_code = "VUID-VkDescriptorImageInfo-imageView-00343";
1973 *error_msg = "ImageView must not be a 2D or 2DArray view of a 3D image";
1974 return false;
1975 }
1976
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001977 // TODO : The various image aspect and format checks here are based on general spec language in 11.5 Image Views section under
1978 // vkCreateImageView(). What's the best way to create unique id for these cases?
Mark Lobodzinski3fc3d752019-06-24 14:22:46 -06001979 *error_code = "UNASSIGNED-CoreValidation-DrawState-InvalidImageView";
Dave Houlton1d2022c2017-03-29 11:43:58 -06001980 bool ds = FormatIsDepthOrStencil(format);
Tobin Ehlis1809f912016-05-25 09:24:36 -06001981 switch (image_layout) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001982 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
1983 // Only Color bit must be set
1984 if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
Tobin Ehlis1809f912016-05-25 09:24:36 -06001985 std::stringstream error_str;
Dave Houltona9df0ce2018-02-07 10:51:23 -07001986 error_str
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001987 << "ImageView (" << report_data->FormatHandle(image_view)
Dave Houltona9df0ce2018-02-07 10:51:23 -07001988 << ") 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 -06001989 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -06001990 return false;
1991 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001992 // format must NOT be DS
1993 if (ds) {
1994 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06001995 error_str << "ImageView (" << report_data->FormatHandle(image_view)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001996 << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but the image format is "
1997 << string_VkFormat(format) << " which is not a color format.";
1998 *error_msg = error_str.str();
1999 return false;
2000 }
2001 break;
2002 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
2003 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2004 // Depth or stencil bit must be set, but both must NOT be set
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06002005 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
2006 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
2007 // both must NOT be set
2008 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002009 error_str << "ImageView (" << report_data->FormatHandle(image_view)
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002010 << ") has both STENCIL and DEPTH aspects set";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002011 *error_msg = error_str.str();
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06002012 return false;
2013 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002014 } else if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
2015 // Neither were set
2016 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002017 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002018 << string_VkImageLayout(image_layout) << " but does not have STENCIL or DEPTH aspects set";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002019 *error_msg = error_str.str();
2020 return false;
Tobin Ehlisbbf3f912016-06-15 13:03:58 -06002021 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002022 // format must be DS
2023 if (!ds) {
2024 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002025 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002026 << string_VkImageLayout(image_layout) << " but the image format is " << string_VkFormat(format)
2027 << " which is not a depth/stencil format.";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002028 *error_msg = error_str.str();
2029 return false;
2030 }
2031 break;
2032 default:
2033 // For other layouts if the source is depth/stencil image, both aspect bits must not be set
2034 if (ds) {
2035 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
2036 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
2037 // both must NOT be set
2038 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002039 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has layout "
Mark Lobodzinski6b042922019-06-21 14:46:42 -06002040 << string_VkImageLayout(image_layout) << " and is using depth/stencil image of format "
2041 << string_VkFormat(format)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002042 << " but it has both STENCIL and DEPTH aspects set, which is illegal. When using a depth/stencil "
2043 "image in a descriptor set, please only set either VK_IMAGE_ASPECT_DEPTH_BIT or "
2044 "VK_IMAGE_ASPECT_STENCIL_BIT depending on whether it will be used for depth reads or stencil "
2045 "reads respectively.";
Mark Lobodzinski4d05d7a2019-06-25 09:12:06 -06002046 *error_code = "VUID-VkDescriptorImageInfo-imageView-01976";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002047 *error_msg = error_str.str();
2048 return false;
2049 }
2050 }
2051 }
2052 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002053 }
2054 // Now validate that usage flags are correctly set for given type of update
Tobin Ehlisfb4cf712016-10-10 14:02:48 -06002055 // 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 -06002056 // TODO : The various image usage bit requirements are in general spec language for VkImageUsageFlags bit block in 11.3 Images
2057 // under vkCreateImage()
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002058 const char *error_usage_bit = nullptr;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002059 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002060 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
sfricke-samsung088f1242020-06-06 02:15:35 -07002061 if (iv_state->samplerConversion != VK_NULL_HANDLE) {
2062 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-01946";
2063 std::stringstream error_str;
2064 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ")"
2065 << "used as a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE can't be created with VkSamplerYcbcrConversion";
2066 *error_msg = error_str.str();
2067 return false;
2068 }
2069 // drop through
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002070 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
2071 if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
2072 error_usage_bit = "VK_IMAGE_USAGE_SAMPLED_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08002073 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00337";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002074 }
2075 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002076 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002077 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
2078 if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
2079 error_usage_bit = "VK_IMAGE_USAGE_STORAGE_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08002080 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00339";
sfricke-samsungada55a12020-08-15 03:39:41 -07002081 } else if ((VK_IMAGE_LAYOUT_GENERAL != image_layout) || ((VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR != image_layout) &&
2082 (device_extensions.vk_khr_shared_presentable_image))) {
sfricke-samsungf1058982020-09-10 22:36:49 -07002083 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04152";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002084 std::stringstream error_str;
sfricke-samsungada55a12020-08-15 03:39:41 -07002085 error_str << "Descriptor update with descriptorType VK_DESCRIPTOR_TYPE_STORAGE_IMAGE"
2086 << " is being updated with invalid imageLayout " << string_VkImageLayout(image_layout) << " for image "
2087 << report_data->FormatHandle(image) << " in imageView " << report_data->FormatHandle(image_view)
2088 << ". Allowed layouts are: VK_IMAGE_LAYOUT_GENERAL";
2089 if (device_extensions.vk_khr_shared_presentable_image) {
2090 error_str << " or VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR";
Tobin Ehlisbb03e5f2017-05-11 08:52:51 -06002091 }
sfricke-samsungada55a12020-08-15 03:39:41 -07002092 *error_msg = error_str.str();
2093 return false;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002094 }
2095 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002096 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002097 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
2098 if (!(usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
2099 error_usage_bit = "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT";
sfricke-samsung7923f212020-02-29 21:17:35 -08002100 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00338";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002101 }
2102 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002103 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002104 default:
2105 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -06002106 }
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002107 if (error_usage_bit) {
Tobin Ehlis1809f912016-05-25 09:24:36 -06002108 std::stringstream error_str;
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002109 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") with usage mask " << std::hex << std::showbase
2110 << usage << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have "
2111 << error_usage_bit << " set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002112 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -06002113 return false;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002114 }
John Zulauff4c07882019-01-24 14:03:36 -07002115
sfricke-samsungada55a12020-08-15 03:39:41 -07002116 // All the following types share the same image layouts
2117 // checkf or Storage Images above
2118 if ((type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) || (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
2119 (type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
John Zulauff4c07882019-01-24 14:03:36 -07002120 // Test that the layout is compatible with the descriptorType for the two sampled image types
2121 const static std::array<VkImageLayout, 3> valid_layouts = {
Jeremy Hayesd0549f62019-06-05 10:15:36 -06002122 {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 -07002123
2124 struct ExtensionLayout {
2125 VkImageLayout layout;
Tony-LunarG2ec96bb2019-11-26 13:43:02 -07002126 ExtEnabled DeviceExtensions::*extension;
John Zulauff4c07882019-01-24 14:03:36 -07002127 };
Jeremy Gebben579aaca2021-02-15 13:36:18 -07002128 const static std::array<ExtensionLayout, 5> extended_layouts{{
2129 // Note double brace req'd for aggregate initialization
2130 {VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR, &DeviceExtensions::vk_khr_shared_presentable_image},
2131 {VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, &DeviceExtensions::vk_khr_maintenance2},
2132 {VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, &DeviceExtensions::vk_khr_maintenance2},
2133 {VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, &DeviceExtensions::vk_khr_synchronization_2},
2134 {VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, &DeviceExtensions::vk_khr_synchronization_2},
2135 }};
John Zulaufc93c4252019-06-25 09:19:49 -06002136 auto is_layout = [image_layout, this](const ExtensionLayout &ext_layout) {
2137 return device_extensions.*(ext_layout.extension) && (ext_layout.layout == image_layout);
John Zulauff4c07882019-01-24 14:03:36 -07002138 };
2139
2140 bool valid_layout = (std::find(valid_layouts.cbegin(), valid_layouts.cend(), image_layout) != valid_layouts.cend()) ||
2141 std::any_of(extended_layouts.cbegin(), extended_layouts.cend(), is_layout);
2142
2143 if (!valid_layout) {
sfricke-samsungf1058982020-09-10 22:36:49 -07002144 // The following works as currently all 3 descriptor types share the same set of valid layouts
sfricke-samsungada55a12020-08-15 03:39:41 -07002145 switch (type) {
2146 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
Shannon McPherson2c793ba2020-08-28 12:13:24 -06002147 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04149";
sfricke-samsungada55a12020-08-15 03:39:41 -07002148 break;
2149 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
Shannon McPherson2c793ba2020-08-28 12:13:24 -06002150 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04150";
sfricke-samsungada55a12020-08-15 03:39:41 -07002151 break;
2152 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
sfricke-samsungf1058982020-09-10 22:36:49 -07002153 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-04151";
sfricke-samsungada55a12020-08-15 03:39:41 -07002154 break;
2155 default:
2156 break;
2157 }
John Zulauff4c07882019-01-24 14:03:36 -07002158 std::stringstream error_str;
2159 error_str << "Descriptor update with descriptorType " << string_VkDescriptorType(type)
Mark Lobodzinski74eddba2019-06-21 14:16:33 -06002160 << " is being updated with invalid imageLayout " << string_VkImageLayout(image_layout) << " for image "
Mark Lobodzinski298f0fd2020-04-09 11:50:19 -06002161 << report_data->FormatHandle(image) << " in imageView " << report_data->FormatHandle(image_view)
John Zulauff4c07882019-01-24 14:03:36 -07002162 << ". Allowed layouts are: VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "
2163 << "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL";
2164 for (auto &ext_layout : extended_layouts) {
John Zulaufc93c4252019-06-25 09:19:49 -06002165 if (device_extensions.*(ext_layout.extension)) {
John Zulauff4c07882019-01-24 14:03:36 -07002166 error_str << ", " << string_VkImageLayout(ext_layout.layout);
2167 }
2168 }
2169 *error_msg = error_str.str();
2170 return false;
2171 }
2172 }
2173
sfricke-samsungbd0e8052020-06-06 01:36:39 -07002174 if ((type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) || (type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
2175 const VkComponentMapping components = iv_state->create_info.components;
2176 if (IsIdentitySwizzle(components) == false) {
2177 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00336";
2178 std::stringstream error_str;
2179 error_str << "ImageView (" << report_data->FormatHandle(image_view) << ") has a non-identiy swizzle component, "
2180 << " r swizzle = " << string_VkComponentSwizzle(components.r) << ","
2181 << " g swizzle = " << string_VkComponentSwizzle(components.g) << ","
2182 << " b swizzle = " << string_VkComponentSwizzle(components.b) << ","
2183 << " a swizzle = " << string_VkComponentSwizzle(components.a) << ".";
2184 *error_msg = error_str.str();
2185 return false;
2186 }
2187 }
2188
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002189 return true;
2190}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002191
John Zulaufd2c3dae2019-12-12 11:02:17 -07002192void cvdescriptorset::SamplerDescriptor::WriteUpdate(const ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update,
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002193 const uint32_t index) {
Chris Forbesfea2c542018-04-13 09:34:15 -07002194 if (!immutable_) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002195 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(update->pImageInfo[index].sampler);
Chris Forbesfea2c542018-04-13 09:34:15 -07002196 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002197 updated = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002198}
2199
John Zulaufd2c3dae2019-12-12 11:02:17 -07002200void cvdescriptorset::SamplerDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tony-LunarG80358322021-04-16 07:58:13 -06002201 updated = true;
2202 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2203 if (src->descriptor_class == Mutable) {
2204 this->descriptor_class = Mutable;
2205 return;
2206 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002207 if (!immutable_) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002208 sampler_state_ = static_cast<const SamplerDescriptor *>(src)->sampler_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002209 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002210}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002211
John Zulauffbf3c202019-07-17 14:57:14 -06002212void cvdescriptorset::SamplerDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002213 if (!immutable_) {
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002214 auto sampler_state = GetSamplerState();
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07002215 if (sampler_state) dev_data->AddCommandBufferBindingSampler(cb_node, sampler_state);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002216 }
2217}
2218
John Zulaufd2c3dae2019-12-12 11:02:17 -07002219cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(const ValidationStateTracker *dev_data, const VkSampler *immut)
Karl Schultz76d16a42020-11-11 05:05:33 -07002220 : immutable_(false), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002221 updated = false;
2222 descriptor_class = ImageSampler;
2223 if (immut) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002224 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(*immut);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002225 immutable_ = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002226 }
2227}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002228
John Zulaufd2c3dae2019-12-12 11:02:17 -07002229void cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(const ValidationStateTracker *dev_data,
2230 const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002231 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002232 const auto &image_info = update->pImageInfo[index];
Chris Forbesfea2c542018-04-13 09:34:15 -07002233 if (!immutable_) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002234 sampler_state_ = dev_data->GetConstCastShared<SAMPLER_STATE>(image_info.sampler);
Chris Forbesfea2c542018-04-13 09:34:15 -07002235 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002236 image_layout_ = image_info.imageLayout;
Karl Schultz76d16a42020-11-11 05:05:33 -07002237 image_view_state_ = dev_data->GetConstCastShared<IMAGE_VIEW_STATE>(image_info.imageView);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002238}
2239
John Zulaufd2c3dae2019-12-12 11:02:17 -07002240void cvdescriptorset::ImageSamplerDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tony-LunarG80358322021-04-16 07:58:13 -06002241 updated = true;
2242 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2243 if (src->descriptor_class == Mutable) {
2244 this->descriptor_class = Mutable;
2245 return;
2246 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002247 if (!immutable_) {
Karl Schultz76d16a42020-11-11 05:05:33 -07002248 sampler_state_ = static_cast<const ImageSamplerDescriptor *>(src)->sampler_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002249 }
Karl Schultz76d16a42020-11-11 05:05:33 -07002250 image_layout_ = static_cast<const ImageSamplerDescriptor *>(src)->image_layout_;
2251 image_view_state_ = static_cast<const ImageSamplerDescriptor *>(src)->image_view_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002252}
2253
John Zulauffbf3c202019-07-17 14:57:14 -06002254void cvdescriptorset::ImageSamplerDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Tobin Ehlis81e46372016-08-17 13:33:44 -06002255 // First add binding for any non-immutable sampler
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002256 if (!immutable_) {
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002257 auto sampler_state = GetSamplerState();
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07002258 if (sampler_state) dev_data->AddCommandBufferBindingSampler(cb_node, sampler_state);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002259 }
Tobin Ehlis81e46372016-08-17 13:33:44 -06002260 // Add binding for image
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002261 auto iv_state = GetImageViewState();
Tobin Ehlis8b26a382016-09-14 08:02:49 -06002262 if (iv_state) {
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07002263 dev_data->AddCommandBufferBindingImageView(cb_node, iv_state);
John Zulauffbf3c202019-07-17 14:57:14 -06002264 dev_data->CallSetImageViewInitialLayoutCallback(cb_node, *iv_state, image_layout_);
Jeff Bolz148d94e2018-12-13 21:25:56 -06002265 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002266}
2267
sfricke-samsung4ba7d6e2021-03-06 20:56:35 -08002268cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type) : image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002269 updated = false;
2270 descriptor_class = Image;
Petr Kraus13c98a62017-12-09 00:22:39 +01002271}
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002272
John Zulaufd2c3dae2019-12-12 11:02:17 -07002273void cvdescriptorset::ImageDescriptor::WriteUpdate(const ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update,
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002274 const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002275 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002276 const auto &image_info = update->pImageInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06002277 image_layout_ = image_info.imageLayout;
Karl Schultz76d16a42020-11-11 05:05:33 -07002278 image_view_state_ = dev_data->GetConstCastShared<IMAGE_VIEW_STATE>(image_info.imageView);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002279}
2280
John Zulaufd2c3dae2019-12-12 11:02:17 -07002281void cvdescriptorset::ImageDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002282 updated = true;
Tony-LunarG80358322021-04-16 07:58:13 -06002283 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2284 if (src->descriptor_class == Mutable) {
2285 this->descriptor_class = Mutable;
2286 return;
2287 }
2288
Karl Schultz76d16a42020-11-11 05:05:33 -07002289 image_layout_ = static_cast<const ImageDescriptor *>(src)->image_layout_;
2290 image_view_state_ = static_cast<const ImageDescriptor *>(src)->image_view_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002291}
2292
John Zulauffbf3c202019-07-17 14:57:14 -06002293void cvdescriptorset::ImageDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Tobin Ehlis81e46372016-08-17 13:33:44 -06002294 // Add binding for image
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002295 auto iv_state = GetImageViewState();
Tobin Ehlis8b26a382016-09-14 08:02:49 -06002296 if (iv_state) {
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07002297 dev_data->AddCommandBufferBindingImageView(cb_node, iv_state);
John Zulauffbf3c202019-07-17 14:57:14 -06002298 dev_data->CallSetImageViewInitialLayoutCallback(cb_node, *iv_state, image_layout_);
Jeff Bolz148d94e2018-12-13 21:25:56 -06002299 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002300}
2301
sfricke-samsung4ba7d6e2021-03-06 20:56:35 -08002302cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type) : offset_(0), range_(0) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002303 updated = false;
2304 descriptor_class = GeneralBuffer;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002305}
John Zulaufd2c3dae2019-12-12 11:02:17 -07002306void cvdescriptorset::BufferDescriptor::WriteUpdate(const ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update,
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002307 const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002308 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06002309 const auto &buffer_info = update->pBufferInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06002310 offset_ = buffer_info.offset;
2311 range_ = buffer_info.range;
Karl Schultz76d16a42020-11-11 05:05:33 -07002312 buffer_state_ = dev_data->GetConstCastShared<BUFFER_STATE>(buffer_info.buffer);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002313}
2314
John Zulaufd2c3dae2019-12-12 11:02:17 -07002315void cvdescriptorset::BufferDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002316 updated = true;
Tony-LunarG80358322021-04-16 07:58:13 -06002317 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2318 if (src->descriptor_class == Mutable) {
2319 this->descriptor_class = Mutable;
2320 return;
2321 }
Karl Schultz76d16a42020-11-11 05:05:33 -07002322 const auto buff_desc = static_cast<const BufferDescriptor *>(src);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002323 offset_ = buff_desc->offset_;
2324 range_ = buff_desc->range_;
Karl Schultz76d16a42020-11-11 05:05:33 -07002325 buffer_state_ = buff_desc->buffer_state_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002326}
2327
John Zulauffbf3c202019-07-17 14:57:14 -06002328void cvdescriptorset::BufferDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002329 auto buffer_node = GetBufferState();
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07002330 if (buffer_node) dev_data->AddCommandBufferBindingBuffer(cb_node, buffer_node);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002331}
2332
sfricke-samsung4ba7d6e2021-03-06 20:56:35 -08002333cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002334 updated = false;
2335 descriptor_class = TexelBuffer;
Petr Kraus13c98a62017-12-09 00:22:39 +01002336}
Tobin Ehlis56a30942016-05-19 08:00:00 -06002337
John Zulaufd2c3dae2019-12-12 11:02:17 -07002338void cvdescriptorset::TexelDescriptor::WriteUpdate(const ValidationStateTracker *dev_data, const VkWriteDescriptorSet *update,
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002339 const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002340 updated = true;
Karl Schultz76d16a42020-11-11 05:05:33 -07002341 buffer_view_state_ = dev_data->GetConstCastShared<BUFFER_VIEW_STATE>(update->pTexelBufferView[index]);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06002342}
2343
John Zulaufd2c3dae2019-12-12 11:02:17 -07002344void cvdescriptorset::TexelDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002345 updated = true;
Tony-LunarG80358322021-04-16 07:58:13 -06002346 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2347 if (src->descriptor_class == Mutable) {
2348 this->descriptor_class = Mutable;
2349 return;
2350 }
Karl Schultz76d16a42020-11-11 05:05:33 -07002351 buffer_view_state_ = static_cast<const TexelDescriptor *>(src)->buffer_view_state_;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002352}
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002353
John Zulauffbf3c202019-07-17 14:57:14 -06002354void cvdescriptorset::TexelDescriptor::UpdateDrawState(ValidationStateTracker *dev_data, CMD_BUFFER_STATE *cb_node) {
Jeff Bolzfaffeb32019-10-04 12:47:16 -05002355 auto bv_state = GetBufferViewState();
Tobin Ehlis8b872462016-09-14 08:12:08 -06002356 if (bv_state) {
Mark Lobodzinskifae179e2019-03-08 16:47:08 -07002357 dev_data->AddCommandBufferBindingBufferView(cb_node, bv_state);
Tobin Ehlis81e46372016-08-17 13:33:44 -06002358 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06002359}
2360
Jeff Bolz95176d02020-04-01 00:36:16 -05002361cvdescriptorset::AccelerationStructureDescriptor::AccelerationStructureDescriptor(const VkDescriptorType type)
sourav parmarcd5fb182020-07-17 12:58:44 -07002362 : acc_(VK_NULL_HANDLE), acc_nv_(VK_NULL_HANDLE) {
Jeff Bolz95176d02020-04-01 00:36:16 -05002363 updated = false;
sourav parmarcd5fb182020-07-17 12:58:44 -07002364 is_khr_ = false;
Jeff Bolz95176d02020-04-01 00:36:16 -05002365 descriptor_class = AccelerationStructure;
2366}
2367void cvdescriptorset::AccelerationStructureDescriptor::WriteUpdate(const ValidationStateTracker *dev_data,
2368 const VkWriteDescriptorSet *update, const uint32_t index) {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07002369 const auto *acc_info = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureKHR>(update->pNext);
2370 const auto *acc_info_nv = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureNV>(update->pNext);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002371 assert(acc_info || acc_info_nv);
2372 is_khr_ = (acc_info != NULL);
Jeff Bolz95176d02020-04-01 00:36:16 -05002373 updated = true;
sourav parmarcd5fb182020-07-17 12:58:44 -07002374 if (is_khr_) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002375 acc_ = acc_info->pAccelerationStructures[index];
sourav parmarcd5fb182020-07-17 12:58:44 -07002376 acc_state_ = dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE_KHR>(acc_);
2377 } else {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002378 acc_nv_ = acc_info_nv->pAccelerationStructures[index];
sourav parmarcd5fb182020-07-17 12:58:44 -07002379 acc_state_nv_ = dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE>(acc_nv_);
2380 }
Jeff Bolz95176d02020-04-01 00:36:16 -05002381}
2382
2383void cvdescriptorset::AccelerationStructureDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
2384 auto acc_desc = static_cast<const AccelerationStructureDescriptor *>(src);
2385 updated = true;
Tony-LunarG80358322021-04-16 07:58:13 -06002386 // Mutable descriptors not currently tracked or validated. If copied from mutable, set to mutable to keep from validating.
2387 if (src->descriptor_class == Mutable) {
2388 this->descriptor_class = Mutable;
2389 return;
2390 }
sourav parmarcd5fb182020-07-17 12:58:44 -07002391 if (is_khr_) {
2392 acc_ = acc_desc->acc_;
2393 acc_state_ = dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE_KHR>(acc_);
2394 } else {
2395 acc_nv_ = acc_desc->acc_nv_;
2396 acc_state_nv_ = dev_data->GetConstCastShared<ACCELERATION_STRUCTURE_STATE>(acc_nv_);
2397 }
Jeff Bolz95176d02020-04-01 00:36:16 -05002398}
2399
2400void cvdescriptorset::AccelerationStructureDescriptor::UpdateDrawState(ValidationStateTracker *dev_data,
2401 CMD_BUFFER_STATE *cb_node) {
sourav parmarcd5fb182020-07-17 12:58:44 -07002402 if (is_khr_) {
2403 auto acc_node = GetAccelerationStructureStateKHR();
2404 if (acc_node) dev_data->AddCommandBufferBindingAccelerationStructure(cb_node, acc_node);
2405 } else {
2406 auto acc_node = GetAccelerationStructureStateNV();
2407 if (acc_node) dev_data->AddCommandBufferBindingAccelerationStructure(cb_node, acc_node);
2408 }
Jeff Bolz95176d02020-04-01 00:36:16 -05002409}
2410
Tony-LunarGf563b362021-03-18 16:13:18 -06002411cvdescriptorset::MutableDescriptor::MutableDescriptor() {
2412 updated = false;
2413 descriptor_class = Mutable;
2414 active_descriptor_class_ = NoDescriptorClass;
2415}
2416
2417void cvdescriptorset::MutableDescriptor::WriteUpdate(const ValidationStateTracker *dev_data,
2418 const VkWriteDescriptorSet *update, const uint32_t index) {
2419 updated = true;
2420}
2421
2422void cvdescriptorset::MutableDescriptor::CopyUpdate(const ValidationStateTracker *dev_data, const Descriptor *src) {
2423 updated = true;
2424}
2425
2426void cvdescriptorset::MutableDescriptor::UpdateDrawState(ValidationStateTracker *dev_data,
2427 CMD_BUFFER_STATE *cb_node) {
2428}
2429
Tobin Ehlis300888c2016-05-18 13:43:26 -06002430// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
2431// sets, and then calls their respective Validate[Write|Copy]Update functions.
2432// If the update hits an issue for which the callback returns "true", meaning that the call down the chain should
2433// be skipped, then true is returned.
2434// If there is no issue with the update, then false is returned.
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002435bool CoreChecks::ValidateUpdateDescriptorSets(uint32_t write_count, const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05002436 const VkCopyDescriptorSet *p_cds, const char *func_name) const {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002437 bool skip = false;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002438 // Validate Write updates
Tobin Ehlis56a30942016-05-19 08:00:00 -06002439 for (uint32_t i = 0; i < write_count; i++) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002440 auto dest_set = p_wds[i].dstSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002441 auto set_node = GetSetNode(dest_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002442 if (!set_node) {
sfricke-samsungbda4a852021-03-06 20:58:01 -08002443 skip |= LogError(dest_set, kVUID_Core_DrawState_InvalidDescriptorSet,
2444 "Cannot call %s on %s that has not been allocated in pDescriptorWrites[%u].", func_name,
2445 report_data->FormatHandle(dest_set).c_str(), i);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002446 } else {
Dave Houltond8ed0212018-05-16 17:18:24 -06002447 std::string error_code;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002448 std::string error_str;
John Zulaufc93c4252019-06-25 09:19:49 -06002449 if (!ValidateWriteUpdate(set_node, &p_wds[i], func_name, &error_code, &error_str)) {
sfricke-samsungbda4a852021-03-06 20:58:01 -08002450 skip |=
2451 LogError(dest_set, error_code, "%s pDescriptorWrites[%u] failed write update validation for %s with error: %s.",
2452 func_name, i, report_data->FormatHandle(dest_set).c_str(), error_str.c_str());
Tobin Ehlis300888c2016-05-18 13:43:26 -06002453 }
2454 }
sourav parmara24fb7b2020-05-26 10:50:04 -07002455 if (p_wds[i].pNext) {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07002456 const auto *pnext_struct = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureKHR>(p_wds[i].pNext);
Mark Lobodzinski17dc4602020-05-29 07:48:40 -06002457 if (pnext_struct) {
2458 for (uint32_t j = 0; j < pnext_struct->accelerationStructureCount; ++j) {
sourav parmarcd5fb182020-07-17 12:58:44 -07002459 const ACCELERATION_STRUCTURE_STATE_KHR *as_state =
2460 GetAccelerationStructureStateKHR(pnext_struct->pAccelerationStructures[j]);
2461 if (as_state && (as_state->create_infoKHR.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR &&
sourav parmar766e2a72020-12-03 16:17:11 -08002462 (as_state->create_infoKHR.type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR &&
2463 as_state->create_infoKHR.type != VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR))) {
sourav parmara24fb7b2020-05-26 10:50:04 -07002464 skip |=
sourav parmarcd5fb182020-07-17 12:58:44 -07002465 LogError(dest_set, "VUID-VkWriteDescriptorSetAccelerationStructureKHR-pAccelerationStructures-03579",
sfricke-samsungbda4a852021-03-06 20:58:01 -08002466 "%s: For pDescriptorWrites[%u] acceleration structure in pAccelerationStructures[%u] must "
2467 "have been created with "
sourav parmarbcee7512020-12-28 14:34:49 -08002468 "VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR or VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR.",
sfricke-samsungbda4a852021-03-06 20:58:01 -08002469 func_name, i, j);
sourav parmara24fb7b2020-05-26 10:50:04 -07002470 }
2471 }
2472 }
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07002473 const auto *pnext_struct_nv = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureNV>(p_wds[i].pNext);
sourav parmarcd5fb182020-07-17 12:58:44 -07002474 if (pnext_struct_nv) {
2475 for (uint32_t j = 0; j < pnext_struct_nv->accelerationStructureCount; ++j) {
2476 const ACCELERATION_STRUCTURE_STATE *as_state =
2477 GetAccelerationStructureStateNV(pnext_struct_nv->pAccelerationStructures[j]);
2478 if (as_state && (as_state->create_infoNV.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV &&
2479 as_state->create_infoNV.info.type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV)) {
2480 skip |= LogError(dest_set, "VUID-VkWriteDescriptorSetAccelerationStructureNV-pAccelerationStructures-03748",
sfricke-samsungbda4a852021-03-06 20:58:01 -08002481 "%s: For pDescriptorWrites[%u] acceleration structure in pAccelerationStructures[%u] must "
2482 "have been created with"
sourav parmarcd5fb182020-07-17 12:58:44 -07002483 " VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV.",
sfricke-samsungbda4a852021-03-06 20:58:01 -08002484 func_name, i, j);
sourav parmarcd5fb182020-07-17 12:58:44 -07002485 }
2486 }
2487 }
sourav parmara24fb7b2020-05-26 10:50:04 -07002488 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002489 }
2490 // Now validate copy updates
Tobin Ehlis56a30942016-05-19 08:00:00 -06002491 for (uint32_t i = 0; i < copy_count; ++i) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002492 auto dst_set = p_cds[i].dstSet;
2493 auto src_set = p_cds[i].srcSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002494 auto src_node = GetSetNode(src_set);
2495 auto dst_node = GetSetNode(dst_set);
Tobin Ehlisa1712752017-01-04 09:41:47 -07002496 // Object_tracker verifies that src & dest descriptor set are valid
2497 assert(src_node);
2498 assert(dst_node);
Dave Houltond8ed0212018-05-16 17:18:24 -06002499 std::string error_code;
Tobin Ehlisa1712752017-01-04 09:41:47 -07002500 std::string error_str;
John Zulaufc93c4252019-06-25 09:19:49 -06002501 if (!ValidateCopyUpdate(&p_cds[i], dst_node, src_node, func_name, &error_code, &error_str)) {
Mark Lobodzinski9d38ea22020-03-16 18:22:16 -06002502 LogObjectList objlist(dst_set);
2503 objlist.add(src_set);
sfricke-samsungbda4a852021-03-06 20:58:01 -08002504 skip |= LogError(objlist, error_code, "%s pDescriptorCopies[%u] failed copy update from %s to %s with error: %s.",
2505 func_name, i, report_data->FormatHandle(src_set).c_str(), report_data->FormatHandle(dst_set).c_str(),
2506 error_str.c_str());
Tobin Ehlis300888c2016-05-18 13:43:26 -06002507 }
2508 }
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06002509 return skip;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002510}
2511// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
2512// sets, and then calls their respective Perform[Write|Copy]Update functions.
2513// Prerequisite : ValidateUpdateDescriptorSets() should be called and return "false" prior to calling PerformUpdateDescriptorSets()
2514// with the same set of updates.
2515// This is split from the validate code to allow validation prior to calling down the chain, and then update after
2516// calling down the chain.
John Zulaufe3b35f32019-06-25 14:21:21 -06002517void cvdescriptorset::PerformUpdateDescriptorSets(ValidationStateTracker *dev_data, uint32_t write_count,
2518 const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
2519 const VkCopyDescriptorSet *p_cds) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06002520 // Write updates first
2521 uint32_t i = 0;
2522 for (i = 0; i < write_count; ++i) {
2523 auto dest_set = p_wds[i].dstSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002524 auto set_node = dev_data->GetSetNode(dest_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002525 if (set_node) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05002526 set_node->PerformWriteUpdate(dev_data, &p_wds[i]);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002527 }
2528 }
2529 // Now copy updates
2530 for (i = 0; i < copy_count; ++i) {
2531 auto dst_set = p_cds[i].dstSet;
2532 auto src_set = p_cds[i].srcSet;
Mark Lobodzinskifc2f0d32019-03-06 11:25:39 -07002533 auto src_node = dev_data->GetSetNode(src_set);
2534 auto dst_node = dev_data->GetSetNode(dst_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06002535 if (src_node && dst_node) {
Jeff Bolz41a1ced2019-10-11 11:40:49 -05002536 dst_node->PerformCopyUpdate(dev_data, &p_cds[i], src_node);
Tobin Ehlis300888c2016-05-18 13:43:26 -06002537 }
2538 }
2539}
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002540
John Zulaufe3b35f32019-06-25 14:21:21 -06002541cvdescriptorset::DecodedTemplateUpdate::DecodedTemplateUpdate(const ValidationStateTracker *device_data,
2542 VkDescriptorSet descriptorSet, const TEMPLATE_STATE *template_state,
2543 const void *pData, VkDescriptorSetLayout push_layout) {
John Zulaufb845eb22018-10-12 11:41:06 -06002544 auto const &create_info = template_state->create_info;
2545 inline_infos.resize(create_info.descriptorUpdateEntryCount); // Make sure we have one if we need it
sourav parmar480d2772021-01-24 22:24:54 -08002546 inline_infos_khr.resize(create_info.descriptorUpdateEntryCount);
2547 inline_infos_nv.resize(create_info.descriptorUpdateEntryCount);
John Zulaufb845eb22018-10-12 11:41:06 -06002548 desc_writes.reserve(create_info.descriptorUpdateEntryCount); // emplaced, so reserved without initialization
John Zulauf1d27e0a2018-11-05 10:12:48 -07002549 VkDescriptorSetLayout effective_dsl = create_info.templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
2550 ? create_info.descriptorSetLayout
2551 : push_layout;
Jeff Bolz6ae39612019-10-11 20:57:36 -05002552 auto layout_obj = device_data->GetDescriptorSetLayoutShared(effective_dsl);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002553
2554 // Create a WriteDescriptorSet struct for each template update entry
2555 for (uint32_t i = 0; i < create_info.descriptorUpdateEntryCount; i++) {
2556 auto binding_count = layout_obj->GetDescriptorCountFromBinding(create_info.pDescriptorUpdateEntries[i].dstBinding);
2557 auto binding_being_updated = create_info.pDescriptorUpdateEntries[i].dstBinding;
2558 auto dst_array_element = create_info.pDescriptorUpdateEntries[i].dstArrayElement;
2559
John Zulaufb6d71202017-12-22 16:47:09 -07002560 desc_writes.reserve(desc_writes.size() + create_info.pDescriptorUpdateEntries[i].descriptorCount);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002561 for (uint32_t j = 0; j < create_info.pDescriptorUpdateEntries[i].descriptorCount; j++) {
2562 desc_writes.emplace_back();
2563 auto &write_entry = desc_writes.back();
2564
2565 size_t offset = create_info.pDescriptorUpdateEntries[i].offset + j * create_info.pDescriptorUpdateEntries[i].stride;
2566 char *update_entry = (char *)(pData) + offset;
2567
2568 if (dst_array_element >= binding_count) {
2569 dst_array_element = 0;
Mark Lobodzinski4aa479d2017-03-10 09:14:00 -07002570 binding_being_updated = layout_obj->GetNextValidBinding(binding_being_updated);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002571 }
2572
2573 write_entry.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2574 write_entry.pNext = NULL;
2575 write_entry.dstSet = descriptorSet;
2576 write_entry.dstBinding = binding_being_updated;
2577 write_entry.dstArrayElement = dst_array_element;
2578 write_entry.descriptorCount = 1;
2579 write_entry.descriptorType = create_info.pDescriptorUpdateEntries[i].descriptorType;
2580
2581 switch (create_info.pDescriptorUpdateEntries[i].descriptorType) {
2582 case VK_DESCRIPTOR_TYPE_SAMPLER:
2583 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2584 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2585 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2586 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2587 write_entry.pImageInfo = reinterpret_cast<VkDescriptorImageInfo *>(update_entry);
2588 break;
2589
2590 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2591 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2592 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2593 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2594 write_entry.pBufferInfo = reinterpret_cast<VkDescriptorBufferInfo *>(update_entry);
2595 break;
2596
2597 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2598 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2599 write_entry.pTexelBufferView = reinterpret_cast<VkBufferView *>(update_entry);
2600 break;
Dave Houlton142c4cb2018-10-17 15:04:41 -06002601 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: {
2602 VkWriteDescriptorSetInlineUniformBlockEXT *inline_info = &inline_infos[i];
2603 inline_info->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT;
2604 inline_info->pNext = nullptr;
2605 inline_info->dataSize = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2606 inline_info->pData = update_entry;
2607 write_entry.pNext = inline_info;
Ricardo Garciafee15732019-05-28 11:13:31 +02002608 // descriptorCount must match the dataSize member of the VkWriteDescriptorSetInlineUniformBlockEXT structure
2609 write_entry.descriptorCount = inline_info->dataSize;
Dave Houlton142c4cb2018-10-17 15:04:41 -06002610 // skip the rest of the array, they just represent bytes in the update
2611 j = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2612 break;
2613 }
sourav parmar480d2772021-01-24 22:24:54 -08002614 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: {
2615 VkWriteDescriptorSetAccelerationStructureKHR *inline_info_khr = &inline_infos_khr[i];
2616 inline_info_khr->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
2617 inline_info_khr->pNext = nullptr;
2618 inline_info_khr->accelerationStructureCount = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2619 inline_info_khr->pAccelerationStructures = reinterpret_cast<VkAccelerationStructureKHR *>(update_entry);
2620 write_entry.pNext = inline_info_khr;
2621 break;
2622 }
2623 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: {
2624 VkWriteDescriptorSetAccelerationStructureNV *inline_info_nv = &inline_infos_nv[i];
2625 inline_info_nv->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV;
2626 inline_info_nv->pNext = nullptr;
2627 inline_info_nv->accelerationStructureCount = create_info.pDescriptorUpdateEntries[i].descriptorCount;
2628 inline_info_nv->pAccelerationStructures = reinterpret_cast<VkAccelerationStructureNV *>(update_entry);
2629 write_entry.pNext = inline_info_nv;
2630 break;
2631 }
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07002632 default:
2633 assert(0);
2634 break;
2635 }
2636 dst_array_element++;
2637 }
2638 }
John Zulaufb845eb22018-10-12 11:41:06 -06002639}
John Zulaufb45fdc32018-10-12 15:14:17 -06002640// These helper functions carry out the validate and record descriptor updates peformed via update templates. They decode
2641// the templatized data and leverage the non-template UpdateDescriptor helper functions.
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002642bool CoreChecks::ValidateUpdateDescriptorSetsWithTemplateKHR(VkDescriptorSet descriptorSet, const TEMPLATE_STATE *template_state,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05002643 const void *pData) const {
John Zulaufb45fdc32018-10-12 15:14:17 -06002644 // Translate the templated update into a normal update for validation...
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002645 cvdescriptorset::DecodedTemplateUpdate decoded_update(this, descriptorSet, template_state, pData);
2646 return ValidateUpdateDescriptorSets(static_cast<uint32_t>(decoded_update.desc_writes.size()), decoded_update.desc_writes.data(),
2647 0, NULL, "vkUpdateDescriptorSetWithTemplate()");
John Zulaufb45fdc32018-10-12 15:14:17 -06002648}
John Zulaufb845eb22018-10-12 11:41:06 -06002649
John Zulauf4e7bcb52018-11-02 10:46:30 -06002650std::string cvdescriptorset::DescriptorSet::StringifySetAndLayout() const {
2651 std::string out;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002652 auto layout_handle = layout_->GetDescriptorSetLayout();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002653 if (IsPushDescriptor()) {
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002654 std::ostringstream str;
Tony-LunarG1d3ee2d2020-10-27 15:54:52 -06002655 str << "Push Descriptors defined with " << state_data_->report_data->FormatHandle(layout_handle);
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002656 out = str.str();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002657 } else {
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002658 std::ostringstream str;
Tony-LunarG1d3ee2d2020-10-27 15:54:52 -06002659 str << state_data_->report_data->FormatHandle(set_) << " allocated with "
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06002660 << state_data_->report_data->FormatHandle(layout_handle);
2661 out = str.str();
John Zulauf4e7bcb52018-11-02 10:46:30 -06002662 }
2663 return out;
2664};
2665
John Zulauf1d27e0a2018-11-05 10:12:48 -07002666// Loop through the write updates to validate for a push descriptor set, ignoring dstSet
John Zulaufc93c4252019-06-25 09:19:49 -06002667bool CoreChecks::ValidatePushDescriptorsUpdate(const DescriptorSet *push_set, uint32_t write_count,
John Zulaufbd9b3412019-08-22 17:16:11 -06002668 const VkWriteDescriptorSet *p_wds, const char *func_name) const {
John Zulaufd9435c32019-06-05 15:55:36 -06002669 assert(push_set->IsPushDescriptor());
John Zulauf1d27e0a2018-11-05 10:12:48 -07002670 bool skip = false;
2671 for (uint32_t i = 0; i < write_count; i++) {
2672 std::string error_code;
2673 std::string error_str;
John Zulaufc93c4252019-06-25 09:19:49 -06002674 if (!ValidateWriteUpdate(push_set, &p_wds[i], func_name, &error_code, &error_str)) {
sfricke-samsungbda4a852021-03-06 20:58:01 -08002675 skip |= LogError(push_set->GetDescriptorSetLayout(), error_code,
2676 "%s VkWriteDescriptorSet[%u] failed update validation: %s.", func_name, i, error_str.c_str());
John Zulauf1d27e0a2018-11-05 10:12:48 -07002677 }
2678 }
2679 return skip;
2680}
2681
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002682// For the given buffer, verify that its creation parameters are appropriate for the given type
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002683// 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 -06002684bool cvdescriptorset::ValidateBufferUsage(debug_report_data *report_data, BUFFER_STATE const *buffer_node, VkDescriptorType type,
2685 std::string *error_code, std::string *error_msg) {
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002686 // Verify that usage bits set correctly for given type
Tobin Ehlis94bc5d22016-06-02 07:46:52 -06002687 auto usage = buffer_node->createInfo.usage;
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002688 const char *error_usage_bit = nullptr;
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002689 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002690 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2691 if (!(usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002692 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00334";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002693 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT";
2694 }
2695 break;
2696 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2697 if (!(usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002698 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00335";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002699 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT";
2700 }
2701 break;
2702 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2703 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2704 if (!(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002705 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00330";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002706 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT";
2707 }
2708 break;
2709 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2710 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2711 if (!(usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002712 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00331";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002713 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT";
2714 }
2715 break;
2716 default:
2717 break;
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002718 }
Jeff Bolz6d3beaa2019-02-09 21:00:05 -06002719 if (error_usage_bit) {
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002720 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002721 error_str << "Buffer (" << report_data->FormatHandle(buffer_node->buffer) << ") with usage mask " << std::hex
2722 << std::showbase << usage << " being used for a descriptor update of type " << string_VkDescriptorType(type)
2723 << " does not have " << error_usage_bit << " set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002724 *error_msg = error_str.str();
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06002725 return false;
2726 }
2727 return true;
2728}
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002729// For buffer descriptor updates, verify the buffer usage and VkDescriptorBufferInfo struct which includes:
2730// 1. buffer is valid
2731// 2. buffer was created with correct usage flags
2732// 3. offset is less than buffer size
2733// 4. range is either VK_WHOLE_SIZE or falls in (0, (buffer size - offset)]
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002734// 5. range and offset are within the device's limits
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002735// 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 -06002736bool CoreChecks::ValidateBufferUpdate(VkDescriptorBufferInfo const *buffer_info, VkDescriptorType type, const char *func_name,
John Zulaufbd9b3412019-08-22 17:16:11 -06002737 std::string *error_code, std::string *error_msg) const {
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002738 // First make sure that buffer is valid
John Zulaufc93c4252019-06-25 09:19:49 -06002739 auto buffer_node = GetBufferState(buffer_info->buffer);
Tobin Ehlisfa8b6182016-12-22 13:40:45 -07002740 // Any invalid buffer should already be caught by object_tracker
2741 assert(buffer_node);
John Zulaufc93c4252019-06-25 09:19:49 -06002742 if (ValidateMemoryIsBoundToBuffer(buffer_node, func_name, "VUID-VkWriteDescriptorSet-descriptorType-00329")) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002743 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00329";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002744 *error_msg = "No memory bound to buffer.";
Tobin Ehlis81280962016-07-20 14:04:20 -06002745 return false;
Tobin Ehlisfed999f2016-09-21 15:09:45 -06002746 }
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002747 // Verify usage bits
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002748 if (!cvdescriptorset::ValidateBufferUsage(report_data, buffer_node, type, error_code, error_msg)) {
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002749 // error_msg will have been updated by ValidateBufferUsage()
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002750 return false;
2751 }
2752 // offset must be less than buffer size
Jeremy Hayesd1a6a822017-03-09 14:39:45 -07002753 if (buffer_info->offset >= buffer_node->createInfo.size) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002754 *error_code = "VUID-VkDescriptorBufferInfo-offset-00340";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002755 std::stringstream error_str;
Jeremy Hayesd1a6a822017-03-09 14:39:45 -07002756 error_str << "VkDescriptorBufferInfo offset of " << buffer_info->offset << " is greater than or equal to buffer "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002757 << report_data->FormatHandle(buffer_node->buffer) << " size of " << buffer_node->createInfo.size;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002758 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002759 return false;
2760 }
2761 if (buffer_info->range != VK_WHOLE_SIZE) {
2762 // Range must be VK_WHOLE_SIZE or > 0
2763 if (!buffer_info->range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002764 *error_code = "VUID-VkDescriptorBufferInfo-range-00341";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002765 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002766 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer)
2767 << " VkDescriptorBufferInfo range is not VK_WHOLE_SIZE and is zero, which is not allowed.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002768 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002769 return false;
2770 }
2771 // Range must be VK_WHOLE_SIZE or <= (buffer size - offset)
2772 if (buffer_info->range > (buffer_node->createInfo.size - buffer_info->offset)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002773 *error_code = "VUID-VkDescriptorBufferInfo-range-00342";
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002774 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002775 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer) << " VkDescriptorBufferInfo range is "
2776 << buffer_info->range << " which is greater than buffer size (" << buffer_node->createInfo.size
2777 << ") minus requested offset of " << buffer_info->offset;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002778 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002779 return false;
2780 }
2781 }
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002782 // Check buffer update sizes against device limits
John Zulaufc93c4252019-06-25 09:19:49 -06002783 const auto &limits = phys_dev_props.limits;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002784 if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == type || VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) {
John Zulaufd9435c32019-06-05 15:55:36 -06002785 auto max_ub_range = limits.maxUniformBufferRange;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002786 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_ub_range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002787 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00332";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002788 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002789 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer) << " VkDescriptorBufferInfo range is "
2790 << buffer_info->range << " which is greater than this device's maxUniformBufferRange (" << max_ub_range
2791 << ")";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002792 *error_msg = error_str.str();
2793 return false;
Peter Kohaut2794a292018-07-13 11:13:47 +02002794 } else if (buffer_info->range == VK_WHOLE_SIZE && (buffer_node->createInfo.size - buffer_info->offset) > max_ub_range) {
2795 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00332";
2796 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002797 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer)
2798 << " VkDescriptorBufferInfo range is VK_WHOLE_SIZE but effective range "
Peter Kohaut18f413d2018-07-16 13:15:42 +02002799 << "(" << (buffer_node->createInfo.size - buffer_info->offset) << ") is greater than this device's "
Peter Kohaut2794a292018-07-13 11:13:47 +02002800 << "maxUniformBufferRange (" << max_ub_range << ")";
2801 *error_msg = error_str.str();
2802 return false;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002803 }
2804 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type || VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) {
John Zulaufd9435c32019-06-05 15:55:36 -06002805 auto max_sb_range = limits.maxStorageBufferRange;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002806 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_sb_range) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002807 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00333";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002808 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002809 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer) << " VkDescriptorBufferInfo range is "
2810 << buffer_info->range << " which is greater than this device's maxStorageBufferRange (" << max_sb_range
2811 << ")";
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002812 *error_msg = error_str.str();
2813 return false;
Peter Kohaut2794a292018-07-13 11:13:47 +02002814 } else if (buffer_info->range == VK_WHOLE_SIZE && (buffer_node->createInfo.size - buffer_info->offset) > max_sb_range) {
2815 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00333";
2816 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002817 error_str << "For buffer " << report_data->FormatHandle(buffer_node->buffer)
2818 << " VkDescriptorBufferInfo range is VK_WHOLE_SIZE but effective range "
Peter Kohaut18f413d2018-07-16 13:15:42 +02002819 << "(" << (buffer_node->createInfo.size - buffer_info->offset) << ") is greater than this device's "
Peter Kohaut2794a292018-07-13 11:13:47 +02002820 << "maxStorageBufferRange (" << max_sb_range << ")";
2821 *error_msg = error_str.str();
2822 return false;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07002823 }
2824 }
Tobin Ehlis3d38f082016-07-01 17:36:48 -06002825 return true;
2826}
sourav parmarcd5fb182020-07-17 12:58:44 -07002827template <typename T>
2828bool CoreChecks::ValidateAccelerationStructureUpdate(T acc_node, const char *func_name, std::string *error_code,
Jeff Bolz95176d02020-04-01 00:36:16 -05002829 std::string *error_msg) const {
Jeff Bolz95176d02020-04-01 00:36:16 -05002830 // Any invalid acc struct should already be caught by object_tracker
2831 assert(acc_node);
2832 if (ValidateMemoryIsBoundToAccelerationStructure(acc_node, func_name, kVUIDUndefined)) {
2833 *error_code = kVUIDUndefined;
2834 *error_msg = "No memory bound to acceleration structure.";
2835 return false;
2836 }
2837 return true;
2838}
2839
Tobin Ehlis300888c2016-05-18 13:43:26 -06002840// Verify that the contents of the update are ok, but don't perform actual update
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002841bool CoreChecks::VerifyCopyUpdateContents(const VkCopyDescriptorSet *update, const DescriptorSet *src_set,
2842 VkDescriptorType src_type, uint32_t src_index, const DescriptorSet *dst_set,
2843 VkDescriptorType dst_type, uint32_t dst_index, const char *func_name,
2844 std::string *error_code, std::string *error_msg) const {
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06002845 // Note : Repurposing some Write update error codes here as specific details aren't called out for copy updates like they are
2846 // for write updates
John Zulaufc93c4252019-06-25 09:19:49 -06002847 using DescriptorClass = cvdescriptorset::DescriptorClass;
2848 using BufferDescriptor = cvdescriptorset::BufferDescriptor;
2849 using ImageDescriptor = cvdescriptorset::ImageDescriptor;
2850 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
2851 using SamplerDescriptor = cvdescriptorset::SamplerDescriptor;
2852 using TexelDescriptor = cvdescriptorset::TexelDescriptor;
2853
2854 auto device_data = this;
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002855
2856 if (dst_type == VK_DESCRIPTOR_TYPE_SAMPLER) {
2857 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
2858 const auto dst_desc = dst_set->GetDescriptorFromGlobalIndex(dst_index + di);
2859 if (!dst_desc->updated) continue;
2860 if (dst_desc->IsImmutableSampler()) {
2861 *error_code = "VUID-VkCopyDescriptorSet-dstBinding-02753";
2862 std::stringstream error_str;
2863 error_str << "Attempted copy update to an immutable sampler descriptor.";
2864 *error_msg = error_str.str();
2865 return false;
2866 }
2867 }
2868 }
2869
2870 switch (src_set->GetDescriptorFromGlobalIndex(src_index)->descriptor_class) {
John Zulaufc93c4252019-06-25 09:19:49 -06002871 case DescriptorClass::PlainSampler: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002872 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002873 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002874 if (!src_desc->updated) continue;
2875 if (!src_desc->IsImmutableSampler()) {
John Zulaufd9435c32019-06-05 15:55:36 -06002876 auto update_sampler = static_cast<const SamplerDescriptor *>(src_desc)->GetSampler();
John Zulaufc93c4252019-06-25 09:19:49 -06002877 if (!ValidateSampler(update_sampler)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002878 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002879 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002880 error_str << "Attempted copy update to sampler descriptor with invalid sampler: "
2881 << report_data->FormatHandle(update_sampler) << ".";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002882 *error_msg = error_str.str();
2883 return false;
2884 }
2885 } else {
2886 // TODO : Warn here
2887 }
2888 }
2889 break;
2890 }
John Zulaufc93c4252019-06-25 09:19:49 -06002891 case DescriptorClass::ImageSampler: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002892 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002893 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002894 if (!src_desc->updated) continue;
2895 auto img_samp_desc = static_cast<const ImageSamplerDescriptor *>(src_desc);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002896 // First validate sampler
2897 if (!img_samp_desc->IsImmutableSampler()) {
2898 auto update_sampler = img_samp_desc->GetSampler();
John Zulaufc93c4252019-06-25 09:19:49 -06002899 if (!ValidateSampler(update_sampler)) {
Dave Houlton00c154e2018-05-24 13:20:50 -06002900 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002901 std::stringstream error_str;
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06002902 error_str << "Attempted copy update to sampler descriptor with invalid sampler: "
2903 << report_data->FormatHandle(update_sampler) << ".";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002904 *error_msg = error_str.str();
2905 return false;
2906 }
2907 } else {
2908 // TODO : Warn here
2909 }
2910 // Validate image
2911 auto image_view = img_samp_desc->GetImageView();
2912 auto image_layout = img_samp_desc->GetImageLayout();
Jeff Bolz165818a2020-05-08 11:19:03 -05002913 if (image_view) {
2914 if (!ValidateImageUpdate(image_view, image_layout, src_type, func_name, error_code, error_msg)) {
2915 std::stringstream error_str;
2916 error_str << "Attempted copy update to combined image sampler descriptor failed due to: "
2917 << error_msg->c_str();
2918 *error_msg = error_str.str();
2919 return false;
2920 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002921 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002922 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002923 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002924 }
John Zulaufc93c4252019-06-25 09:19:49 -06002925 case DescriptorClass::Image: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002926 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002927 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002928 if (!src_desc->updated) continue;
2929 auto img_desc = static_cast<const ImageDescriptor *>(src_desc);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002930 auto image_view = img_desc->GetImageView();
2931 auto image_layout = img_desc->GetImageLayout();
Jeff Bolz165818a2020-05-08 11:19:03 -05002932 if (image_view) {
2933 if (!ValidateImageUpdate(image_view, image_layout, src_type, func_name, error_code, error_msg)) {
2934 std::stringstream error_str;
2935 error_str << "Attempted copy update to image descriptor failed due to: " << error_msg->c_str();
2936 *error_msg = error_str.str();
2937 return false;
2938 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002939 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002940 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002941 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002942 }
John Zulaufc93c4252019-06-25 09:19:49 -06002943 case DescriptorClass::TexelBuffer: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002944 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002945 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002946 if (!src_desc->updated) continue;
John Zulaufd9435c32019-06-05 15:55:36 -06002947 auto buffer_view = static_cast<const TexelDescriptor *>(src_desc)->GetBufferView();
Jeff Bolz165818a2020-05-08 11:19:03 -05002948 if (buffer_view) {
2949 auto bv_state = device_data->GetBufferViewState(buffer_view);
2950 if (!bv_state) {
2951 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
2952 std::stringstream error_str;
2953 error_str << "Attempted copy update to texel buffer descriptor with invalid buffer view: "
2954 << report_data->FormatHandle(buffer_view);
2955 *error_msg = error_str.str();
2956 return false;
2957 }
2958 auto buffer = bv_state->create_info.buffer;
2959 if (!cvdescriptorset::ValidateBufferUsage(report_data, GetBufferState(buffer), src_type, error_code,
2960 error_msg)) {
2961 std::stringstream error_str;
2962 error_str << "Attempted copy update to texel buffer descriptor failed due to: " << error_msg->c_str();
2963 *error_msg = error_str.str();
2964 return false;
2965 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002966 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06002967 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002968 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002969 }
John Zulaufc93c4252019-06-25 09:19:49 -06002970 case DescriptorClass::GeneralBuffer: {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002971 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07002972 const auto src_desc = src_set->GetDescriptorFromGlobalIndex(src_index + di);
Józef Kucia5297e372017-10-13 22:31:34 +02002973 if (!src_desc->updated) continue;
John Zulaufd9435c32019-06-05 15:55:36 -06002974 auto buffer = static_cast<const BufferDescriptor *>(src_desc)->GetBuffer();
Jeff Bolz165818a2020-05-08 11:19:03 -05002975 if (buffer) {
2976 if (!cvdescriptorset::ValidateBufferUsage(report_data, GetBufferState(buffer), src_type, error_code,
2977 error_msg)) {
2978 std::stringstream error_str;
2979 error_str << "Attempted copy update to buffer descriptor failed due to: " << error_msg->c_str();
2980 *error_msg = error_str.str();
2981 return false;
2982 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002983 }
Tobin Ehliscbcf2342016-05-24 13:07:12 -06002984 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002985 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002986 }
John Zulaufc93c4252019-06-25 09:19:49 -06002987 case DescriptorClass::InlineUniform:
2988 case DescriptorClass::AccelerationStructure:
Ricardo Garcia14f4f762021-04-13 11:36:12 +02002989 case DescriptorClass::Mutable:
Jeff Bolze54ae892018-09-08 12:16:29 -05002990 break;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07002991 default:
2992 assert(0); // We've already verified update type so should never get here
2993 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06002994 }
2995 // All checks passed so update contents are good
2996 return true;
Chris Forbesb4e0bdb2016-05-31 16:34:40 +12002997}
Tobin Ehlisee471462016-05-26 11:21:59 -06002998// Verify that the state at allocate time is correct, but don't actually allocate the sets yet
Mark Lobodzinski3840ca02019-03-08 18:36:11 -07002999bool CoreChecks::ValidateAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *p_alloc_info,
Jeff Bolz46c0ea02019-10-09 13:06:29 -05003000 const cvdescriptorset::AllocateDescriptorSetsData *ds_data) const {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06003001 bool skip = false;
Mark Lobodzinski7804bd42019-03-06 11:28:48 -07003002 auto pool_state = GetDescriptorPoolState(p_alloc_info->descriptorPool);
Tobin Ehlisee471462016-05-26 11:21:59 -06003003
3004 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
Jeff Bolz6ae39612019-10-11 20:57:36 -05003005 auto layout = GetDescriptorSetLayoutShared(p_alloc_info->pSetLayouts[i]);
John Zulauf5562d062018-01-24 11:54:05 -07003006 if (layout) { // nullptr layout indicates no valid layout handle for this device, validated/logged in object_tracker
John Zulauf1d27e0a2018-11-05 10:12:48 -07003007 if (layout->IsPushDescriptor()) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003008 skip |= LogError(p_alloc_info->pSetLayouts[i], "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-00308",
3009 "%s specified at pSetLayouts[%" PRIu32
3010 "] in vkAllocateDescriptorSets() was created with invalid flag %s set.",
3011 report_data->FormatHandle(p_alloc_info->pSetLayouts[i]).c_str(), i,
3012 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR");
John Zulauf5562d062018-01-24 11:54:05 -07003013 }
Mike Schuchardt2df08912020-12-15 16:28:09 -08003014 if (layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT &&
3015 !(pool_state->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT)) {
sfricke-samsungbda4a852021-03-06 20:58:01 -08003016 skip |= LogError(
3017 device, "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-03044",
3018 "vkAllocateDescriptorSets(): Descriptor set layout create flags and pool create flags mismatch for index (%d)",
3019 i);
Jeff Bolzfdf96072018-04-10 14:32:18 -05003020 }
Tobin Ehlisee471462016-05-26 11:21:59 -06003021 }
3022 }
Mark Lobodzinskif45e45f2019-04-19 14:15:39 -06003023 if (!device_extensions.vk_khr_maintenance1) {
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06003024 // Track number of descriptorSets allowable in this pool
3025 if (pool_state->availableSets < p_alloc_info->descriptorSetCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003026 skip |= LogError(pool_state->pool, "VUID-VkDescriptorSetAllocateInfo-descriptorSetCount-00306",
sfricke-samsungbda4a852021-03-06 20:58:01 -08003027 "vkAllocateDescriptorSets(): Unable to allocate %u descriptorSets from %s"
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003028 ". This pool only has %d descriptorSets remaining.",
3029 p_alloc_info->descriptorSetCount, report_data->FormatHandle(pool_state->pool).c_str(),
3030 pool_state->availableSets);
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06003031 }
3032 // Determine whether descriptor counts are satisfiable
Jeff Bolze54ae892018-09-08 12:16:29 -05003033 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 -05003034 auto count_iter = pool_state->availableDescriptorTypeCount.find(it->first);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003035 uint32_t available_count = (count_iter != pool_state->availableDescriptorTypeCount.end()) ? count_iter->second : 0;
Jeff Bolz46c0ea02019-10-09 13:06:29 -05003036
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003037 if (ds_data->required_descriptors_by_type.at(it->first) > available_count) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003038 skip |= LogError(pool_state->pool, "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307",
sfricke-samsungbda4a852021-03-06 20:58:01 -08003039 "vkAllocateDescriptorSets(): Unable to allocate %u descriptors of type %s from %s"
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003040 ". This pool only has %d descriptors of this type remaining.",
3041 ds_data->required_descriptors_by_type.at(it->first),
3042 string_VkDescriptorType(VkDescriptorType(it->first)),
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003043 report_data->FormatHandle(pool_state->pool).c_str(), available_count);
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06003044 }
Tobin Ehlisee471462016-05-26 11:21:59 -06003045 }
3046 }
Tobin Ehlis5d749ea2016-07-18 13:14:01 -06003047
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07003048 const auto *count_allocate_info = LvlFindInChain<VkDescriptorSetVariableDescriptorCountAllocateInfo>(p_alloc_info->pNext);
Jeff Bolzfdf96072018-04-10 14:32:18 -05003049
3050 if (count_allocate_info) {
3051 if (count_allocate_info->descriptorSetCount != 0 &&
3052 count_allocate_info->descriptorSetCount != p_alloc_info->descriptorSetCount) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003053 skip |= LogError(device, "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfo-descriptorSetCount-03045",
sfricke-samsungbda4a852021-03-06 20:58:01 -08003054 "vkAllocateDescriptorSets(): VkDescriptorSetAllocateInfo::descriptorSetCount (%d) != "
Mike Schuchardt2df08912020-12-15 16:28:09 -08003055 "VkDescriptorSetVariableDescriptorCountAllocateInfo::descriptorSetCount (%d)",
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003056 p_alloc_info->descriptorSetCount, count_allocate_info->descriptorSetCount);
Jeff Bolzfdf96072018-04-10 14:32:18 -05003057 }
3058 if (count_allocate_info->descriptorSetCount == p_alloc_info->descriptorSetCount) {
3059 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
Jeff Bolz6ae39612019-10-11 20:57:36 -05003060 auto layout = GetDescriptorSetLayoutShared(p_alloc_info->pSetLayouts[i]);
Jeff Bolzfdf96072018-04-10 14:32:18 -05003061 if (count_allocate_info->pDescriptorCounts[i] > layout->GetDescriptorCountFromBinding(layout->GetMaxBinding())) {
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003062 skip |= LogError(device, "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfo-pSetLayouts-03046",
sfricke-samsungbda4a852021-03-06 20:58:01 -08003063 "vkAllocateDescriptorSets(): pDescriptorCounts[%d] = (%d), binding's descriptorCount = (%d)",
3064 i, count_allocate_info->pDescriptorCounts[i],
Mark Lobodzinskid18de902020-01-15 12:20:37 -07003065 layout->GetDescriptorCountFromBinding(layout->GetMaxBinding()));
Jeff Bolzfdf96072018-04-10 14:32:18 -05003066 }
3067 }
3068 }
3069 }
3070
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06003071 return skip;
Tobin Ehlisee471462016-05-26 11:21:59 -06003072}
John Zulauf48a6a702017-12-22 17:14:54 -07003073
Jeff Bolzdd4cfa12019-08-11 20:57:51 -05003074const BindingReqMap &cvdescriptorset::PrefilterBindRequestMap::FilteredMap(const CMD_BUFFER_STATE &cb_state,
3075 const PIPELINE_STATE &pipeline) {
John Zulauffbf3c202019-07-17 14:57:14 -06003076 if (IsManyDescriptors()) {
Karl Schultz7090a052020-11-10 08:54:21 -07003077 filtered_map_.reset(new BindingReqMap);
John Zulauffbf3c202019-07-17 14:57:14 -06003078 descriptor_set_.FilterBindingReqs(cb_state, pipeline, orig_map_, filtered_map_.get());
3079 return *filtered_map_;
John Zulauf48a6a702017-12-22 17:14:54 -07003080 }
John Zulauffbf3c202019-07-17 14:57:14 -06003081 return orig_map_;
Artem Kharytoniuk2456f992018-01-12 14:17:41 +01003082}
John Zulauf4a015c92019-06-04 09:50:05 -06003083
3084// Starting at offset descriptor of given binding, parse over update_count
3085// descriptor updates and verify that for any binding boundaries that are crossed, the next binding(s) are all consistent
3086// Consistency means that their type, stage flags, and whether or not they use immutable samplers matches
3087// If so, return true. If not, fill in error_msg and return false
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003088bool cvdescriptorset::VerifyUpdateConsistency(debug_report_data *report_data,
3089 DescriptorSetLayout::ConstBindingIterator current_binding, uint32_t offset,
John Zulauf4a015c92019-06-04 09:50:05 -06003090 uint32_t update_count, const char *type, const VkDescriptorSet set,
3091 std::string *error_msg) {
locke-lunarge46b7782019-09-10 01:44:20 -06003092 bool pass = true;
John Zulauf4a015c92019-06-04 09:50:05 -06003093 // Verify consecutive bindings match (if needed)
3094 auto orig_binding = current_binding;
locke-lunarge46b7782019-09-10 01:44:20 -06003095
3096 while (pass && update_count) {
3097 // First, it's legal to offset beyond your own binding so handle that case
3098 if (offset > 0) {
3099 const auto &index_range = current_binding.GetGlobalIndexRange();
3100 // index_range.start + offset is which descriptor is needed to update. If it > index_range.end, it means the descriptor
3101 // isn't in this binding, maybe in next binding.
3102 if ((index_range.start + offset) >= index_range.end) {
3103 // Advance to next binding, decrement offset by binding size
3104 offset -= current_binding.GetDescriptorCount();
3105 ++current_binding;
3106 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
3107 if (!orig_binding.IsConsistent(current_binding)) {
3108 pass = false;
3109 }
3110 continue;
John Zulauf4a015c92019-06-04 09:50:05 -06003111 }
John Zulauf4a015c92019-06-04 09:50:05 -06003112 }
locke-lunarge46b7782019-09-10 01:44:20 -06003113
3114 update_count -= std::min(update_count, current_binding.GetDescriptorCount() - offset);
3115 if (update_count) {
3116 // Starting offset is beyond the current binding. Check consistency, update counters and advance to the next binding,
3117 // looking for the start point. All bindings (even those skipped) must be consistent with the update and with the
3118 // original binding.
3119 offset = 0;
3120 ++current_binding;
3121 // Verify next consecutive binding matches type, stage flags & immutable sampler use and if AtEnd
3122 if (!orig_binding.IsConsistent(current_binding)) {
3123 pass = false;
3124 }
3125 }
John Zulauf4a015c92019-06-04 09:50:05 -06003126 }
locke-lunarge46b7782019-09-10 01:44:20 -06003127
3128 if (!pass) {
3129 std::stringstream error_str;
3130 error_str << "Attempting " << type;
3131 if (current_binding.Layout()->IsPushDescriptor()) {
3132 error_str << " push descriptors";
3133 } else {
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003134 error_str << " descriptor set " << report_data->FormatHandle(set);
locke-lunarge46b7782019-09-10 01:44:20 -06003135 }
3136 error_str << " binding #" << orig_binding.Binding() << " with #" << update_count
3137 << " descriptors being updated but this update oversteps the bounds of this binding and the next binding is "
sfricke-samsung5de34882021-04-15 22:33:23 -07003138 "not consistent with current binding";
3139
3140 // Get what was not consistent in IsConsistent() as a more detailed error message
3141 const auto *binding_ci = orig_binding.GetDescriptorSetLayoutBindingPtr();
3142 const auto *other_binding_ci = current_binding.GetDescriptorSetLayoutBindingPtr();
3143 if (binding_ci == nullptr || other_binding_ci == nullptr) {
3144 error_str << " (No two valid DescriptorSetLayoutBinding to compare)";
3145 } else if (binding_ci->descriptorType != other_binding_ci->descriptorType) {
3146 error_str << " (" << string_VkDescriptorType(binding_ci->descriptorType)
3147 << " != " << string_VkDescriptorType(other_binding_ci->descriptorType) << ")";
3148 } else if (binding_ci->stageFlags != other_binding_ci->stageFlags) {
3149 error_str << " (" << string_VkShaderStageFlags(binding_ci->stageFlags)
3150 << " != " << string_VkShaderStageFlags(other_binding_ci->stageFlags) << ")";
3151 } else if (!hash_util::similar_for_nullity(binding_ci->pImmutableSamplers, other_binding_ci->pImmutableSamplers)) {
3152 error_str << " (pImmutableSamplers don't match)";
3153 } else if (orig_binding.GetDescriptorBindingFlags() != current_binding.GetDescriptorBindingFlags()) {
3154 error_str << " (" << string_VkDescriptorBindingFlags(orig_binding.GetDescriptorBindingFlags())
3155 << " != " << string_VkDescriptorBindingFlags(current_binding.GetDescriptorBindingFlags()) << ")";
3156 }
3157
3158 error_str << " so this update is invalid";
locke-lunarge46b7782019-09-10 01:44:20 -06003159 *error_msg = error_str.str();
3160 }
3161 return pass;
John Zulauf4a015c92019-06-04 09:50:05 -06003162}
John Zulauf4956fff2019-06-04 16:54:38 -06003163
3164// Validate the state for a given write update but don't actually perform the update
3165// 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 -06003166bool CoreChecks::ValidateWriteUpdate(const DescriptorSet *dest_set, const VkWriteDescriptorSet *update, const char *func_name,
John Zulaufbd9b3412019-08-22 17:16:11 -06003167 std::string *error_code, std::string *error_msg) const {
Jeff Bolz6aad1742019-10-16 11:10:09 -05003168 const auto dest_layout = dest_set->GetLayout().get();
John Zulauf4956fff2019-06-04 16:54:38 -06003169
3170 // Verify dst layout still valid
Jeff Bolz6ae39612019-10-11 20:57:36 -05003171 if (dest_layout->destroyed) {
John Zulauf4956fff2019-06-04 16:54:38 -06003172 *error_code = "VUID-VkWriteDescriptorSet-dstSet-00320";
Mark Lobodzinski23e395e2020-04-09 10:17:31 -06003173 std::ostringstream str;
3174 str << "Cannot call " << func_name << " to perform write update on " << dest_set->StringifySetAndLayout()
3175 << " which has been destroyed";
3176 *error_msg = str.str();
John Zulauf4956fff2019-06-04 16:54:38 -06003177 return false;
3178 }
3179 // Verify dst binding exists
3180 if (!dest_layout->HasBinding(update->dstBinding)) {
3181 *error_code = "VUID-VkWriteDescriptorSet-dstBinding-00315";
3182 std::stringstream error_str;
3183 error_str << dest_set->StringifySetAndLayout() << " does not have binding " << update->dstBinding;
3184 *error_msg = error_str.str();
3185 return false;
3186 }
3187
Jeff Bolz6aad1742019-10-16 11:10:09 -05003188 DescriptorSetLayout::ConstBindingIterator dest(dest_layout, update->dstBinding);
John Zulauf4956fff2019-06-04 16:54:38 -06003189 // Make sure binding isn't empty
3190 if (0 == dest.GetDescriptorCount()) {
3191 *error_code = "VUID-VkWriteDescriptorSet-dstBinding-00316";
3192 std::stringstream error_str;
3193 error_str << dest_set->StringifySetAndLayout() << " cannot updated binding " << update->dstBinding
3194 << " that has 0 descriptors";
3195 *error_msg = error_str.str();
3196 return false;
3197 }
3198
3199 // Verify idle ds
Mike Schuchardt2df08912020-12-15 16:28:09 -08003200 if (dest_set->in_use.load() && !(dest.GetDescriptorBindingFlags() & (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT |
3201 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT))) {
John Zulauf4956fff2019-06-04 16:54:38 -06003202 // TODO : Re-using Free Idle error code, need write update idle error code
3203 *error_code = "VUID-vkFreeDescriptorSets-pDescriptorSets-00309";
3204 std::stringstream error_str;
3205 error_str << "Cannot call " << func_name << " to perform write update on " << dest_set->StringifySetAndLayout()
3206 << " that is in use by a command buffer";
3207 *error_msg = error_str.str();
3208 return false;
3209 }
3210 // We know that binding is valid, verify update and do update on each descriptor
3211 auto start_idx = dest.GetGlobalIndexRange().start + update->dstArrayElement;
3212 auto type = dest.GetType();
Tony-LunarGf563b362021-03-18 16:13:18 -06003213 if ((type != VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) && (type != update->descriptorType)) {
John Zulauf4956fff2019-06-04 16:54:38 -06003214 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00319";
3215 std::stringstream error_str;
3216 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3217 << " with type " << string_VkDescriptorType(type) << " but update type is "
3218 << string_VkDescriptorType(update->descriptorType);
3219 *error_msg = error_str.str();
3220 return false;
3221 }
John Zulauf4956fff2019-06-04 16:54:38 -06003222 if (type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
3223 if ((update->dstArrayElement % 4) != 0) {
3224 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02219";
3225 std::stringstream error_str;
3226 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3227 << " with "
3228 << "dstArrayElement " << update->dstArrayElement << " not a multiple of 4";
3229 *error_msg = error_str.str();
3230 return false;
3231 }
3232 if ((update->descriptorCount % 4) != 0) {
3233 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02220";
3234 std::stringstream error_str;
3235 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3236 << " with "
3237 << "descriptorCount " << update->descriptorCount << " not a multiple of 4";
3238 *error_msg = error_str.str();
3239 return false;
3240 }
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07003241 const auto *write_inline_info = LvlFindInChain<VkWriteDescriptorSetInlineUniformBlockEXT>(update->pNext);
John Zulauf4956fff2019-06-04 16:54:38 -06003242 if (!write_inline_info || write_inline_info->dataSize != update->descriptorCount) {
3243 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02221";
3244 std::stringstream error_str;
3245 if (!write_inline_info) {
3246 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #"
3247 << update->dstBinding << " with "
3248 << "VkWriteDescriptorSetInlineUniformBlockEXT missing";
3249 } else {
3250 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #"
3251 << update->dstBinding << " with "
3252 << "VkWriteDescriptorSetInlineUniformBlockEXT dataSize " << write_inline_info->dataSize
3253 << " not equal to "
3254 << "VkWriteDescriptorSet descriptorCount " << update->descriptorCount;
3255 }
3256 *error_msg = error_str.str();
3257 return false;
3258 }
3259 // This error is probably unreachable due to the previous two errors
3260 if (write_inline_info && (write_inline_info->dataSize % 4) != 0) {
3261 *error_code = "VUID-VkWriteDescriptorSetInlineUniformBlockEXT-dataSize-02222";
3262 std::stringstream error_str;
3263 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3264 << " with "
3265 << "VkWriteDescriptorSetInlineUniformBlockEXT dataSize " << write_inline_info->dataSize
3266 << " not a multiple of 4";
3267 *error_msg = error_str.str();
3268 return false;
3269 }
3270 }
sfricke-samsung941d48b2020-02-10 00:20:01 -08003271 // Verify all bindings update share identical properties across all items
3272 if (update->descriptorCount > 0) {
3273 // Save first binding information and error if something different is found
3274 DescriptorSetLayout::ConstBindingIterator current_binding(dest_layout, update->dstBinding);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003275 VkShaderStageFlags stage_flags = current_binding.GetStageFlags();
3276 VkDescriptorType descriptor_type = current_binding.GetType();
3277 bool immutable_samplers = (current_binding.GetImmutableSamplerPtr() == nullptr);
3278 uint32_t dst_array_element = update->dstArrayElement;
sfricke-samsung941d48b2020-02-10 00:20:01 -08003279
Jeff Bolz9198e882020-03-18 13:03:30 -05003280 for (uint32_t i = 0; i < update->descriptorCount;) {
sfricke-samsung941d48b2020-02-10 00:20:01 -08003281 if (current_binding.AtEnd() == true) {
3282 break; // prevents setting error here if bindings don't exist
3283 }
3284
3285 // Check for consistent stageFlags and descriptorType
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003286 if ((current_binding.GetStageFlags() != stage_flags) || (current_binding.GetType() != descriptor_type)) {
sfricke-samsung941d48b2020-02-10 00:20:01 -08003287 *error_code = "VUID-VkWriteDescriptorSet-descriptorCount-00317";
3288 std::stringstream error_str;
3289 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3290 << current_binding.GetIndex() << " (" << i << " from dstBinding offset)"
3291 << " with a different stageFlag and/or descriptorType from previous bindings."
3292 << " All bindings must have consecutive stageFlag and/or descriptorType across a VkWriteDescriptorSet";
3293 *error_msg = error_str.str();
3294 return false;
3295 }
3296 // Check if all immutableSamplers or not
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003297 if ((current_binding.GetImmutableSamplerPtr() == nullptr) != immutable_samplers) {
sfricke-samsung941d48b2020-02-10 00:20:01 -08003298 *error_code = "VUID-VkWriteDescriptorSet-descriptorCount-00318";
3299 std::stringstream error_str;
3300 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3301 << current_binding.GetIndex() << " (" << i << " from dstBinding offset)"
3302 << " with a different usage of immutable samplers from previous bindings."
3303 << " All bindings must have all or none usage of immutable samplers across a VkWriteDescriptorSet";
3304 *error_msg = error_str.str();
3305 return false;
3306 }
Jeff Bolz9198e882020-03-18 13:03:30 -05003307
3308 // Skip the remaining descriptors for this binding, and move to the next binding
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003309 i += (current_binding.GetDescriptorCount() - dst_array_element);
3310 dst_array_element = 0;
sfricke-samsung941d48b2020-02-10 00:20:01 -08003311 ++current_binding;
3312 }
3313 }
3314
John Zulauf4956fff2019-06-04 16:54:38 -06003315 // Verify consecutive bindings match (if needed)
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003316 if (!VerifyUpdateConsistency(report_data, DescriptorSetLayout::ConstBindingIterator(dest_layout, update->dstBinding),
John Zulauf4956fff2019-06-04 16:54:38 -06003317 update->dstArrayElement, update->descriptorCount, "write update to", dest_set->GetSet(),
3318 error_msg)) {
John Zulauf4956fff2019-06-04 16:54:38 -06003319 *error_code = "VUID-VkWriteDescriptorSet-dstArrayElement-00321";
3320 return false;
3321 }
Tony-LunarG1f79c952020-10-27 15:55:51 -06003322 // Verify write to variable descriptor
3323 if (dest_set->IsVariableDescriptorCount(update->dstBinding)) {
3324 if ((update->dstArrayElement + update->descriptorCount) > dest_set->GetVariableDescriptorCount()) {
3325 std::stringstream error_str;
3326 *error_code = "VUID-VkWriteDescriptorSet-dstArrayElement-00321";
3327 error_str << "Attempting write update to " << dest_set->StringifySetAndLayout() << " binding index #"
3328 << update->dstBinding << " array element " << update->dstArrayElement << " with " << update->descriptorCount
3329 << " writes but variable descriptor size is " << dest_set->GetVariableDescriptorCount();
3330 *error_msg = error_str.str();
3331 return false;
3332 }
3333 }
John Zulauf4956fff2019-06-04 16:54:38 -06003334 // Update is within bounds and consistent so last step is to validate update contents
John Zulauf459939f2019-06-04 16:49:35 -06003335 if (!VerifyWriteUpdateContents(dest_set, update, start_idx, func_name, error_code, error_msg)) {
John Zulauf4956fff2019-06-04 16:54:38 -06003336 std::stringstream error_str;
3337 error_str << "Write update to " << dest_set->StringifySetAndLayout() << " binding #" << update->dstBinding
3338 << " failed with error message: " << error_msg->c_str();
3339 *error_msg = error_str.str();
3340 return false;
3341 }
3342 // All checks passed, update is clean
3343 return true;
3344}
John Zulaufadb3f542019-06-04 17:01:00 -06003345
3346// Verify that the contents of the update are ok, but don't perform actual update
John Zulaufc93c4252019-06-25 09:19:49 -06003347bool CoreChecks::VerifyWriteUpdateContents(const DescriptorSet *dest_set, const VkWriteDescriptorSet *update, const uint32_t index,
John Zulaufbd9b3412019-08-22 17:16:11 -06003348 const char *func_name, std::string *error_code, std::string *error_msg) const {
John Zulaufc93c4252019-06-25 09:19:49 -06003349 using ImageSamplerDescriptor = cvdescriptorset::ImageSamplerDescriptor;
Nathaniel Cesarioff521512020-12-11 16:00:26 -07003350 using Descriptor = cvdescriptorset::Descriptor;
John Zulaufc93c4252019-06-25 09:19:49 -06003351
John Zulaufadb3f542019-06-04 17:01:00 -06003352 switch (update->descriptorType) {
3353 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
3354 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3355 // Validate image
3356 auto image_view = update->pImageInfo[di].imageView;
3357 auto image_layout = update->pImageInfo[di].imageLayout;
Mark Lobodzinski3ca937b2020-02-14 14:56:06 -07003358 auto sampler = update->pImageInfo[di].sampler;
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003359 auto iv_state = GetImageViewState(image_view);
Nathaniel Cesarioff521512020-12-11 16:00:26 -07003360 const ImageSamplerDescriptor *desc =
3361 (const ImageSamplerDescriptor *)dest_set->GetDescriptorFromGlobalIndex(index + di);
Jeff Bolz165818a2020-05-08 11:19:03 -05003362 if (image_view) {
3363 auto image_state = iv_state->image_state.get();
3364 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, func_name, error_code, error_msg)) {
3365 std::stringstream error_str;
3366 error_str << "Attempted write update to combined image sampler descriptor failed due to: "
3367 << error_msg->c_str();
3368 *error_msg = error_str.str();
3369 return false;
3370 }
3371 if (device_extensions.vk_khr_sampler_ycbcr_conversion) {
3372 if (desc->IsImmutableSampler()) {
3373 auto sampler_state = GetSamplerState(desc->GetSampler());
3374 if (iv_state && sampler_state) {
3375 if (iv_state->samplerConversion != sampler_state->samplerConversion) {
3376 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-01948";
3377 std::stringstream error_str;
3378 error_str
3379 << "Attempted write update to combined image sampler and image view and sampler ycbcr "
3380 "conversions are not identical, sampler: "
3381 << report_data->FormatHandle(desc->GetSampler())
3382 << " image view: " << report_data->FormatHandle(iv_state->image_view) << ".";
3383 *error_msg = error_str.str();
3384 return false;
3385 }
3386 }
3387 } else {
3388 if (iv_state && (iv_state->samplerConversion != VK_NULL_HANDLE)) {
3389 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02738";
John Zulaufadb3f542019-06-04 17:01:00 -06003390 std::stringstream error_str;
Jeff Bolz165818a2020-05-08 11:19:03 -05003391 error_str << "Because dstSet (" << report_data->FormatHandle(update->dstSet)
3392 << ") is bound to image view (" << report_data->FormatHandle(iv_state->image_view)
3393 << ") that includes a YCBCR conversion, it must have been allocated with a layout that "
3394 "includes an immutable sampler.";
John Zulaufadb3f542019-06-04 17:01:00 -06003395 *error_msg = error_str.str();
3396 return false;
3397 }
3398 }
Jeff Bolz165818a2020-05-08 11:19:03 -05003399 }
John Baumanda8abff2020-10-19 21:25:21 +00003400 // If there is an immutable sampler then |sampler| isn't used, so the following VU does not apply.
3401 if (sampler && !desc->IsImmutableSampler() && FormatIsMultiplane(image_state->createInfo.format)) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003402 // multiplane formats must be created with mutable format bit
3403 if (0 == (image_state->createInfo.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) {
3404 *error_code = "VUID-VkDescriptorImageInfo-sampler-01564";
John Zulaufadb3f542019-06-04 17:01:00 -06003405 std::stringstream error_str;
Jeff Bolz165818a2020-05-08 11:19:03 -05003406 error_str << "image " << report_data->FormatHandle(image_state->image)
3407 << " combined image sampler is a multi-planar "
3408 << "format and was not was not created with the VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT";
John Zulaufadb3f542019-06-04 17:01:00 -06003409 *error_msg = error_str.str();
3410 return false;
3411 }
Jeff Bolz165818a2020-05-08 11:19:03 -05003412 // image view need aspect mask for only the planes supported of format
3413 VkImageAspectFlags legal_aspect_flags = (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT);
3414 legal_aspect_flags |=
3415 (FormatPlaneCount(image_state->createInfo.format) == 3) ? VK_IMAGE_ASPECT_PLANE_2_BIT : 0;
3416 if (0 != (iv_state->create_info.subresourceRange.aspectMask & (~legal_aspect_flags))) {
3417 *error_code = "VUID-VkDescriptorImageInfo-sampler-01564";
3418 std::stringstream error_str;
3419 error_str << "image " << report_data->FormatHandle(image_state->image)
3420 << " combined image sampler is a multi-planar "
3421 << "format and " << report_data->FormatHandle(iv_state->image_view)
3422 << " aspectMask must only include " << string_VkImageAspectFlags(legal_aspect_flags);
3423 *error_msg = error_str.str();
3424 return false;
3425 }
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003426 }
Nathaniel Cesario23afadd2020-11-17 12:51:45 -07003427
3428 // Verify portability
3429 auto sampler_state = GetSamplerState(sampler);
3430 if (sampler_state) {
3431 if (ExtEnabled::kNotEnabled != device_extensions.vk_khr_portability_subset) {
3432 if ((VK_FALSE == enabled_features.portability_subset_features.mutableComparisonSamplers) &&
3433 (VK_FALSE != sampler_state->createInfo.compareEnable)) {
3434 LogError(device, "VUID-VkDescriptorImageInfo-mutableComparisonSamplers-04450",
3435 "%s (portability error): sampler comparison not available.", func_name);
3436 }
3437 }
3438 }
sfricke-samsung27e5d5a2020-01-07 21:07:08 -08003439 }
John Zulaufadb3f542019-06-04 17:01:00 -06003440 }
3441 }
Mark Lobodzinskiac727772020-01-08 10:47:30 -07003442 // Fall through
John Zulaufadb3f542019-06-04 17:01:00 -06003443 case VK_DESCRIPTOR_TYPE_SAMPLER: {
3444 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003445 const auto *desc = static_cast<const Descriptor *>(dest_set->GetDescriptorFromGlobalIndex(index + di));
John Zulaufadb3f542019-06-04 17:01:00 -06003446 if (!desc->IsImmutableSampler()) {
John Zulaufc93c4252019-06-25 09:19:49 -06003447 if (!ValidateSampler(update->pImageInfo[di].sampler)) {
John Zulaufadb3f542019-06-04 17:01:00 -06003448 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-00325";
3449 std::stringstream error_str;
3450 error_str << "Attempted write update to sampler descriptor with invalid sampler: "
Mark Lobodzinskidb35b8b2020-04-09 08:46:59 -06003451 << report_data->FormatHandle(update->pImageInfo[di].sampler) << ".";
John Zulaufadb3f542019-06-04 17:01:00 -06003452 *error_msg = error_str.str();
3453 return false;
3454 }
Mark Lobodzinskiac727772020-01-08 10:47:30 -07003455 } else if (update->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) {
Mark Lobodzinskif4ed6c12020-01-03 11:21:58 -07003456 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02752";
3457 std::stringstream error_str;
3458 error_str << "Attempted write update to an immutable sampler descriptor.";
3459 *error_msg = error_str.str();
3460 return false;
John Zulaufadb3f542019-06-04 17:01:00 -06003461 }
3462 }
3463 break;
3464 }
3465 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
3466 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
3467 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
3468 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3469 auto image_view = update->pImageInfo[di].imageView;
3470 auto image_layout = update->pImageInfo[di].imageLayout;
Jeff Bolz165818a2020-05-08 11:19:03 -05003471 if (image_view) {
3472 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, func_name, error_code, error_msg)) {
3473 std::stringstream error_str;
3474 error_str << "Attempted write update to image descriptor failed due to: " << error_msg->c_str();
3475 *error_msg = error_str.str();
3476 return false;
3477 }
John Zulaufadb3f542019-06-04 17:01:00 -06003478 }
3479 }
3480 break;
3481 }
3482 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
3483 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
3484 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
3485 auto buffer_view = update->pTexelBufferView[di];
Jeff Bolz165818a2020-05-08 11:19:03 -05003486 if (buffer_view) {
3487 auto bv_state = GetBufferViewState(buffer_view);
3488 if (!bv_state) {
3489 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
3490 std::stringstream error_str;
3491 error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: "
3492 << report_data->FormatHandle(buffer_view);
3493 *error_msg = error_str.str();
3494 return false;
3495 }
3496 auto buffer = bv_state->create_info.buffer;
3497 auto buffer_state = GetBufferState(buffer);
3498 // Verify that buffer underlying the view hasn't been destroyed prematurely
3499 if (!buffer_state) {
3500 *error_code = "VUID-VkWriteDescriptorSet-descriptorType-02994";
3501 std::stringstream error_str;
3502 error_str << "Attempted write update to texel buffer descriptor failed because underlying buffer ("
3503 << report_data->FormatHandle(buffer) << ") has been destroyed: " << error_msg->c_str();
3504 *error_msg = error_str.str();
3505 return false;
3506 } else if (!cvdescriptorset::ValidateBufferUsage(report_data, buffer_state, update->descriptorType, error_code,
3507 error_msg)) {
3508 std::stringstream error_str;
3509 error_str << "Attempted write update to texel buffer descriptor failed due to: " << error_msg->c_str();
3510 *error_msg = error_str.str();
3511 return false;
3512 }
John Zulaufadb3f542019-06-04 17:01:00 -06003513 }
3514 }
3515 break;
3516 }
3517 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
3518 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
3519 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
3520 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
3521 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Jeff Bolz165818a2020-05-08 11:19:03 -05003522 if (update->pBufferInfo[di].buffer) {
3523 if (!ValidateBufferUpdate(update->pBufferInfo + di, update->descriptorType, func_name, error_code, error_msg)) {
3524 std::stringstream error_str;
3525 error_str << "Attempted write update to buffer descriptor failed due to: " << error_msg->c_str();
3526 *error_msg = error_str.str();
3527 return false;
3528 }
John Zulaufadb3f542019-06-04 17:01:00 -06003529 }
3530 }
3531 break;
3532 }
3533 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
3534 break;
Jeff Bolz95176d02020-04-01 00:36:16 -05003535 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -07003536 const auto *acc_info = LvlFindInChain<VkWriteDescriptorSetAccelerationStructureNV>(update->pNext);
Jeff Bolz95176d02020-04-01 00:36:16 -05003537 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07003538 if (!ValidateAccelerationStructureUpdate(GetAccelerationStructureStateNV(acc_info->pAccelerationStructures[di]),
Mark Lobodzinski85ebd402020-12-03 12:56:07 -07003539 func_name, error_code, error_msg)) {
Jeff Bolz95176d02020-04-01 00:36:16 -05003540 std::stringstream error_str;
3541 error_str << "Attempted write update to acceleration structure descriptor failed due to: "
3542 << error_msg->c_str();
3543 *error_msg = error_str.str();
3544 return false;
3545 }
3546 }
3547
3548 } break;
sourav parmarcd5fb182020-07-17 12:58:44 -07003549 // KHR acceleration structures don't require memory to be bound manually to them.
3550 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
3551 break;
John Zulaufadb3f542019-06-04 17:01:00 -06003552 default:
3553 assert(0); // We've already verified update type so should never get here
3554 break;
3555 }
3556 // All checks passed so update contents are good
3557 return true;
3558}