blob: b217d913a1743f584e930130d6bd1aabac2da2b2 [file] [log] [blame]
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001/* Copyright (c) 2015-2016 The Khronos Group Inc.
2 * Copyright (c) 2015-2016 Valve Corporation
3 * Copyright (c) 2015-2016 LunarG, Inc.
4 * Copyright (C) 2015-2016 Google Inc.
5 *
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>
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060020 */
21
Tobin Ehlisf922ef82016-11-30 10:19:14 -070022// Allow use of STL min and max functions in Windows
23#define NOMINMAX
24
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060025#include "descriptor_sets.h"
26#include "vk_enum_string_helper.h"
27#include "vk_safe_struct.h"
Tobin Ehlisc8266452017-04-07 12:20:30 -060028#include "buffer_validation.h"
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060029#include <sstream>
Mark Lobodzinski2eee5d82016-12-02 15:33:18 -070030#include <algorithm>
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060031
32// Construct DescriptorSetLayout instance from given create info
John Zulauf48a6a702017-12-22 17:14:54 -070033// Proactively reserve and resize as possible, as the reallocation was visible in profiling
Tobin Ehlis154c2692016-10-25 09:36:53 -060034cvdescriptorset::DescriptorSetLayout::DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info,
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060035 const VkDescriptorSetLayout layout)
Józef Kucia1bb00972017-09-10 11:24:08 +020036 : layout_(layout),
37 flags_(p_create_info->flags),
38 binding_count_(p_create_info->bindingCount),
39 descriptor_count_(0),
40 dynamic_descriptor_count_(0) {
John Zulauf48a6a702017-12-22 17:14:54 -070041 binding_type_stats_ = {0, 0, 0};
John Zulaufb6d71202017-12-22 16:47:09 -070042 std::set<uint32_t> sorted_bindings;
43 // Create the sorted set and unsorted map of bindings and indices
44 for (uint32_t i = 0; i < binding_count_; i++) {
45 sorted_bindings.insert(p_create_info->pBindings[i].binding);
46 }
47 uint32_t index = 0;
48 binding_to_index_map_.reserve(binding_count_);
49 for (const uint32_t binding_num : sorted_bindings) {
50 binding_to_index_map_[binding_num] = index++;
51 }
52
53 // Store the create info in the sorted order from above
Tobin Ehlisa3525e02016-11-17 10:50:52 -070054 std::map<uint32_t, uint32_t> binding_to_dyn_count;
John Zulaufb6d71202017-12-22 16:47:09 -070055 bindings_.resize(binding_count_);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060056 for (uint32_t i = 0; i < binding_count_; ++i) {
John Zulaufb6d71202017-12-22 16:47:09 -070057 const auto binding_num = p_create_info->pBindings[i].binding;
58 auto &binding_info = bindings_[binding_to_index_map_[binding_num]];
59 binding_info = std::move(safe_VkDescriptorSetLayoutBinding(&p_create_info->pBindings[i]));
60 descriptor_count_ += binding_info.descriptorCount;
61 if (binding_info.descriptorCount > 0) {
62 non_empty_bindings_.insert(binding_num);
Tobin Ehlis9637fb22016-12-12 15:59:34 -070063 }
John Zulaufb6d71202017-12-22 16:47:09 -070064
65 if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
66 binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
67 binding_to_dyn_count[binding_num] = binding_info.descriptorCount;
68 dynamic_descriptor_count_ += binding_info.descriptorCount;
John Zulauf48a6a702017-12-22 17:14:54 -070069 binding_type_stats_.dynamic_buffer_count++;
70 } else if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
71 (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)) {
72 binding_type_stats_.non_dynamic_buffer_count++;
73 } else {
74 binding_type_stats_.image_sampler_count++;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060075 }
76 }
Tobin Ehlis9637fb22016-12-12 15:59:34 -070077 assert(bindings_.size() == binding_count_);
78 uint32_t global_index = 0;
John Zulaufb6d71202017-12-22 16:47:09 -070079 binding_to_global_index_range_map_.reserve(binding_count_);
80 // Vector order is finalized so create maps of bindings to descriptors and descriptors to indices
Tobin Ehlis9637fb22016-12-12 15:59:34 -070081 for (uint32_t i = 0; i < binding_count_; ++i) {
82 auto binding_num = bindings_[i].binding;
John Zulaufc483f442017-12-15 14:02:06 -070083 auto final_index = global_index + bindings_[i].descriptorCount;
84 binding_to_global_index_range_map_[binding_num] = IndexRange(global_index, final_index);
John Zulaufb6d71202017-12-22 16:47:09 -070085 if (final_index != global_index) {
86 global_start_to_index_map_[global_index] = i;
87 }
John Zulaufc483f442017-12-15 14:02:06 -070088 global_index = final_index;
Tobin Ehlis9637fb22016-12-12 15:59:34 -070089 }
John Zulaufb6d71202017-12-22 16:47:09 -070090
Tobin Ehlisa3525e02016-11-17 10:50:52 -070091 // Now create dyn offset array mapping for any dynamic descriptors
92 uint32_t dyn_array_idx = 0;
John Zulaufb6d71202017-12-22 16:47:09 -070093 binding_to_dynamic_array_idx_map_.reserve(binding_to_dyn_count.size());
Tobin Ehlisa3525e02016-11-17 10:50:52 -070094 for (const auto &bc_pair : binding_to_dyn_count) {
95 binding_to_dynamic_array_idx_map_[bc_pair.first] = dyn_array_idx;
96 dyn_array_idx += bc_pair.second;
97 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060098}
Tobin Ehlis154c2692016-10-25 09:36:53 -060099
100// Validate descriptor set layout create info
101bool cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(debug_report_data *report_data,
102 const VkDescriptorSetLayoutCreateInfo *create_info) {
103 bool skip = false;
104 std::unordered_set<uint32_t> bindings;
105 for (uint32_t i = 0; i < create_info->bindingCount; ++i) {
Tobin Ehlisfdcb63f2016-10-25 20:56:47 -0600106 if (!bindings.insert(create_info->pBindings[i].binding).second) {
Tobin Ehlis154c2692016-10-25 09:36:53 -0600107 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600108 VALIDATION_ERROR_0500022e, "DS", "duplicated binding number in VkDescriptorSetLayoutBinding. %s",
109 validation_error_map[VALIDATION_ERROR_0500022e]);
Tobin Ehlis154c2692016-10-25 09:36:53 -0600110 }
Tobin Ehlis154c2692016-10-25 09:36:53 -0600111 }
112 return skip;
113}
114
John Zulaufb6d71202017-12-22 16:47:09 -0700115// Return valid index or "end" i.e. binding_count_;
116// The asserts in "Get" are reduced to the set where no valid answer(like null or 0) could be given
117// Common code for all binding lookups.
118uint32_t cvdescriptorset::DescriptorSetLayout::GetIndexFromBinding(uint32_t binding) const {
Tobin Ehlis0bc30632016-05-05 10:16:02 -0600119 const auto &bi_itr = binding_to_index_map_.find(binding);
John Zulaufb6d71202017-12-22 16:47:09 -0700120 if (bi_itr != binding_to_index_map_.cend()) return bi_itr->second;
121 return GetBindingCount();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600122}
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700123VkDescriptorSetLayoutBinding const *cvdescriptorset::DescriptorSetLayout::GetDescriptorSetLayoutBindingPtrFromIndex(
124 const uint32_t index) const {
125 if (index >= bindings_.size()) return nullptr;
Tobin Ehlis664e6012016-05-05 11:04:44 -0600126 return bindings_[index].ptr();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600127}
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600128// Return descriptorCount for given index, 0 if index is unavailable
129uint32_t cvdescriptorset::DescriptorSetLayout::GetDescriptorCountFromIndex(const uint32_t index) const {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700130 if (index >= bindings_.size()) return 0;
Tobin Ehlis664e6012016-05-05 11:04:44 -0600131 return bindings_[index].descriptorCount;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600132}
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600133// For the given index, return descriptorType
134VkDescriptorType cvdescriptorset::DescriptorSetLayout::GetTypeFromIndex(const uint32_t index) const {
135 assert(index < bindings_.size());
John Zulaufb6d71202017-12-22 16:47:09 -0700136 if (index < bindings_.size()) return bindings_[index].descriptorType;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600137 return VK_DESCRIPTOR_TYPE_MAX_ENUM;
138}
John Zulaufb6d71202017-12-22 16:47:09 -0700139// For the given index, return stageFlags
140VkShaderStageFlags cvdescriptorset::DescriptorSetLayout::GetStageFlagsFromIndex(const uint32_t index) const {
141 assert(index < bindings_.size());
142 if (index < bindings_.size()) return bindings_[index].stageFlags;
Tobin Ehlis0bc30632016-05-05 10:16:02 -0600143 return VkShaderStageFlags(0);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600144}
John Zulaufc483f442017-12-15 14:02:06 -0700145
John Zulaufb6d71202017-12-22 16:47:09 -0700146// For the given global index, return index
147uint32_t cvdescriptorset::DescriptorSetLayout::GetIndexFromGlobalIndex(const uint32_t global_index) const {
148 auto start_it = global_start_to_index_map_.upper_bound(global_index);
149 uint32_t index = binding_count_;
150 assert(start_it != global_start_to_index_map_.cbegin());
151 if (start_it != global_start_to_index_map_.cbegin()) {
152 --start_it;
153 index = start_it->second;
154#ifndef NDEBUG
155 const auto &range = GetGlobalIndexRangeFromBinding(bindings_[index].binding);
156 assert(range.start <= global_index && global_index < range.end);
157#endif
158 }
159 return index;
160}
161
162// For the given binding, return the global index range
John Zulaufc483f442017-12-15 14:02:06 -0700163// As start and end are often needed in pairs, get both with a single hash lookup.
164const cvdescriptorset::IndexRange &cvdescriptorset::DescriptorSetLayout::GetGlobalIndexRangeFromBinding(
165 const uint32_t binding) const {
166 assert(binding_to_global_index_range_map_.count(binding));
Tobin Ehlis0bc30632016-05-05 10:16:02 -0600167 // In error case max uint32_t so index is out of bounds to break ASAP
John Zulaufc483f442017-12-15 14:02:06 -0700168 const static IndexRange kInvalidRange = {0xFFFFFFFF, 0xFFFFFFFF};
169 const auto &range_it = binding_to_global_index_range_map_.find(binding);
170 if (range_it != binding_to_global_index_range_map_.end()) {
171 return range_it->second;
Tobin Ehlis0bc30632016-05-05 10:16:02 -0600172 }
John Zulaufc483f442017-12-15 14:02:06 -0700173 return kInvalidRange;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600174}
John Zulaufc483f442017-12-15 14:02:06 -0700175
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600176// For given binding, return ptr to ImmutableSampler array
177VkSampler const *cvdescriptorset::DescriptorSetLayout::GetImmutableSamplerPtrFromBinding(const uint32_t binding) const {
Tobin Ehlis0bc30632016-05-05 10:16:02 -0600178 const auto &bi_itr = binding_to_index_map_.find(binding);
179 if (bi_itr != binding_to_index_map_.end()) {
Tobin Ehlis664e6012016-05-05 11:04:44 -0600180 return bindings_[bi_itr->second].pImmutableSamplers;
Tobin Ehlis0bc30632016-05-05 10:16:02 -0600181 }
182 return nullptr;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600183}
Mark Lobodzinski4aa479d2017-03-10 09:14:00 -0700184// Move to next valid binding having a non-zero binding count
185uint32_t cvdescriptorset::DescriptorSetLayout::GetNextValidBinding(const uint32_t binding) const {
John Zulaufb6d71202017-12-22 16:47:09 -0700186 auto it = non_empty_bindings_.upper_bound(binding);
187 assert(it != non_empty_bindings_.cend());
188 if (it != non_empty_bindings_.cend()) return *it;
189 return GetMaxBinding() + 1;
Mark Lobodzinski4aa479d2017-03-10 09:14:00 -0700190}
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600191// For given index, return ptr to ImmutableSampler array
192VkSampler const *cvdescriptorset::DescriptorSetLayout::GetImmutableSamplerPtrFromIndex(const uint32_t index) const {
John Zulaufb6d71202017-12-22 16:47:09 -0700193 if (index < bindings_.size()) {
194 return bindings_[index].pImmutableSamplers;
195 }
196 return nullptr;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600197}
198// If our layout is compatible with rh_ds_layout, return true,
199// else return false and fill in error_msg will description of what causes incompatibility
Tobin Ehlis6dc57dd2017-06-21 10:08:52 -0600200bool cvdescriptorset::DescriptorSetLayout::IsCompatible(DescriptorSetLayout const *const rh_ds_layout,
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600201 std::string *error_msg) const {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600202 // Trivial case
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700203 if (layout_ == rh_ds_layout->GetDescriptorSetLayout()) return true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600204 if (descriptor_count_ != rh_ds_layout->descriptor_count_) {
205 std::stringstream error_str;
206 error_str << "DescriptorSetLayout " << layout_ << " has " << descriptor_count_ << " descriptors, but DescriptorSetLayout "
Tobin Ehlisb1861d92017-07-06 16:50:10 -0600207 << rh_ds_layout->GetDescriptorSetLayout() << ", which comes from pipelineLayout, has "
208 << rh_ds_layout->descriptor_count_ << " descriptors.";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600209 *error_msg = error_str.str();
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700210 return false; // trivial fail case
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600211 }
212 // Descriptor counts match so need to go through bindings one-by-one
213 // and verify that type and stageFlags match
214 for (auto binding : bindings_) {
215 // TODO : Do we also need to check immutable samplers?
216 // VkDescriptorSetLayoutBinding *rh_binding;
Tobin Ehlis664e6012016-05-05 11:04:44 -0600217 if (binding.descriptorCount != rh_ds_layout->GetDescriptorCountFromBinding(binding.binding)) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600218 std::stringstream error_str;
Tobin Ehlis664e6012016-05-05 11:04:44 -0600219 error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << layout_ << " has a descriptorCount of "
220 << binding.descriptorCount << " but binding " << binding.binding << " for DescriptorSetLayout "
Tobin Ehlisb1861d92017-07-06 16:50:10 -0600221 << rh_ds_layout->GetDescriptorSetLayout() << ", which comes from pipelineLayout, has a descriptorCount of "
Tobin Ehlis664e6012016-05-05 11:04:44 -0600222 << rh_ds_layout->GetDescriptorCountFromBinding(binding.binding);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600223 *error_msg = error_str.str();
224 return false;
Tobin Ehlis664e6012016-05-05 11:04:44 -0600225 } else if (binding.descriptorType != rh_ds_layout->GetTypeFromBinding(binding.binding)) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600226 std::stringstream error_str;
Tobin Ehlis664e6012016-05-05 11:04:44 -0600227 error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << layout_ << " is type '"
228 << string_VkDescriptorType(binding.descriptorType) << "' but binding " << binding.binding
Tobin Ehlisb1861d92017-07-06 16:50:10 -0600229 << " for DescriptorSetLayout " << rh_ds_layout->GetDescriptorSetLayout()
230 << ", which comes from pipelineLayout, is type '"
Tobin Ehlis664e6012016-05-05 11:04:44 -0600231 << string_VkDescriptorType(rh_ds_layout->GetTypeFromBinding(binding.binding)) << "'";
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600232 *error_msg = error_str.str();
233 return false;
Tobin Ehlis664e6012016-05-05 11:04:44 -0600234 } else if (binding.stageFlags != rh_ds_layout->GetStageFlagsFromBinding(binding.binding)) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600235 std::stringstream error_str;
Tobin Ehlis664e6012016-05-05 11:04:44 -0600236 error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << layout_ << " has stageFlags "
237 << binding.stageFlags << " but binding " << binding.binding << " for DescriptorSetLayout "
Tobin Ehlisb1861d92017-07-06 16:50:10 -0600238 << rh_ds_layout->GetDescriptorSetLayout() << ", which comes from pipelineLayout, has stageFlags "
Tobin Ehlis664e6012016-05-05 11:04:44 -0600239 << rh_ds_layout->GetStageFlagsFromBinding(binding.binding);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600240 *error_msg = error_str.str();
241 return false;
242 }
243 }
244 return true;
245}
246
247bool cvdescriptorset::DescriptorSetLayout::IsNextBindingConsistent(const uint32_t binding) const {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700248 if (!binding_to_index_map_.count(binding + 1)) return false;
Tobin Ehlis0bc30632016-05-05 10:16:02 -0600249 auto const &bi_itr = binding_to_index_map_.find(binding);
250 if (bi_itr != binding_to_index_map_.end()) {
251 const auto &next_bi_itr = binding_to_index_map_.find(binding + 1);
252 if (next_bi_itr != binding_to_index_map_.end()) {
Tobin Ehlis664e6012016-05-05 11:04:44 -0600253 auto type = bindings_[bi_itr->second].descriptorType;
254 auto stage_flags = bindings_[bi_itr->second].stageFlags;
255 auto immut_samp = bindings_[bi_itr->second].pImmutableSamplers ? true : false;
256 if ((type != bindings_[next_bi_itr->second].descriptorType) ||
257 (stage_flags != bindings_[next_bi_itr->second].stageFlags) ||
258 (immut_samp != (bindings_[next_bi_itr->second].pImmutableSamplers ? true : false))) {
Tobin Ehlis0bc30632016-05-05 10:16:02 -0600259 return false;
260 }
261 return true;
262 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600263 }
Tobin Ehlis0bc30632016-05-05 10:16:02 -0600264 return false;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600265}
Tobin Ehlis1f946f82016-05-05 12:03:44 -0600266// Starting at offset descriptor of given binding, parse over update_count
267// descriptor updates and verify that for any binding boundaries that are crossed, the next binding(s) are all consistent
268// Consistency means that their type, stage flags, and whether or not they use immutable samplers matches
269// If so, return true. If not, fill in error_msg and return false
270bool cvdescriptorset::DescriptorSetLayout::VerifyUpdateConsistency(uint32_t current_binding, uint32_t offset, uint32_t update_count,
271 const char *type, const VkDescriptorSet set,
272 std::string *error_msg) const {
273 // Verify consecutive bindings match (if needed)
274 auto orig_binding = current_binding;
275 // Track count of descriptors in the current_bindings that are remaining to be updated
276 auto binding_remaining = GetDescriptorCountFromBinding(current_binding);
277 // First, it's legal to offset beyond your own binding so handle that case
278 // Really this is just searching for the binding in which the update begins and adjusting offset accordingly
279 while (offset >= binding_remaining) {
280 // Advance to next binding, decrement offset by binding size
281 offset -= binding_remaining;
282 binding_remaining = GetDescriptorCountFromBinding(++current_binding);
283 }
284 binding_remaining -= offset;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700285 while (update_count > binding_remaining) { // While our updates overstep current binding
Tobin Ehlis1f946f82016-05-05 12:03:44 -0600286 // Verify next consecutive binding matches type, stage flags & immutable sampler use
287 if (!IsNextBindingConsistent(current_binding++)) {
288 std::stringstream error_str;
289 error_str << "Attempting " << type << " descriptor set " << set << " binding #" << orig_binding << " with #"
290 << update_count << " descriptors being updated but this update oversteps the bounds of this binding and the "
291 "next binding is not consistent with current binding so this update is invalid.";
292 *error_msg = error_str.str();
293 return false;
294 }
295 // For sake of this check consider the bindings updated and grab count for next binding
296 update_count -= binding_remaining;
297 binding_remaining = GetDescriptorCountFromBinding(current_binding);
298 }
299 return true;
300}
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600301
Tobin Ehlis68d0adf2016-06-01 11:33:50 -0600302cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t count)
303 : required_descriptors_by_type{}, layout_nodes(count, nullptr) {}
304
Tobin Ehlis93f22372016-10-12 14:34:12 -0600305cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const VkDescriptorPool pool,
John Zulauf48a6a702017-12-22 17:14:54 -0700306 const std::shared_ptr<DescriptorSetLayout const> &layout, layer_data *dev_data)
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -0700307 : some_update_(false),
308 set_(set),
309 pool_state_(nullptr),
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600310 p_layout_(layout),
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -0700311 device_data_(dev_data),
Józef Kucia1bb00972017-09-10 11:24:08 +0200312 limits_(GetPhysDevProperties(dev_data)->properties.limits) {
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -0700313 pool_state_ = GetDescriptorPoolState(dev_data, pool);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600314 // Foreach binding, create default descriptors of given type
John Zulaufb6d71202017-12-22 16:47:09 -0700315 descriptors_.reserve(p_layout_->GetTotalDescriptorCount());
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600316 for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) {
317 auto type = p_layout_->GetTypeFromIndex(i);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600318 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700319 case VK_DESCRIPTOR_TYPE_SAMPLER: {
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600320 auto immut_sampler = p_layout_->GetImmutableSamplerPtrFromIndex(i);
321 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) {
Tobin Ehlis082c7512017-05-08 11:24:57 -0600322 if (immut_sampler) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700323 descriptors_.emplace_back(new SamplerDescriptor(immut_sampler + di));
Tobin Ehlis082c7512017-05-08 11:24:57 -0600324 some_update_ = true; // Immutable samplers are updated at creation
325 } else
Chris Forbes9f340852017-05-09 08:51:38 -0700326 descriptors_.emplace_back(new SamplerDescriptor(nullptr));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700327 }
328 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600329 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700330 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600331 auto immut = p_layout_->GetImmutableSamplerPtrFromIndex(i);
332 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) {
Tobin Ehlis082c7512017-05-08 11:24:57 -0600333 if (immut) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700334 descriptors_.emplace_back(new ImageSamplerDescriptor(immut + di));
Tobin Ehlis082c7512017-05-08 11:24:57 -0600335 some_update_ = true; // Immutable samplers are updated at creation
336 } else
Chris Forbes9f340852017-05-09 08:51:38 -0700337 descriptors_.emplace_back(new ImageSamplerDescriptor(nullptr));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700338 }
339 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600340 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700341 // ImageDescriptors
342 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
343 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
344 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600345 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700346 descriptors_.emplace_back(new ImageDescriptor(type));
347 break;
348 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
349 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600350 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700351 descriptors_.emplace_back(new TexelDescriptor(type));
352 break;
353 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
354 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
355 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
356 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600357 for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700358 descriptors_.emplace_back(new BufferDescriptor(type));
359 break;
360 default:
361 assert(0); // Bad descriptor type specified
362 break;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600363 }
364 }
365}
Tobin Ehlis56a30942016-05-19 08:00:00 -0600366
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700367cvdescriptorset::DescriptorSet::~DescriptorSet() { InvalidateBoundCmdBuffers(); }
Chris Forbes57989132016-07-26 17:06:10 +1200368
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700369static std::string string_descriptor_req_view_type(descriptor_req req) {
370 std::string result("");
Chris Forbes57989132016-07-26 17:06:10 +1200371 for (unsigned i = 0; i <= VK_IMAGE_VIEW_TYPE_END_RANGE; i++) {
372 if (req & (1 << i)) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700373 if (result.size()) result += ", ";
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700374 result += string_VkImageViewType(VkImageViewType(i));
Chris Forbes57989132016-07-26 17:06:10 +1200375 }
376 }
377
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700378 if (!result.size()) result = "(none)";
Chris Forbes6e58ebd2016-08-31 12:58:14 -0700379
380 return result;
Chris Forbes57989132016-07-26 17:06:10 +1200381}
382
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600383// Is this sets underlying layout compatible with passed in layout according to "Pipeline Layout Compatibility" in spec?
Tobin Ehlis6dc57dd2017-06-21 10:08:52 -0600384bool cvdescriptorset::DescriptorSet::IsCompatible(DescriptorSetLayout const *const layout, std::string *error) const {
385 return layout->IsCompatible(p_layout_.get(), error);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600386}
Chris Forbes57989132016-07-26 17:06:10 +1200387
Tobin Ehlis3066db62016-08-22 08:12:23 -0600388// 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 -0600389// This includes validating that all descriptors in the given bindings are updated,
390// that any update buffers are valid, and that any dynamic offsets are within the bounds of their buffers.
391// Return true if state is acceptable, or false and write an error message into error string
Tobin Ehliscebc4c02016-08-22 10:10:43 -0600392bool cvdescriptorset::DescriptorSet::ValidateDrawState(const std::map<uint32_t, descriptor_req> &bindings,
John Zulauf48a6a702017-12-22 17:14:54 -0700393 const std::vector<uint32_t> &dynamic_offsets, GLOBAL_CB_NODE *cb_node,
Tobin Ehlisc8266452017-04-07 12:20:30 -0600394 const char *caller, std::string *error) const {
Chris Forbesc7090a82016-07-25 18:10:41 +1200395 for (auto binding_pair : bindings) {
396 auto binding = binding_pair.first;
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600397 if (!p_layout_->HasBinding(binding)) {
Tobin Ehlis58c59582016-06-21 12:34:33 -0600398 std::stringstream error_str;
399 error_str << "Attempting to validate DrawState for binding #" << binding
400 << " which is an invalid binding for this descriptor set.";
401 *error = error_str.str();
402 return false;
403 }
John Zulaufc483f442017-12-15 14:02:06 -0700404 IndexRange index_range = p_layout_->GetGlobalIndexRangeFromBinding(binding);
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700405 auto array_idx = 0; // Track array idx if we're dealing with array descriptors
John Zulaufc483f442017-12-15 14:02:06 -0700406 for (uint32_t i = index_range.start; i < index_range.end; ++i, ++array_idx) {
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700407 if (!descriptors_[i]->updated) {
408 std::stringstream error_str;
409 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
410 << " is being used in draw but has not been updated.";
411 *error = error_str.str();
412 return false;
413 } else {
414 auto descriptor_class = descriptors_[i]->GetClass();
415 if (descriptor_class == GeneralBuffer) {
416 // Verify that buffers are valid
417 auto buffer = static_cast<BufferDescriptor *>(descriptors_[i].get())->GetBuffer();
418 auto buffer_node = GetBufferState(device_data_, buffer);
419 if (!buffer_node) {
420 std::stringstream error_str;
421 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
422 << " references invalid buffer " << buffer << ".";
423 *error = error_str.str();
424 return false;
John Zulauf48a6a702017-12-22 17:14:54 -0700425 } else if (!buffer_node->sparse) {
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700426 for (auto mem_binding : buffer_node->GetBoundMemory()) {
427 if (!GetMemObjInfo(device_data_, mem_binding)) {
428 std::stringstream error_str;
429 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
430 << " uses buffer " << buffer << " that references invalid memory " << mem_binding << ".";
431 *error = error_str.str();
Tobin Ehlisc8266452017-04-07 12:20:30 -0600432 return false;
433 }
434 }
John Zulauf48a6a702017-12-22 17:14:54 -0700435 } else {
436 // Enqueue sparse resource validation, as these can only be validated at submit time
437 auto device_data_copy = device_data_; // Cannot capture members by value, so make capturable copy.
438 std::function<bool(void)> function = [device_data_copy, caller, buffer_node]() {
439 return core_validation::ValidateBufferMemoryIsValid(device_data_copy, buffer_node, caller);
440 };
441 cb_node->queue_submit_functions.push_back(function);
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700442 }
443 if (descriptors_[i]->IsDynamic()) {
444 // Validate that dynamic offsets are within the buffer
445 auto buffer_size = buffer_node->createInfo.size;
446 auto range = static_cast<BufferDescriptor *>(descriptors_[i].get())->GetRange();
447 auto desc_offset = static_cast<BufferDescriptor *>(descriptors_[i].get())->GetOffset();
448 auto dyn_offset = dynamic_offsets[GetDynamicOffsetIndexFromBinding(binding) + array_idx];
449 if (VK_WHOLE_SIZE == range) {
450 if ((dyn_offset + desc_offset) > buffer_size) {
451 std::stringstream error_str;
452 error_str << "Dynamic descriptor in binding #" << binding << " at global descriptor index " << i
453 << " uses buffer " << buffer << " with update range of VK_WHOLE_SIZE has dynamic offset "
454 << dyn_offset << " combined with offset " << desc_offset
455 << " that oversteps the buffer size of " << buffer_size << ".";
456 *error = error_str.str();
457 return false;
458 }
459 } else {
460 if ((dyn_offset + desc_offset + range) > buffer_size) {
461 std::stringstream error_str;
462 error_str << "Dynamic descriptor in binding #" << binding << " at global descriptor index " << i
463 << " uses buffer " << buffer << " with dynamic offset " << dyn_offset
464 << " combined with offset " << desc_offset << " and range " << range
465 << " that oversteps the buffer size of " << buffer_size << ".";
466 *error = error_str.str();
467 return false;
468 }
469 }
470 }
471 } else if (descriptor_class == ImageSampler || descriptor_class == Image) {
472 VkImageView image_view;
473 VkImageLayout image_layout;
474 if (descriptor_class == ImageSampler) {
475 image_view = static_cast<ImageSamplerDescriptor *>(descriptors_[i].get())->GetImageView();
476 image_layout = static_cast<ImageSamplerDescriptor *>(descriptors_[i].get())->GetImageLayout();
477 } else {
478 image_view = static_cast<ImageDescriptor *>(descriptors_[i].get())->GetImageView();
479 image_layout = static_cast<ImageDescriptor *>(descriptors_[i].get())->GetImageLayout();
480 }
481 auto reqs = binding_pair.second;
482
483 auto image_view_state = GetImageViewState(device_data_, image_view);
Tobin Ehlis836a1372017-07-14 11:25:21 -0600484 if (nullptr == image_view_state) {
485 // Image view must have been destroyed since initial update. Could potentially flag the descriptor
486 // as "invalid" (updated = false) at DestroyImageView() time and detect this error at bind time
487 std::stringstream error_str;
488 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
489 << " is using imageView " << image_view << " that has been destroyed.";
490 *error = error_str.str();
491 return false;
492 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700493 auto image_view_ci = image_view_state->create_info;
494
495 if ((reqs & DESCRIPTOR_REQ_ALL_VIEW_TYPE_BITS) && (~reqs & (1 << image_view_ci.viewType))) {
496 // bad view type
497 std::stringstream error_str;
498 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
499 << " requires an image view of type " << string_descriptor_req_view_type(reqs) << " but got "
500 << string_VkImageViewType(image_view_ci.viewType) << ".";
501 *error = error_str.str();
502 return false;
503 }
504
505 auto image_node = GetImageState(device_data_, image_view_ci.image);
506 assert(image_node);
507 // Verify Image Layout
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700508 // Copy first mip level into sub_layers and loop over each mip level to verify layout
509 VkImageSubresourceLayers sub_layers;
510 sub_layers.aspectMask = image_view_ci.subresourceRange.aspectMask;
511 sub_layers.baseArrayLayer = image_view_ci.subresourceRange.baseArrayLayer;
512 sub_layers.layerCount = image_view_ci.subresourceRange.layerCount;
513 bool hit_error = false;
514 for (auto cur_level = image_view_ci.subresourceRange.baseMipLevel;
515 cur_level < image_view_ci.subresourceRange.levelCount; ++cur_level) {
516 sub_layers.mipLevel = cur_level;
517 VerifyImageLayout(device_data_, cb_node, image_node, sub_layers, image_layout, VK_IMAGE_LAYOUT_UNDEFINED,
Chris Forbesc6bb6ce2017-07-21 14:03:06 -0700518 caller, VALIDATION_ERROR_046002b0, &hit_error);
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700519 if (hit_error) {
520 *error =
521 "Image layout specified at vkUpdateDescriptorSets() time doesn't match actual image layout at "
522 "time descriptor is used. See previous error callback for specific details.";
Chris Forbes57989132016-07-26 17:06:10 +1200523 return false;
524 }
Chris Forbes1f7f3ca2017-05-08 13:54:50 -0700525 }
526 // Verify Sample counts
527 if ((reqs & DESCRIPTOR_REQ_SINGLE_SAMPLE) && image_node->createInfo.samples != VK_SAMPLE_COUNT_1_BIT) {
528 std::stringstream error_str;
529 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
530 << " requires bound image to have VK_SAMPLE_COUNT_1_BIT but got "
531 << string_VkSampleCountFlagBits(image_node->createInfo.samples) << ".";
532 *error = error_str.str();
533 return false;
534 }
535 if ((reqs & DESCRIPTOR_REQ_MULTI_SAMPLE) && image_node->createInfo.samples == VK_SAMPLE_COUNT_1_BIT) {
536 std::stringstream error_str;
537 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
538 << " requires bound image to have multiple samples, but got VK_SAMPLE_COUNT_1_BIT.";
539 *error = error_str.str();
540 return false;
Chris Forbes57989132016-07-26 17:06:10 +1200541 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600542 }
543 }
544 }
545 }
546 return true;
547}
Chris Forbes57989132016-07-26 17:06:10 +1200548
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600549// For given bindings, place any update buffers or images into the passed-in unordered_sets
Tobin Ehliscebc4c02016-08-22 10:10:43 -0600550uint32_t cvdescriptorset::DescriptorSet::GetStorageUpdates(const std::map<uint32_t, descriptor_req> &bindings,
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600551 std::unordered_set<VkBuffer> *buffer_set,
552 std::unordered_set<VkImageView> *image_set) const {
553 auto num_updates = 0;
Chris Forbesc7090a82016-07-25 18:10:41 +1200554 for (auto binding_pair : bindings) {
555 auto binding = binding_pair.first;
Tobin Ehlis58c59582016-06-21 12:34:33 -0600556 // If a binding doesn't exist, skip it
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600557 if (!p_layout_->HasBinding(binding)) {
Tobin Ehlis58c59582016-06-21 12:34:33 -0600558 continue;
559 }
John Zulaufc483f442017-12-15 14:02:06 -0700560 uint32_t start_idx = p_layout_->GetGlobalIndexRangeFromBinding(binding).start;
Tobin Ehlis81f17852016-05-05 09:04:33 -0600561 if (descriptors_[start_idx]->IsStorage()) {
562 if (Image == descriptors_[start_idx]->descriptor_class) {
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600563 for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) {
Tobin Ehlis81f17852016-05-05 09:04:33 -0600564 if (descriptors_[start_idx + i]->updated) {
565 image_set->insert(static_cast<ImageDescriptor *>(descriptors_[start_idx + i].get())->GetImageView());
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600566 num_updates++;
567 }
568 }
Tobin Ehlis81f17852016-05-05 09:04:33 -0600569 } else if (TexelBuffer == descriptors_[start_idx]->descriptor_class) {
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600570 for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) {
Tobin Ehlis81f17852016-05-05 09:04:33 -0600571 if (descriptors_[start_idx + i]->updated) {
572 auto bufferview = static_cast<TexelDescriptor *>(descriptors_[start_idx + i].get())->GetBufferView();
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -0700573 auto bv_state = GetBufferViewState(device_data_, bufferview);
Tobin Ehlis8b872462016-09-14 08:12:08 -0600574 if (bv_state) {
575 buffer_set->insert(bv_state->create_info.buffer);
Tobin Ehlis0bc30632016-05-05 10:16:02 -0600576 num_updates++;
577 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600578 }
579 }
Tobin Ehlis81f17852016-05-05 09:04:33 -0600580 } else if (GeneralBuffer == descriptors_[start_idx]->descriptor_class) {
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600581 for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) {
Tobin Ehlis81f17852016-05-05 09:04:33 -0600582 if (descriptors_[start_idx + i]->updated) {
583 buffer_set->insert(static_cast<BufferDescriptor *>(descriptors_[start_idx + i].get())->GetBuffer());
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600584 num_updates++;
585 }
586 }
587 }
588 }
589 }
590 return num_updates;
591}
Tobin Ehlis9906d9d2016-05-17 14:23:46 -0600592// Set is being deleted or updates so invalidate all bound cmd buffers
593void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers() {
Petr Krausbc7f5442017-05-14 23:43:38 +0200594 core_validation::invalidateCommandBuffers(device_data_, cb_bindings, {HandleToUint64(set_), kVulkanObjectTypeDescriptorSet});
Tobin Ehlis9906d9d2016-05-17 14:23:46 -0600595}
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600596// Perform write update in given update struct
Tobin Ehlis300888c2016-05-18 13:43:26 -0600597void cvdescriptorset::DescriptorSet::PerformWriteUpdate(const VkWriteDescriptorSet *update) {
Tobin Ehlisf922ef82016-11-30 10:19:14 -0700598 // Perform update on a per-binding basis as consecutive updates roll over to next binding
599 auto descriptors_remaining = update->descriptorCount;
600 auto binding_being_updated = update->dstBinding;
601 auto offset = update->dstArrayElement;
Tobin Ehlise16805c2017-08-09 09:10:37 -0600602 uint32_t update_index = 0;
Tobin Ehlisf922ef82016-11-30 10:19:14 -0700603 while (descriptors_remaining) {
604 uint32_t update_count = std::min(descriptors_remaining, GetDescriptorCountFromBinding(binding_being_updated));
John Zulaufc483f442017-12-15 14:02:06 -0700605 auto global_idx = p_layout_->GetGlobalIndexRangeFromBinding(binding_being_updated).start + offset;
Tobin Ehlisf922ef82016-11-30 10:19:14 -0700606 // Loop over the updates for a single binding at a time
Tobin Ehlise16805c2017-08-09 09:10:37 -0600607 for (uint32_t di = 0; di < update_count; ++di, ++update_index) {
608 descriptors_[global_idx + di]->WriteUpdate(update, update_index);
Tobin Ehlisf922ef82016-11-30 10:19:14 -0700609 }
610 // Roll over to next binding in case of consecutive update
611 descriptors_remaining -= update_count;
612 offset = 0;
613 binding_being_updated++;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600614 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700615 if (update->descriptorCount) some_update_ = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -0600616
Tobin Ehlis9906d9d2016-05-17 14:23:46 -0600617 InvalidateBoundCmdBuffers();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600618}
Tobin Ehlis300888c2016-05-18 13:43:26 -0600619// Validate Copy update
620bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data *report_data, const VkCopyDescriptorSet *update,
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600621 const DescriptorSet *src_set, UNIQUE_VALIDATION_ERROR_CODE *error_code,
622 std::string *error_msg) {
Tobin Ehlis03d61de2016-05-17 08:31:46 -0600623 // Verify idle ds
624 if (in_use.load()) {
Tobin Ehlis2cb8eb22017-01-03 14:09:57 -0700625 // TODO : Re-using Free Idle error code, need copy update idle error code
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600626 *error_code = VALIDATION_ERROR_2860026a;
Tobin Ehlis03d61de2016-05-17 08:31:46 -0600627 std::stringstream error_str;
628 error_str << "Cannot call vkUpdateDescriptorSets() to perform copy update on descriptor set " << set_
Tobin Ehlis1d81edd2016-11-21 09:50:49 -0700629 << " that is in use by a command buffer";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600630 *error_msg = error_str.str();
Tobin Ehlis03d61de2016-05-17 08:31:46 -0600631 return false;
632 }
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600633 if (!p_layout_->HasBinding(update->dstBinding)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600634 *error_code = VALIDATION_ERROR_032002b6;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600635 std::stringstream error_str;
Tobin Ehlis1d81edd2016-11-21 09:50:49 -0700636 error_str << "DescriptorSet " << set_ << " does not have copy update dest binding of " << update->dstBinding;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600637 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600638 return false;
639 }
640 if (!src_set->HasBinding(update->srcBinding)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600641 *error_code = VALIDATION_ERROR_032002b2;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600642 std::stringstream error_str;
Tobin Ehlis1d81edd2016-11-21 09:50:49 -0700643 error_str << "DescriptorSet " << set_ << " does not have copy update src binding of " << update->srcBinding;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600644 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600645 return false;
646 }
647 // src & dst set bindings are valid
648 // Check bounds of src & dst
John Zulaufc483f442017-12-15 14:02:06 -0700649 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600650 if ((src_start_idx + update->descriptorCount) > src_set->GetTotalDescriptorCount()) {
651 // SRC update out of bounds
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600652 *error_code = VALIDATION_ERROR_032002b4;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600653 std::stringstream error_str;
654 error_str << "Attempting copy update from descriptorSet " << update->srcSet << " binding#" << update->srcBinding
John Zulaufc483f442017-12-15 14:02:06 -0700655 << " with offset index of " << src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600656 << " plus update array offset of " << update->srcArrayElement << " and update of " << update->descriptorCount
Tobin Ehlis1d81edd2016-11-21 09:50:49 -0700657 << " descriptors oversteps total number of descriptors in set: " << src_set->GetTotalDescriptorCount();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600658 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600659 return false;
660 }
John Zulaufc483f442017-12-15 14:02:06 -0700661 auto dst_start_idx = p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600662 if ((dst_start_idx + update->descriptorCount) > p_layout_->GetTotalDescriptorCount()) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600663 // DST update out of bounds
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600664 *error_code = VALIDATION_ERROR_032002b8;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600665 std::stringstream error_str;
666 error_str << "Attempting copy update to descriptorSet " << set_ << " binding#" << update->dstBinding
John Zulaufc483f442017-12-15 14:02:06 -0700667 << " with offset index of " << p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600668 << " plus update array offset of " << update->dstArrayElement << " and update of " << update->descriptorCount
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600669 << " descriptors oversteps total number of descriptors in set: " << p_layout_->GetTotalDescriptorCount();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600670 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600671 return false;
672 }
673 // Check that types match
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600674 // TODO : Base default error case going from here is VALIDATION_ERROR_0002b8012ba which covers all consistency issues, need more
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600675 // fine-grained error codes
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600676 *error_code = VALIDATION_ERROR_032002ba;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600677 auto src_type = src_set->GetTypeFromBinding(update->srcBinding);
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600678 auto dst_type = p_layout_->GetTypeFromBinding(update->dstBinding);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600679 if (src_type != dst_type) {
680 std::stringstream error_str;
681 error_str << "Attempting copy update to descriptorSet " << set_ << " binding #" << update->dstBinding << " with type "
682 << string_VkDescriptorType(dst_type) << " from descriptorSet " << src_set->GetSet() << " binding #"
Tobin Ehlis1d81edd2016-11-21 09:50:49 -0700683 << update->srcBinding << " with type " << string_VkDescriptorType(src_type) << ". Types do not match";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600684 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600685 return false;
686 }
687 // Verify consistency of src & dst bindings if update crosses binding boundaries
Tobin Ehlis1f946f82016-05-05 12:03:44 -0600688 if ((!src_set->GetLayout()->VerifyUpdateConsistency(update->srcBinding, update->srcArrayElement, update->descriptorCount,
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600689 "copy update from", src_set->GetSet(), error_msg)) ||
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600690 (!p_layout_->VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, "copy update to",
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600691 set_, error_msg))) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600692 return false;
693 }
Tobin Ehlisd41e7b62016-05-19 07:56:18 -0600694 // Update parameters all look good and descriptor updated so verify update contents
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700695 if (!VerifyCopyUpdateContents(update, src_set, src_type, src_start_idx, error_code, error_msg)) return false;
Tobin Ehlis300888c2016-05-18 13:43:26 -0600696
697 // All checks passed so update is good
698 return true;
699}
700// Perform Copy update
701void cvdescriptorset::DescriptorSet::PerformCopyUpdate(const VkCopyDescriptorSet *update, const DescriptorSet *src_set) {
John Zulaufc483f442017-12-15 14:02:06 -0700702 auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
703 auto dst_start_idx = p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600704 // Update parameters all look good so perform update
705 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Józef Kucia5297e372017-10-13 22:31:34 +0200706 auto src = src_set->descriptors_[src_start_idx + di].get();
707 auto dst = descriptors_[dst_start_idx + di].get();
708 if (src->updated) {
709 dst->CopyUpdate(src);
710 some_update_ = true;
711 } else {
712 dst->updated = false;
713 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600714 }
Tobin Ehlis56a30942016-05-19 08:00:00 -0600715
Tobin Ehlis9906d9d2016-05-17 14:23:46 -0600716 InvalidateBoundCmdBuffers();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600717}
Tobin Ehlis56a30942016-05-19 08:00:00 -0600718
Tobin Ehlisf9519102016-08-17 09:49:13 -0600719// Bind cb_node to this set and this set to cb_node.
720// Prereq: This should be called for a set that has been confirmed to be active for the given cb_node, meaning it's going
721// to be used in a draw by the given cb_node
Tobin Ehlis276d3d32016-12-21 09:21:06 -0700722void cvdescriptorset::DescriptorSet::BindCommandBuffer(GLOBAL_CB_NODE *cb_node,
Tobin Ehlis022528b2016-12-29 12:22:32 -0700723 const std::map<uint32_t, descriptor_req> &binding_req_map) {
Tobin Ehlis9252c2b2016-07-21 14:40:22 -0600724 // bind cb to this descriptor set
725 cb_bindings.insert(cb_node);
Tobin Ehlis7ca20be2016-10-12 15:09:16 -0600726 // Add bindings for descriptor set, the set's pool, and individual objects in the set
Petr Krausbc7f5442017-05-14 23:43:38 +0200727 cb_node->object_bindings.insert({HandleToUint64(set_), kVulkanObjectTypeDescriptorSet});
Tobin Ehlis7ca20be2016-10-12 15:09:16 -0600728 pool_state_->cb_bindings.insert(cb_node);
Petr Krausbc7f5442017-05-14 23:43:38 +0200729 cb_node->object_bindings.insert({HandleToUint64(pool_state_->pool), kVulkanObjectTypeDescriptorPool});
Tobin Ehlisf9519102016-08-17 09:49:13 -0600730 // For the active slots, use set# to look up descriptorSet from boundDescriptorSets, and bind all of that descriptor set's
731 // resources
Tobin Ehlis022528b2016-12-29 12:22:32 -0700732 for (auto binding_req_pair : binding_req_map) {
733 auto binding = binding_req_pair.first;
John Zulaufc483f442017-12-15 14:02:06 -0700734 auto range = p_layout_->GetGlobalIndexRangeFromBinding(binding);
735 for (uint32_t i = range.start; i < range.end; ++i) {
Tobin Ehlis8020eea2016-08-17 11:10:41 -0600736 descriptors_[i]->BindCommandBuffer(device_data_, cb_node);
737 }
738 }
Tobin Ehlis9252c2b2016-07-21 14:40:22 -0600739}
John Zulauf48a6a702017-12-22 17:14:54 -0700740void cvdescriptorset::DescriptorSet::FilterAndTrackOneBindingReq(const BindingReqMap::value_type &binding_req_pair,
741 const BindingReqMap &in_req, BindingReqMap *out_req,
742 TrackedBindings *bindings) {
743 assert(out_req);
744 assert(bindings);
745 const auto binding = binding_req_pair.first;
746 // Use insert and look at the boolean ("was inserted") in the returned pair to see if this is a new set member.
747 // Saves one hash lookup vs. find ... compare w/ end ... insert.
748 const auto it_bool_pair = bindings->insert(binding);
749 if (it_bool_pair.second) {
750 out_req->emplace(binding_req_pair);
751 }
752}
753void cvdescriptorset::DescriptorSet::FilterAndTrackOneBindingReq(const BindingReqMap::value_type &binding_req_pair,
754 const BindingReqMap &in_req, BindingReqMap *out_req,
755 TrackedBindings *bindings, uint32_t limit) {
756 if (bindings->size() < limit) FilterAndTrackOneBindingReq(binding_req_pair, in_req, out_req, bindings);
757}
758
759void cvdescriptorset::DescriptorSet::FilterAndTrackBindingReqs(GLOBAL_CB_NODE *cb_state, const BindingReqMap &in_req,
760 BindingReqMap *out_req) {
761 TrackedBindings &bound = cached_validation_[cb_state].command_binding_and_usage;
762 if (bound.size() == GetBindingCount()) {
763 return; // All bindings are bound, out req is empty
764 }
765 for (const auto &binding_req_pair : in_req) {
766 const auto binding = binding_req_pair.first;
767 // If a binding doesn't exist, or has already been bound, skip it
768 if (p_layout_->HasBinding(binding)) {
769 FilterAndTrackOneBindingReq(binding_req_pair, in_req, out_req, &bound);
770 }
771 }
772}
773
774void cvdescriptorset::DescriptorSet::FilterAndTrackBindingReqs(GLOBAL_CB_NODE *cb_state, PIPELINE_STATE *pipeline,
775 const BindingReqMap &in_req, BindingReqMap *out_req) {
776 auto &validated = cached_validation_[cb_state];
777 auto &image_sample_val = validated.image_samplers[pipeline];
778 auto *const dynamic_buffers = &validated.dynamic_buffers;
779 auto *const non_dynamic_buffers = &validated.non_dynamic_buffers;
780 const auto &stats = p_layout_->GetBindingTypeStats();
781 for (const auto &binding_req_pair : in_req) {
782 auto binding = binding_req_pair.first;
783 VkDescriptorSetLayoutBinding const *layout_binding = p_layout_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
784 if (!layout_binding) {
785 continue;
786 }
787 // Caching criteria differs per type.
788 // If image_layout have changed , the image descriptors need to be validated against them.
789 if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
790 (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
791 FilterAndTrackOneBindingReq(binding_req_pair, in_req, out_req, dynamic_buffers, stats.dynamic_buffer_count);
792 } else if ((layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
793 (layout_binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)) {
794 FilterAndTrackOneBindingReq(binding_req_pair, in_req, out_req, non_dynamic_buffers, stats.non_dynamic_buffer_count);
795 } else {
796 // This is rather crude, as the changed layouts may not impact the bound descriptors,
797 // but the simple "versioning" is a simple "dirt" test.
798 auto &version = image_sample_val[binding]; // Take advantage of default construtor zero initialzing new entries
799 if (version != cb_state->image_layout_change_count) {
800 version = cb_state->image_layout_change_count;
801 out_req->emplace(binding_req_pair);
802 }
803 }
804 }
805}
Tobin Ehlis9252c2b2016-07-21 14:40:22 -0600806
Tobin Ehlis300888c2016-05-18 13:43:26 -0600807cvdescriptorset::SamplerDescriptor::SamplerDescriptor(const VkSampler *immut) : sampler_(VK_NULL_HANDLE), immutable_(false) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600808 updated = false;
809 descriptor_class = PlainSampler;
810 if (immut) {
811 sampler_ = *immut;
812 immutable_ = true;
813 updated = true;
814 }
815}
Tobin Ehlise2f80292016-06-02 10:08:53 -0600816// Validate given sampler. Currently this only checks to make sure it exists in the samplerMap
Tobin Ehlis58c884f2017-02-08 12:15:27 -0700817bool cvdescriptorset::ValidateSampler(const VkSampler sampler, const layer_data *dev_data) {
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -0700818 return (GetSamplerState(dev_data, sampler) != nullptr);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600819}
Tobin Ehlis56a30942016-05-19 08:00:00 -0600820
Tobin Ehlis554bf382016-05-24 11:14:43 -0600821bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type,
Tobin Ehlis58c884f2017-02-08 12:15:27 -0700822 const layer_data *dev_data, UNIQUE_VALIDATION_ERROR_CODE *error_code,
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600823 std::string *error_msg) {
824 // TODO : Defaulting to 00943 for all cases here. Need to create new error codes for various cases.
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600825 *error_code = VALIDATION_ERROR_15c0028c;
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -0700826 auto iv_state = GetImageViewState(dev_data, image_view);
Tobin Ehlis8b26a382016-09-14 08:02:49 -0600827 if (!iv_state) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600828 std::stringstream error_str;
829 error_str << "Invalid VkImageView: " << image_view;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600830 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600831 return false;
Tobin Ehlis1809f912016-05-25 09:24:36 -0600832 }
Tobin Ehlis81280962016-07-20 14:04:20 -0600833 // 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 -0600834 // Validate that imageLayout is compatible with aspect_mask and image format
835 // and validate that image usage bits are correct for given usage
Tobin Ehlis8b26a382016-09-14 08:02:49 -0600836 VkImageAspectFlags aspect_mask = iv_state->create_info.subresourceRange.aspectMask;
837 VkImage image = iv_state->create_info.image;
Tobin Ehlis1809f912016-05-25 09:24:36 -0600838 VkFormat format = VK_FORMAT_MAX_ENUM;
839 VkImageUsageFlags usage = 0;
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -0700840 auto image_node = GetImageState(dev_data, image);
Tobin Ehlis1c9c55f2016-06-02 11:49:22 -0600841 if (image_node) {
842 format = image_node->createInfo.format;
843 usage = image_node->createInfo.usage;
Tobin Ehlis029d2fe2016-09-21 09:19:15 -0600844 // Validate that memory is bound to image
Tobin Ehlis2cb8eb22017-01-03 14:09:57 -0700845 // TODO: This should have its own valid usage id apart from 2524 which is from CreateImageView case. The only
846 // the error here occurs is if memory bound to a created imageView has been freed.
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600847 if (ValidateMemoryIsBoundToImage(dev_data, image_node, "vkUpdateDescriptorSets()", VALIDATION_ERROR_0ac007f8)) {
848 *error_code = VALIDATION_ERROR_0ac007f8;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600849 *error_msg = "No memory bound to image.";
Tobin Ehlis029d2fe2016-09-21 09:19:15 -0600850 return false;
Tobin Ehlisfed999f2016-09-21 15:09:45 -0600851 }
Chris Forbes67757ff2017-07-21 13:59:01 -0700852
853 // KHR_maintenance1 allows rendering into 2D or 2DArray views which slice a 3D image,
854 // but not binding them to descriptor sets.
855 if (image_node->createInfo.imageType == VK_IMAGE_TYPE_3D &&
856 (iv_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_2D ||
857 iv_state->create_info.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)) {
858 *error_code = VALIDATION_ERROR_046002ae;
859 *error_msg = "ImageView must not be a 2D or 2DArray view of a 3D image";
860 return false;
861 }
Tobin Ehlis1809f912016-05-25 09:24:36 -0600862 }
863 // First validate that format and layout are compatible
864 if (format == VK_FORMAT_MAX_ENUM) {
865 std::stringstream error_str;
866 error_str << "Invalid image (" << image << ") in imageView (" << image_view << ").";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600867 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -0600868 return false;
869 }
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600870 // TODO : The various image aspect and format checks here are based on general spec language in 11.5 Image Views section under
871 // vkCreateImageView(). What's the best way to create unique id for these cases?
Dave Houlton1d2022c2017-03-29 11:43:58 -0600872 bool ds = FormatIsDepthOrStencil(format);
Tobin Ehlis1809f912016-05-25 09:24:36 -0600873 switch (image_layout) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700874 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
875 // Only Color bit must be set
876 if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
Tobin Ehlis1809f912016-05-25 09:24:36 -0600877 std::stringstream error_str;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700878 error_str << "ImageView (" << image_view << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but does "
879 "not have VK_IMAGE_ASPECT_COLOR_BIT set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600880 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -0600881 return false;
882 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700883 // format must NOT be DS
884 if (ds) {
885 std::stringstream error_str;
886 error_str << "ImageView (" << image_view
887 << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but the image format is "
888 << string_VkFormat(format) << " which is not a color format.";
889 *error_msg = error_str.str();
890 return false;
891 }
892 break;
893 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
894 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
895 // Depth or stencil bit must be set, but both must NOT be set
Tobin Ehlisbbf3f912016-06-15 13:03:58 -0600896 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
897 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
898 // both must NOT be set
899 std::stringstream error_str;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700900 error_str << "ImageView (" << image_view << ") has both STENCIL and DEPTH aspects set";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -0600901 *error_msg = error_str.str();
Tobin Ehlisbbf3f912016-06-15 13:03:58 -0600902 return false;
903 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700904 } else if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
905 // Neither were set
906 std::stringstream error_str;
907 error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout)
908 << " but does not have STENCIL or DEPTH aspects set";
909 *error_msg = error_str.str();
910 return false;
Tobin Ehlisbbf3f912016-06-15 13:03:58 -0600911 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700912 // format must be DS
913 if (!ds) {
914 std::stringstream error_str;
915 error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout)
916 << " but the image format is " << string_VkFormat(format) << " which is not a depth/stencil format.";
917 *error_msg = error_str.str();
918 return false;
919 }
920 break;
921 default:
922 // For other layouts if the source is depth/stencil image, both aspect bits must not be set
923 if (ds) {
924 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
925 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
926 // both must NOT be set
927 std::stringstream error_str;
928 error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout)
929 << " and is using depth/stencil image of format " << string_VkFormat(format)
930 << " but it has both STENCIL and DEPTH aspects set, which is illegal. When using a depth/stencil "
931 "image in a descriptor set, please only set either VK_IMAGE_ASPECT_DEPTH_BIT or "
932 "VK_IMAGE_ASPECT_STENCIL_BIT depending on whether it will be used for depth reads or stencil "
933 "reads respectively.";
934 *error_msg = error_str.str();
935 return false;
936 }
937 }
938 }
939 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -0600940 }
941 // Now validate that usage flags are correctly set for given type of update
Tobin Ehlisfb4cf712016-10-10 14:02:48 -0600942 // 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 -0600943 // TODO : The various image usage bit requirements are in general spec language for VkImageUsageFlags bit block in 11.3 Images
944 // under vkCreateImage()
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600945 // TODO : Need to also validate case VALIDATION_ERROR_15c002a0 where STORAGE_IMAGE & INPUT_ATTACH types must have been created
946 // with identify swizzle
Tobin Ehlis1809f912016-05-25 09:24:36 -0600947 std::string error_usage_bit;
948 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700949 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
950 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
951 if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
952 error_usage_bit = "VK_IMAGE_USAGE_SAMPLED_BIT";
953 }
954 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -0600955 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700956 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
957 if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
958 error_usage_bit = "VK_IMAGE_USAGE_STORAGE_BIT";
959 } else if (VK_IMAGE_LAYOUT_GENERAL != image_layout) {
960 std::stringstream error_str;
Tobin Ehlisbb03e5f2017-05-11 08:52:51 -0600961 // TODO : Need to create custom enum error codes for these cases
962 if (image_node->shared_presentable) {
963 if (VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR != image_layout) {
964 error_str
965 << "ImageView (" << image_view
966 << ") of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE type with a front-buffered image is being updated with "
967 "layout "
968 << string_VkImageLayout(image_layout)
969 << " but according to spec section 13.1 Descriptor Types, 'Front-buffered images that report support "
970 "for "
971 "VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT must be in the VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR layout.'";
972 *error_msg = error_str.str();
973 return false;
974 }
975 } else if (VK_IMAGE_LAYOUT_GENERAL != image_layout) {
976 error_str
977 << "ImageView (" << image_view << ") of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE type is being updated with layout "
978 << string_VkImageLayout(image_layout)
979 << " but according to spec section 13.1 Descriptor Types, 'Load and store operations on storage images can "
980 "only be done on images in VK_IMAGE_LAYOUT_GENERAL layout.'";
981 *error_msg = error_str.str();
982 return false;
983 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700984 }
985 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -0600986 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700987 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
988 if (!(usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
989 error_usage_bit = "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT";
990 }
991 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -0600992 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700993 default:
994 break;
Tobin Ehlis1809f912016-05-25 09:24:36 -0600995 }
996 if (!error_usage_bit.empty()) {
997 std::stringstream error_str;
998 error_str << "ImageView (" << image_view << ") with usage mask 0x" << usage
999 << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have "
1000 << error_usage_bit << " set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001001 *error_msg = error_str.str();
Tobin Ehlis1809f912016-05-25 09:24:36 -06001002 return false;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001003 }
1004 return true;
1005}
Tobin Ehlis56a30942016-05-19 08:00:00 -06001006
Tobin Ehlis300888c2016-05-18 13:43:26 -06001007void cvdescriptorset::SamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
1008 sampler_ = update->pImageInfo[index].sampler;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001009 updated = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001010}
1011
Tobin Ehlis300888c2016-05-18 13:43:26 -06001012void cvdescriptorset::SamplerDescriptor::CopyUpdate(const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001013 if (!immutable_) {
1014 auto update_sampler = static_cast<const SamplerDescriptor *>(src)->sampler_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001015 sampler_ = update_sampler;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001016 }
1017 updated = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001018}
Tobin Ehlis56a30942016-05-19 08:00:00 -06001019
Tobin Ehlis58c884f2017-02-08 12:15:27 -07001020void cvdescriptorset::SamplerDescriptor::BindCommandBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
Tobin Ehlis8020eea2016-08-17 11:10:41 -06001021 if (!immutable_) {
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001022 auto sampler_state = GetSamplerState(dev_data, sampler_);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001023 if (sampler_state) core_validation::AddCommandBufferBindingSampler(cb_node, sampler_state);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06001024 }
1025}
1026
Tobin Ehlis300888c2016-05-18 13:43:26 -06001027cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(const VkSampler *immut)
Chris Forbes9f340852017-05-09 08:51:38 -07001028 : sampler_(VK_NULL_HANDLE), immutable_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001029 updated = false;
1030 descriptor_class = ImageSampler;
1031 if (immut) {
1032 sampler_ = *immut;
1033 immutable_ = true;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001034 }
1035}
Tobin Ehlis56a30942016-05-19 08:00:00 -06001036
Tobin Ehlis300888c2016-05-18 13:43:26 -06001037void cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001038 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06001039 const auto &image_info = update->pImageInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06001040 sampler_ = image_info.sampler;
1041 image_view_ = image_info.imageView;
1042 image_layout_ = image_info.imageLayout;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001043}
1044
Tobin Ehlis300888c2016-05-18 13:43:26 -06001045void cvdescriptorset::ImageSamplerDescriptor::CopyUpdate(const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001046 if (!immutable_) {
1047 auto update_sampler = static_cast<const ImageSamplerDescriptor *>(src)->sampler_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001048 sampler_ = update_sampler;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001049 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001050 auto image_view = static_cast<const ImageSamplerDescriptor *>(src)->image_view_;
1051 auto image_layout = static_cast<const ImageSamplerDescriptor *>(src)->image_layout_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001052 updated = true;
1053 image_view_ = image_view;
1054 image_layout_ = image_layout;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001055}
1056
Tobin Ehlis58c884f2017-02-08 12:15:27 -07001057void cvdescriptorset::ImageSamplerDescriptor::BindCommandBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
Tobin Ehlis81e46372016-08-17 13:33:44 -06001058 // First add binding for any non-immutable sampler
Tobin Ehlis8020eea2016-08-17 11:10:41 -06001059 if (!immutable_) {
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001060 auto sampler_state = GetSamplerState(dev_data, sampler_);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001061 if (sampler_state) core_validation::AddCommandBufferBindingSampler(cb_node, sampler_state);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06001062 }
Tobin Ehlis81e46372016-08-17 13:33:44 -06001063 // Add binding for image
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001064 auto iv_state = GetImageViewState(dev_data, image_view_);
Tobin Ehlis8b26a382016-09-14 08:02:49 -06001065 if (iv_state) {
Tobin Ehlis15b8ea02016-09-19 14:02:58 -06001066 core_validation::AddCommandBufferBindingImageView(dev_data, cb_node, iv_state);
Tobin Ehlis81e46372016-08-17 13:33:44 -06001067 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06001068}
1069
Tobin Ehlis300888c2016-05-18 13:43:26 -06001070cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type)
1071 : storage_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001072 updated = false;
1073 descriptor_class = Image;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001074 if (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE == type) storage_ = true;
Petr Kraus13c98a62017-12-09 00:22:39 +01001075}
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001076
Tobin Ehlis300888c2016-05-18 13:43:26 -06001077void cvdescriptorset::ImageDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001078 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06001079 const auto &image_info = update->pImageInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06001080 image_view_ = image_info.imageView;
1081 image_layout_ = image_info.imageLayout;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001082}
1083
Tobin Ehlis300888c2016-05-18 13:43:26 -06001084void cvdescriptorset::ImageDescriptor::CopyUpdate(const Descriptor *src) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001085 auto image_view = static_cast<const ImageDescriptor *>(src)->image_view_;
1086 auto image_layout = static_cast<const ImageDescriptor *>(src)->image_layout_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001087 updated = true;
1088 image_view_ = image_view;
1089 image_layout_ = image_layout;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001090}
1091
Tobin Ehlis58c884f2017-02-08 12:15:27 -07001092void cvdescriptorset::ImageDescriptor::BindCommandBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
Tobin Ehlis81e46372016-08-17 13:33:44 -06001093 // Add binding for image
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001094 auto iv_state = GetImageViewState(dev_data, image_view_);
Tobin Ehlis8b26a382016-09-14 08:02:49 -06001095 if (iv_state) {
Tobin Ehlis15b8ea02016-09-19 14:02:58 -06001096 core_validation::AddCommandBufferBindingImageView(dev_data, cb_node, iv_state);
Tobin Ehlis81e46372016-08-17 13:33:44 -06001097 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06001098}
1099
Tobin Ehlis300888c2016-05-18 13:43:26 -06001100cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type)
1101 : storage_(false), dynamic_(false), buffer_(VK_NULL_HANDLE), offset_(0), range_(0) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001102 updated = false;
1103 descriptor_class = GeneralBuffer;
1104 if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) {
1105 dynamic_ = true;
1106 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type) {
1107 storage_ = true;
1108 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) {
1109 dynamic_ = true;
1110 storage_ = true;
1111 }
1112}
Tobin Ehlis300888c2016-05-18 13:43:26 -06001113void cvdescriptorset::BufferDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001114 updated = true;
Tobin Ehlis56a30942016-05-19 08:00:00 -06001115 const auto &buffer_info = update->pBufferInfo[index];
Tobin Ehlis300888c2016-05-18 13:43:26 -06001116 buffer_ = buffer_info.buffer;
1117 offset_ = buffer_info.offset;
1118 range_ = buffer_info.range;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001119}
1120
Tobin Ehlis300888c2016-05-18 13:43:26 -06001121void cvdescriptorset::BufferDescriptor::CopyUpdate(const Descriptor *src) {
1122 auto buff_desc = static_cast<const BufferDescriptor *>(src);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001123 updated = true;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001124 buffer_ = buff_desc->buffer_;
1125 offset_ = buff_desc->offset_;
1126 range_ = buff_desc->range_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001127}
1128
Tobin Ehlis58c884f2017-02-08 12:15:27 -07001129void cvdescriptorset::BufferDescriptor::BindCommandBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001130 auto buffer_node = GetBufferState(dev_data, buffer_);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001131 if (buffer_node) core_validation::AddCommandBufferBindingBuffer(dev_data, cb_node, buffer_node);
Tobin Ehlis8020eea2016-08-17 11:10:41 -06001132}
1133
Tobin Ehlis300888c2016-05-18 13:43:26 -06001134cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type) : buffer_view_(VK_NULL_HANDLE), storage_(false) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001135 updated = false;
1136 descriptor_class = TexelBuffer;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001137 if (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER == type) storage_ = true;
Petr Kraus13c98a62017-12-09 00:22:39 +01001138}
Tobin Ehlis56a30942016-05-19 08:00:00 -06001139
Tobin Ehlis300888c2016-05-18 13:43:26 -06001140void cvdescriptorset::TexelDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001141 updated = true;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001142 buffer_view_ = update->pTexelBufferView[index];
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001143}
1144
Tobin Ehlis300888c2016-05-18 13:43:26 -06001145void cvdescriptorset::TexelDescriptor::CopyUpdate(const Descriptor *src) {
1146 updated = true;
1147 buffer_view_ = static_cast<const TexelDescriptor *>(src)->buffer_view_;
1148}
Tobin Ehlis8020eea2016-08-17 11:10:41 -06001149
Tobin Ehlis58c884f2017-02-08 12:15:27 -07001150void cvdescriptorset::TexelDescriptor::BindCommandBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001151 auto bv_state = GetBufferViewState(dev_data, buffer_view_);
Tobin Ehlis8b872462016-09-14 08:12:08 -06001152 if (bv_state) {
Tobin Ehlis2515c0e2016-09-28 07:12:28 -06001153 core_validation::AddCommandBufferBindingBufferView(dev_data, cb_node, bv_state);
Tobin Ehlis81e46372016-08-17 13:33:44 -06001154 }
Tobin Ehlis8020eea2016-08-17 11:10:41 -06001155}
1156
Tobin Ehlis300888c2016-05-18 13:43:26 -06001157// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
1158// sets, and then calls their respective Validate[Write|Copy]Update functions.
1159// If the update hits an issue for which the callback returns "true", meaning that the call down the chain should
1160// be skipped, then true is returned.
1161// If there is no issue with the update, then false is returned.
Tobin Ehlis58c884f2017-02-08 12:15:27 -07001162bool cvdescriptorset::ValidateUpdateDescriptorSets(const debug_report_data *report_data, const layer_data *dev_data,
1163 uint32_t write_count, const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06001164 const VkCopyDescriptorSet *p_cds) {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001165 bool skip = false;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001166 // Validate Write updates
Tobin Ehlis56a30942016-05-19 08:00:00 -06001167 for (uint32_t i = 0; i < write_count; i++) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06001168 auto dest_set = p_wds[i].dstSet;
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001169 auto set_node = core_validation::GetSetNode(dev_data, dest_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06001170 if (!set_node) {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001171 skip |=
Tobin Ehlis300888c2016-05-18 13:43:26 -06001172 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
Petr Krausbc7f5442017-05-14 23:43:38 +02001173 HandleToUint64(dest_set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS",
Tobin Ehlis300888c2016-05-18 13:43:26 -06001174 "Cannot call vkUpdateDescriptorSets() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.",
Petr Krausbc7f5442017-05-14 23:43:38 +02001175 HandleToUint64(dest_set));
Tobin Ehlis300888c2016-05-18 13:43:26 -06001176 } else {
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001177 UNIQUE_VALIDATION_ERROR_CODE error_code;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001178 std::string error_str;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001179 if (!set_node->ValidateWriteUpdate(report_data, &p_wds[i], &error_code, &error_str)) {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001180 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
Petr Krausbc7f5442017-05-14 23:43:38 +02001181 HandleToUint64(dest_set), __LINE__, error_code, "DS",
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001182 "vkUpdateDescriptorsSets() failed write update validation for Descriptor Set 0x%" PRIx64
1183 " with error: %s. %s",
Petr Krausbc7f5442017-05-14 23:43:38 +02001184 HandleToUint64(dest_set), error_str.c_str(), validation_error_map[error_code]);
Tobin Ehlis300888c2016-05-18 13:43:26 -06001185 }
1186 }
1187 }
1188 // Now validate copy updates
Tobin Ehlis56a30942016-05-19 08:00:00 -06001189 for (uint32_t i = 0; i < copy_count; ++i) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06001190 auto dst_set = p_cds[i].dstSet;
1191 auto src_set = p_cds[i].srcSet;
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001192 auto src_node = core_validation::GetSetNode(dev_data, src_set);
1193 auto dst_node = core_validation::GetSetNode(dev_data, dst_set);
Tobin Ehlisa1712752017-01-04 09:41:47 -07001194 // Object_tracker verifies that src & dest descriptor set are valid
1195 assert(src_node);
1196 assert(dst_node);
1197 UNIQUE_VALIDATION_ERROR_CODE error_code;
1198 std::string error_str;
1199 if (!dst_node->ValidateCopyUpdate(report_data, &p_cds[i], src_node, &error_code, &error_str)) {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001200 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
Petr Krausbc7f5442017-05-14 23:43:38 +02001201 HandleToUint64(dst_set), __LINE__, error_code, "DS",
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001202 "vkUpdateDescriptorsSets() failed copy update from Descriptor Set 0x%" PRIx64
1203 " to Descriptor Set 0x%" PRIx64 " with error: %s. %s",
Petr Krausbc7f5442017-05-14 23:43:38 +02001204 HandleToUint64(src_set), HandleToUint64(dst_set), error_str.c_str(), validation_error_map[error_code]);
Tobin Ehlis300888c2016-05-18 13:43:26 -06001205 }
1206 }
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001207 return skip;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001208}
1209// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
1210// sets, and then calls their respective Perform[Write|Copy]Update functions.
1211// Prerequisite : ValidateUpdateDescriptorSets() should be called and return "false" prior to calling PerformUpdateDescriptorSets()
1212// with the same set of updates.
1213// This is split from the validate code to allow validation prior to calling down the chain, and then update after
1214// calling down the chain.
Tobin Ehlis58c884f2017-02-08 12:15:27 -07001215void cvdescriptorset::PerformUpdateDescriptorSets(const layer_data *dev_data, uint32_t write_count,
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06001216 const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
1217 const VkCopyDescriptorSet *p_cds) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06001218 // Write updates first
1219 uint32_t i = 0;
1220 for (i = 0; i < write_count; ++i) {
1221 auto dest_set = p_wds[i].dstSet;
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001222 auto set_node = core_validation::GetSetNode(dev_data, dest_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06001223 if (set_node) {
1224 set_node->PerformWriteUpdate(&p_wds[i]);
Tobin Ehlis300888c2016-05-18 13:43:26 -06001225 }
1226 }
1227 // Now copy updates
1228 for (i = 0; i < copy_count; ++i) {
1229 auto dst_set = p_cds[i].dstSet;
1230 auto src_set = p_cds[i].srcSet;
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001231 auto src_node = core_validation::GetSetNode(dev_data, src_set);
1232 auto dst_node = core_validation::GetSetNode(dev_data, dst_set);
Tobin Ehlis6a72dc72016-06-01 16:41:17 -06001233 if (src_node && dst_node) {
1234 dst_node->PerformCopyUpdate(&p_cds[i], src_node);
Tobin Ehlis300888c2016-05-18 13:43:26 -06001235 }
1236 }
1237}
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07001238// This helper function carries out the state updates for descriptor updates peformed via update templates. It basically collects
1239// data and leverages the PerformUpdateDescriptor helper functions to do this.
1240void cvdescriptorset::PerformUpdateDescriptorSetsWithTemplateKHR(layer_data *device_data, VkDescriptorSet descriptorSet,
1241 std::unique_ptr<TEMPLATE_STATE> const &template_state,
1242 const void *pData) {
1243 auto const &create_info = template_state->create_info;
1244
1245 // Create a vector of write structs
1246 std::vector<VkWriteDescriptorSet> desc_writes;
1247 auto layout_obj = GetDescriptorSetLayout(device_data, create_info.descriptorSetLayout);
1248
1249 // Create a WriteDescriptorSet struct for each template update entry
1250 for (uint32_t i = 0; i < create_info.descriptorUpdateEntryCount; i++) {
1251 auto binding_count = layout_obj->GetDescriptorCountFromBinding(create_info.pDescriptorUpdateEntries[i].dstBinding);
1252 auto binding_being_updated = create_info.pDescriptorUpdateEntries[i].dstBinding;
1253 auto dst_array_element = create_info.pDescriptorUpdateEntries[i].dstArrayElement;
1254
John Zulaufb6d71202017-12-22 16:47:09 -07001255 desc_writes.reserve(desc_writes.size() + create_info.pDescriptorUpdateEntries[i].descriptorCount);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07001256 for (uint32_t j = 0; j < create_info.pDescriptorUpdateEntries[i].descriptorCount; j++) {
1257 desc_writes.emplace_back();
1258 auto &write_entry = desc_writes.back();
1259
1260 size_t offset = create_info.pDescriptorUpdateEntries[i].offset + j * create_info.pDescriptorUpdateEntries[i].stride;
1261 char *update_entry = (char *)(pData) + offset;
1262
1263 if (dst_array_element >= binding_count) {
1264 dst_array_element = 0;
Mark Lobodzinski4aa479d2017-03-10 09:14:00 -07001265 binding_being_updated = layout_obj->GetNextValidBinding(binding_being_updated);
Mark Lobodzinski3d63a042017-03-09 16:24:13 -07001266 }
1267
1268 write_entry.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1269 write_entry.pNext = NULL;
1270 write_entry.dstSet = descriptorSet;
1271 write_entry.dstBinding = binding_being_updated;
1272 write_entry.dstArrayElement = dst_array_element;
1273 write_entry.descriptorCount = 1;
1274 write_entry.descriptorType = create_info.pDescriptorUpdateEntries[i].descriptorType;
1275
1276 switch (create_info.pDescriptorUpdateEntries[i].descriptorType) {
1277 case VK_DESCRIPTOR_TYPE_SAMPLER:
1278 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1279 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1280 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1281 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1282 write_entry.pImageInfo = reinterpret_cast<VkDescriptorImageInfo *>(update_entry);
1283 break;
1284
1285 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1286 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1287 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1288 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1289 write_entry.pBufferInfo = reinterpret_cast<VkDescriptorBufferInfo *>(update_entry);
1290 break;
1291
1292 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1293 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1294 write_entry.pTexelBufferView = reinterpret_cast<VkBufferView *>(update_entry);
1295 break;
1296 default:
1297 assert(0);
1298 break;
1299 }
1300 dst_array_element++;
1301 }
1302 }
1303 PerformUpdateDescriptorSets(device_data, static_cast<uint32_t>(desc_writes.size()), desc_writes.data(), 0, NULL);
1304}
Tobin Ehlis300888c2016-05-18 13:43:26 -06001305// Validate the state for a given write update but don't actually perform the update
1306// If an error would occur for this update, return false and fill in details in error_msg string
1307bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data *report_data, const VkWriteDescriptorSet *update,
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001308 UNIQUE_VALIDATION_ERROR_CODE *error_code, std::string *error_msg) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06001309 // Verify idle ds
1310 if (in_use.load()) {
Tobin Ehlis2cb8eb22017-01-03 14:09:57 -07001311 // TODO : Re-using Free Idle error code, need write update idle error code
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001312 *error_code = VALIDATION_ERROR_2860026a;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001313 std::stringstream error_str;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001314 error_str << "Cannot call vkUpdateDescriptorSets() to perform write update on descriptor set " << set_
Tobin Ehlis1d81edd2016-11-21 09:50:49 -07001315 << " that is in use by a command buffer";
Tobin Ehlis300888c2016-05-18 13:43:26 -06001316 *error_msg = error_str.str();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001317 return false;
1318 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06001319 // Verify dst binding exists
Tobin Ehlis7cd8c792017-06-20 08:30:39 -06001320 if (!p_layout_->HasBinding(update->dstBinding)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001321 *error_code = VALIDATION_ERROR_15c00276;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001322 std::stringstream error_str;
Tobin Ehlis1d81edd2016-11-21 09:50:49 -07001323 error_str << "DescriptorSet " << set_ << " does not have binding " << update->dstBinding;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001324 *error_msg = error_str.str();
1325 return false;
Tobin Ehlis59a5efc2016-11-21 09:41:57 -07001326 } else {
1327 // Make sure binding isn't empty
Tobin Ehlis7cd8c792017-06-20 08:30:39 -06001328 if (0 == p_layout_->GetDescriptorCountFromBinding(update->dstBinding)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001329 *error_code = VALIDATION_ERROR_15c00278;
Tobin Ehlis59a5efc2016-11-21 09:41:57 -07001330 std::stringstream error_str;
1331 error_str << "DescriptorSet " << set_ << " cannot updated binding " << update->dstBinding << " that has 0 descriptors";
1332 *error_msg = error_str.str();
1333 return false;
1334 }
Tobin Ehlis57ae28f2016-05-24 12:35:57 -06001335 }
1336 // We know that binding is valid, verify update and do update on each descriptor
John Zulaufc483f442017-12-15 14:02:06 -07001337 auto start_idx = p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
Tobin Ehlis7cd8c792017-06-20 08:30:39 -06001338 auto type = p_layout_->GetTypeFromBinding(update->dstBinding);
Tobin Ehlis57ae28f2016-05-24 12:35:57 -06001339 if (type != update->descriptorType) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001340 *error_code = VALIDATION_ERROR_15c0027e;
Tobin Ehlis57ae28f2016-05-24 12:35:57 -06001341 std::stringstream error_str;
1342 error_str << "Attempting write update to descriptor set " << set_ << " binding #" << update->dstBinding << " with type "
1343 << string_VkDescriptorType(type) << " but update type is " << string_VkDescriptorType(update->descriptorType);
1344 *error_msg = error_str.str();
1345 return false;
1346 }
Tobin Ehlis7b402352016-12-15 07:51:20 -07001347 if (update->descriptorCount > (descriptors_.size() - start_idx)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001348 *error_code = VALIDATION_ERROR_15c00282;
Tobin Ehlis57ae28f2016-05-24 12:35:57 -06001349 std::stringstream error_str;
1350 error_str << "Attempting write update to descriptor set " << set_ << " binding #" << update->dstBinding << " with "
Tobin Ehlis7b402352016-12-15 07:51:20 -07001351 << descriptors_.size() - start_idx
Tobin Ehlisf922ef82016-11-30 10:19:14 -07001352 << " descriptors in that binding and all successive bindings of the set, but update of "
1353 << update->descriptorCount << " descriptors combined with update array element offset of "
1354 << update->dstArrayElement << " oversteps the available number of consecutive descriptors";
Tobin Ehlis57ae28f2016-05-24 12:35:57 -06001355 *error_msg = error_str.str();
1356 return false;
1357 }
1358 // Verify consecutive bindings match (if needed)
Tobin Ehlis7cd8c792017-06-20 08:30:39 -06001359 if (!p_layout_->VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, "write update to",
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001360 set_, error_msg)) {
Tobin Ehlis48fbd692017-01-04 09:17:01 -07001361 // TODO : Should break out "consecutive binding updates" language into valid usage statements
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001362 *error_code = VALIDATION_ERROR_15c00282;
Tobin Ehlis57ae28f2016-05-24 12:35:57 -06001363 return false;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001364 }
Tobin Ehlis57ae28f2016-05-24 12:35:57 -06001365 // Update is within bounds and consistent so last step is to validate update contents
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001366 if (!VerifyWriteUpdateContents(update, start_idx, error_code, error_msg)) {
Tobin Ehlis57ae28f2016-05-24 12:35:57 -06001367 std::stringstream error_str;
1368 error_str << "Write update to descriptor in set " << set_ << " binding #" << update->dstBinding
1369 << " failed with error message: " << error_msg->c_str();
1370 *error_msg = error_str.str();
1371 return false;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001372 }
1373 // All checks passed, update is clean
Tobin Ehlis0a43bde2016-05-03 08:31:08 -06001374 return true;
Tobin Ehlis03d61de2016-05-17 08:31:46 -06001375}
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06001376// For the given buffer, verify that its creation parameters are appropriate for the given type
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001377// If there's an error, update the error_msg string with details and return false, else return true
Tobin Ehlis4668dce2016-11-16 09:30:23 -07001378bool cvdescriptorset::DescriptorSet::ValidateBufferUsage(BUFFER_STATE const *buffer_node, VkDescriptorType type,
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001379 UNIQUE_VALIDATION_ERROR_CODE *error_code, std::string *error_msg) const {
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06001380 // Verify that usage bits set correctly for given type
Tobin Ehlis94bc5d22016-06-02 07:46:52 -06001381 auto usage = buffer_node->createInfo.usage;
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06001382 std::string error_usage_bit;
1383 switch (type) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001384 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1385 if (!(usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001386 *error_code = VALIDATION_ERROR_15c0029c;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001387 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT";
1388 }
1389 break;
1390 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1391 if (!(usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001392 *error_code = VALIDATION_ERROR_15c0029e;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001393 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT";
1394 }
1395 break;
1396 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1397 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1398 if (!(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001399 *error_code = VALIDATION_ERROR_15c00292;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001400 error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT";
1401 }
1402 break;
1403 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1404 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1405 if (!(usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001406 *error_code = VALIDATION_ERROR_15c00296;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001407 error_usage_bit = "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT";
1408 }
1409 break;
1410 default:
1411 break;
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06001412 }
1413 if (!error_usage_bit.empty()) {
1414 std::stringstream error_str;
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001415 error_str << "Buffer (" << buffer_node->buffer << ") with usage mask 0x" << usage
1416 << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have "
1417 << error_usage_bit << " set.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001418 *error_msg = error_str.str();
Tobin Ehlis6bd2b982016-05-24 12:33:42 -06001419 return false;
1420 }
1421 return true;
1422}
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001423// For buffer descriptor updates, verify the buffer usage and VkDescriptorBufferInfo struct which includes:
1424// 1. buffer is valid
1425// 2. buffer was created with correct usage flags
1426// 3. offset is less than buffer size
1427// 4. range is either VK_WHOLE_SIZE or falls in (0, (buffer size - offset)]
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07001428// 5. range and offset are within the device's limits
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001429// If there's an error, update the error_msg string with details and return false, else return true
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001430bool cvdescriptorset::DescriptorSet::ValidateBufferUpdate(VkDescriptorBufferInfo const *buffer_info, VkDescriptorType type,
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001431 UNIQUE_VALIDATION_ERROR_CODE *error_code, std::string *error_msg) const {
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001432 // First make sure that buffer is valid
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001433 auto buffer_node = GetBufferState(device_data_, buffer_info->buffer);
Tobin Ehlisfa8b6182016-12-22 13:40:45 -07001434 // Any invalid buffer should already be caught by object_tracker
1435 assert(buffer_node);
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001436 if (ValidateMemoryIsBoundToBuffer(device_data_, buffer_node, "vkUpdateDescriptorSets()", VALIDATION_ERROR_15c00294)) {
1437 *error_code = VALIDATION_ERROR_15c00294;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001438 *error_msg = "No memory bound to buffer.";
Tobin Ehlis81280962016-07-20 14:04:20 -06001439 return false;
Tobin Ehlisfed999f2016-09-21 15:09:45 -06001440 }
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001441 // Verify usage bits
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001442 if (!ValidateBufferUsage(buffer_node, type, error_code, error_msg)) {
1443 // error_msg will have been updated by ValidateBufferUsage()
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001444 return false;
1445 }
1446 // offset must be less than buffer size
Jeremy Hayesd1a6a822017-03-09 14:39:45 -07001447 if (buffer_info->offset >= buffer_node->createInfo.size) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001448 *error_code = VALIDATION_ERROR_044002a8;
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001449 std::stringstream error_str;
Jeremy Hayesd1a6a822017-03-09 14:39:45 -07001450 error_str << "VkDescriptorBufferInfo offset of " << buffer_info->offset << " is greater than or equal to buffer "
1451 << buffer_node->buffer << " size of " << buffer_node->createInfo.size;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001452 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001453 return false;
1454 }
1455 if (buffer_info->range != VK_WHOLE_SIZE) {
1456 // Range must be VK_WHOLE_SIZE or > 0
1457 if (!buffer_info->range) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001458 *error_code = VALIDATION_ERROR_044002aa;
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001459 std::stringstream error_str;
1460 error_str << "VkDescriptorBufferInfo range is not VK_WHOLE_SIZE and is zero, which is not allowed.";
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001461 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001462 return false;
1463 }
1464 // Range must be VK_WHOLE_SIZE or <= (buffer size - offset)
1465 if (buffer_info->range > (buffer_node->createInfo.size - buffer_info->offset)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001466 *error_code = VALIDATION_ERROR_044002ac;
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001467 std::stringstream error_str;
1468 error_str << "VkDescriptorBufferInfo range is " << buffer_info->range << " which is greater than buffer size ("
1469 << buffer_node->createInfo.size << ") minus requested offset of " << buffer_info->offset;
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001470 *error_msg = error_str.str();
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001471 return false;
1472 }
1473 }
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07001474 // Check buffer update sizes against device limits
1475 if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == type || VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) {
1476 auto max_ub_range = limits_.maxUniformBufferRange;
1477 // TODO : If range is WHOLE_SIZE, need to make sure underlying buffer size doesn't exceed device max
1478 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_ub_range) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001479 *error_code = VALIDATION_ERROR_15c00298;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07001480 std::stringstream error_str;
1481 error_str << "VkDescriptorBufferInfo range is " << buffer_info->range
1482 << " which is greater than this device's maxUniformBufferRange (" << max_ub_range << ")";
1483 *error_msg = error_str.str();
1484 return false;
1485 }
1486 } else if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == type || VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == type) {
1487 auto max_sb_range = limits_.maxStorageBufferRange;
1488 // TODO : If range is WHOLE_SIZE, need to make sure underlying buffer size doesn't exceed device max
1489 if (buffer_info->range != VK_WHOLE_SIZE && buffer_info->range > max_sb_range) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001490 *error_code = VALIDATION_ERROR_15c0029a;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -07001491 std::stringstream error_str;
1492 error_str << "VkDescriptorBufferInfo range is " << buffer_info->range
1493 << " which is greater than this device's maxStorageBufferRange (" << max_sb_range << ")";
1494 *error_msg = error_str.str();
1495 return false;
1496 }
1497 }
Tobin Ehlis3d38f082016-07-01 17:36:48 -06001498 return true;
1499}
1500
Tobin Ehlis300888c2016-05-18 13:43:26 -06001501// Verify that the contents of the update are ok, but don't perform actual update
1502bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDescriptorSet *update, const uint32_t index,
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001503 UNIQUE_VALIDATION_ERROR_CODE *error_code,
1504 std::string *error_msg) const {
Tobin Ehlis300888c2016-05-18 13:43:26 -06001505 switch (update->descriptorType) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001506 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
1507 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1508 // Validate image
1509 auto image_view = update->pImageInfo[di].imageView;
1510 auto image_layout = update->pImageInfo[di].imageLayout;
1511 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, error_code, error_msg)) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06001512 std::stringstream error_str;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001513 error_str << "Attempted write update to combined image sampler descriptor failed due to: "
1514 << error_msg->c_str();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001515 *error_msg = error_str.str();
Tobin Ehlis300888c2016-05-18 13:43:26 -06001516 return false;
1517 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06001518 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001519 // Intentional fall-through to validate sampler
Tobin Ehlis300888c2016-05-18 13:43:26 -06001520 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001521 case VK_DESCRIPTOR_TYPE_SAMPLER: {
1522 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1523 if (!descriptors_[index + di].get()->IsImmutableSampler()) {
1524 if (!ValidateSampler(update->pImageInfo[di].sampler, device_data_)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001525 *error_code = VALIDATION_ERROR_15c0028a;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001526 std::stringstream error_str;
1527 error_str << "Attempted write update to sampler descriptor with invalid sampler: "
1528 << update->pImageInfo[di].sampler << ".";
1529 *error_msg = error_str.str();
1530 return false;
1531 }
1532 } else {
1533 // TODO : Warn here
1534 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06001535 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001536 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001537 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001538 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1539 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1540 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
1541 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1542 auto image_view = update->pImageInfo[di].imageView;
1543 auto image_layout = update->pImageInfo[di].imageLayout;
1544 if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, error_code, error_msg)) {
1545 std::stringstream error_str;
1546 error_str << "Attempted write update to image descriptor failed due to: " << error_msg->c_str();
1547 *error_msg = error_str.str();
1548 return false;
1549 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06001550 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001551 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001552 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001553 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1554 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
1555 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1556 auto buffer_view = update->pTexelBufferView[di];
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001557 auto bv_state = GetBufferViewState(device_data_, buffer_view);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001558 if (!bv_state) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001559 *error_code = VALIDATION_ERROR_15c00286;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001560 std::stringstream error_str;
1561 error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: " << buffer_view;
1562 *error_msg = error_str.str();
1563 return false;
1564 }
1565 auto buffer = bv_state->create_info.buffer;
Tobin Ehlisdf0d62a2017-10-11 08:48:00 -06001566 auto buffer_state = GetBufferState(device_data_, buffer);
1567 // Verify that buffer underlying the view hasn't been destroyed prematurely
1568 if (!buffer_state) {
1569 *error_code = VALIDATION_ERROR_15c00286;
1570 std::stringstream error_str;
1571 error_str << "Attempted write update to texel buffer descriptor failed because underlying buffer (" << buffer
1572 << ") has been destroyed: " << error_msg->c_str();
1573 *error_msg = error_str.str();
1574 return false;
1575 } else if (!ValidateBufferUsage(buffer_state, update->descriptorType, error_code, error_msg)) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001576 std::stringstream error_str;
1577 error_str << "Attempted write update to texel buffer descriptor failed due to: " << error_msg->c_str();
1578 *error_msg = error_str.str();
1579 return false;
1580 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06001581 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001582 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001583 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001584 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1585 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1586 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1587 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
1588 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
1589 if (!ValidateBufferUpdate(update->pBufferInfo + di, update->descriptorType, error_code, error_msg)) {
1590 std::stringstream error_str;
1591 error_str << "Attempted write update to buffer descriptor failed due to: " << error_msg->c_str();
1592 *error_msg = error_str.str();
1593 return false;
1594 }
1595 }
1596 break;
1597 }
1598 default:
1599 assert(0); // We've already verified update type so should never get here
1600 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001601 }
1602 // All checks passed so update contents are good
1603 return true;
1604}
1605// Verify that the contents of the update are ok, but don't perform actual update
1606bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescriptorSet *update, const DescriptorSet *src_set,
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001607 VkDescriptorType type, uint32_t index,
1608 UNIQUE_VALIDATION_ERROR_CODE *error_code,
1609 std::string *error_msg) const {
1610 // Note : Repurposing some Write update error codes here as specific details aren't called out for copy updates like they are
1611 // for write updates
Tobin Ehlis300888c2016-05-18 13:43:26 -06001612 switch (src_set->descriptors_[index]->descriptor_class) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001613 case PlainSampler: {
1614 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Józef Kucia5297e372017-10-13 22:31:34 +02001615 const auto src_desc = src_set->descriptors_[index + di].get();
1616 if (!src_desc->updated) continue;
1617 if (!src_desc->IsImmutableSampler()) {
1618 auto update_sampler = static_cast<SamplerDescriptor *>(src_desc)->GetSampler();
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001619 if (!ValidateSampler(update_sampler, device_data_)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001620 *error_code = VALIDATION_ERROR_15c0028a;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001621 std::stringstream error_str;
1622 error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << ".";
1623 *error_msg = error_str.str();
1624 return false;
1625 }
1626 } else {
1627 // TODO : Warn here
1628 }
1629 }
1630 break;
1631 }
1632 case ImageSampler: {
1633 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Józef Kucia5297e372017-10-13 22:31:34 +02001634 const auto src_desc = src_set->descriptors_[index + di].get();
1635 if (!src_desc->updated) continue;
1636 auto img_samp_desc = static_cast<const ImageSamplerDescriptor *>(src_desc);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001637 // First validate sampler
1638 if (!img_samp_desc->IsImmutableSampler()) {
1639 auto update_sampler = img_samp_desc->GetSampler();
1640 if (!ValidateSampler(update_sampler, device_data_)) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001641 *error_code = VALIDATION_ERROR_15c0028a;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001642 std::stringstream error_str;
1643 error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << ".";
1644 *error_msg = error_str.str();
1645 return false;
1646 }
1647 } else {
1648 // TODO : Warn here
1649 }
1650 // Validate image
1651 auto image_view = img_samp_desc->GetImageView();
1652 auto image_layout = img_samp_desc->GetImageLayout();
1653 if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, error_code, error_msg)) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06001654 std::stringstream error_str;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001655 error_str << "Attempted copy update to combined image sampler descriptor failed due to: " << error_msg->c_str();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001656 *error_msg = error_str.str();
Tobin Ehlis300888c2016-05-18 13:43:26 -06001657 return false;
1658 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06001659 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001660 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001661 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001662 case Image: {
1663 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Józef Kucia5297e372017-10-13 22:31:34 +02001664 const auto src_desc = src_set->descriptors_[index + di].get();
1665 if (!src_desc->updated) continue;
1666 auto img_desc = static_cast<const ImageDescriptor *>(src_desc);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001667 auto image_view = img_desc->GetImageView();
1668 auto image_layout = img_desc->GetImageLayout();
1669 if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, error_code, error_msg)) {
Tobin Ehlis300888c2016-05-18 13:43:26 -06001670 std::stringstream error_str;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001671 error_str << "Attempted copy update to image descriptor failed due to: " << error_msg->c_str();
Tobin Ehlis75f04ec2016-10-06 17:43:11 -06001672 *error_msg = error_str.str();
Tobin Ehlis300888c2016-05-18 13:43:26 -06001673 return false;
1674 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06001675 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001676 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001677 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001678 case TexelBuffer: {
1679 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Józef Kucia5297e372017-10-13 22:31:34 +02001680 const auto src_desc = src_set->descriptors_[index + di].get();
1681 if (!src_desc->updated) continue;
1682 auto buffer_view = static_cast<TexelDescriptor *>(src_desc)->GetBufferView();
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001683 auto bv_state = GetBufferViewState(device_data_, buffer_view);
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001684 if (!bv_state) {
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001685 *error_code = VALIDATION_ERROR_15c00286;
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001686 std::stringstream error_str;
1687 error_str << "Attempted copy update to texel buffer descriptor with invalid buffer view: " << buffer_view;
1688 *error_msg = error_str.str();
1689 return false;
1690 }
1691 auto buffer = bv_state->create_info.buffer;
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001692 if (!ValidateBufferUsage(GetBufferState(device_data_, buffer), type, error_code, error_msg)) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001693 std::stringstream error_str;
1694 error_str << "Attempted copy update to texel buffer descriptor failed due to: " << error_msg->c_str();
1695 *error_msg = error_str.str();
1696 return false;
1697 }
Tobin Ehlis300888c2016-05-18 13:43:26 -06001698 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001699 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001700 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001701 case GeneralBuffer: {
1702 for (uint32_t di = 0; di < update->descriptorCount; ++di) {
Józef Kucia5297e372017-10-13 22:31:34 +02001703 const auto src_desc = src_set->descriptors_[index + di].get();
1704 if (!src_desc->updated) continue;
1705 auto buffer = static_cast<BufferDescriptor *>(src_desc)->GetBuffer();
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001706 if (!ValidateBufferUsage(GetBufferState(device_data_, buffer), type, error_code, error_msg)) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001707 std::stringstream error_str;
1708 error_str << "Attempted copy update to buffer descriptor failed due to: " << error_msg->c_str();
1709 *error_msg = error_str.str();
1710 return false;
1711 }
Tobin Ehliscbcf2342016-05-24 13:07:12 -06001712 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001713 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001714 }
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001715 default:
1716 assert(0); // We've already verified update type so should never get here
1717 break;
Tobin Ehlis300888c2016-05-18 13:43:26 -06001718 }
1719 // All checks passed so update contents are good
1720 return true;
Chris Forbesb4e0bdb2016-05-31 16:34:40 +12001721}
Tobin Ehlisf320b192017-03-14 11:22:50 -06001722// Update the common AllocateDescriptorSetsData
1723void cvdescriptorset::UpdateAllocateDescriptorSetsData(const layer_data *dev_data, const VkDescriptorSetAllocateInfo *p_alloc_info,
1724 AllocateDescriptorSetsData *ds_data) {
1725 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
1726 auto layout = GetDescriptorSetLayout(dev_data, p_alloc_info->pSetLayouts[i]);
1727 if (layout) {
1728 ds_data->layout_nodes[i] = layout;
1729 // Count total descriptors required per type
1730 for (uint32_t j = 0; j < layout->GetBindingCount(); ++j) {
1731 const auto &binding_layout = layout->GetDescriptorSetLayoutBindingPtrFromIndex(j);
1732 uint32_t typeIndex = static_cast<uint32_t>(binding_layout->descriptorType);
1733 ds_data->required_descriptors_by_type[typeIndex] += binding_layout->descriptorCount;
1734 }
1735 }
1736 // Any unknown layouts will be flagged as errors during ValidateAllocateDescriptorSets() call
1737 }
Petr Kraus13c98a62017-12-09 00:22:39 +01001738}
Tobin Ehlisee471462016-05-26 11:21:59 -06001739// Verify that the state at allocate time is correct, but don't actually allocate the sets yet
Tobin Ehlisf320b192017-03-14 11:22:50 -06001740bool cvdescriptorset::ValidateAllocateDescriptorSets(const core_validation::layer_data *dev_data,
1741 const VkDescriptorSetAllocateInfo *p_alloc_info,
1742 const AllocateDescriptorSetsData *ds_data) {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001743 bool skip = false;
Tobin Ehlisf320b192017-03-14 11:22:50 -06001744 auto report_data = core_validation::GetReportData(dev_data);
Tobin Ehlisee471462016-05-26 11:21:59 -06001745
1746 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
Tobin Ehlisb2e1e2c2017-02-08 09:16:32 -07001747 auto layout = GetDescriptorSetLayout(dev_data, p_alloc_info->pSetLayouts[i]);
Tobin Ehlis815e8132016-06-02 13:02:17 -06001748 if (!layout) {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001749 skip |=
Tobin Ehlisee471462016-05-26 11:21:59 -06001750 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
Petr Krausbc7f5442017-05-14 23:43:38 +02001751 HandleToUint64(p_alloc_info->pSetLayouts[i]), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
Tobin Ehlisee471462016-05-26 11:21:59 -06001752 "Unable to find set layout node for layout 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call",
Petr Krausbc7f5442017-05-14 23:43:38 +02001753 HandleToUint64(p_alloc_info->pSetLayouts[i]));
Tobin Ehlisee471462016-05-26 11:21:59 -06001754 }
1755 }
Mark Lobodzinski28426ae2017-06-01 07:56:38 -06001756 if (!GetDeviceExtensions(dev_data)->vk_khr_maintenance1) {
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06001757 auto pool_state = GetDescriptorPoolState(dev_data, p_alloc_info->descriptorPool);
1758 // Track number of descriptorSets allowable in this pool
1759 if (pool_state->availableSets < p_alloc_info->descriptorSetCount) {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001760 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001761 HandleToUint64(pool_state->pool), __LINE__, VALIDATION_ERROR_04c00264, "DS",
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001762 "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64
1763 ". This pool only has %d descriptorSets remaining. %s",
Petr Krausbc7f5442017-05-14 23:43:38 +02001764 p_alloc_info->descriptorSetCount, HandleToUint64(pool_state->pool), pool_state->availableSets,
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001765 validation_error_map[VALIDATION_ERROR_04c00264]);
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06001766 }
1767 // Determine whether descriptor counts are satisfiable
1768 for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) {
1769 if (ds_data->required_descriptors_by_type[i] > pool_state->availableDescriptorTypeCount[i]) {
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001770 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001771 HandleToUint64(pool_state->pool), __LINE__, VALIDATION_ERROR_04c00266, "DS",
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001772 "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64
1773 ". This pool only has %d descriptors of this type remaining. %s",
1774 ds_data->required_descriptors_by_type[i], string_VkDescriptorType(VkDescriptorType(i)),
Petr Krausbc7f5442017-05-14 23:43:38 +02001775 HandleToUint64(pool_state->pool), pool_state->availableDescriptorTypeCount[i],
Tobin Ehlis3c37fb32017-05-24 09:31:13 -06001776 validation_error_map[VALIDATION_ERROR_04c00266]);
Mike Schuchardt64b5bb72017-03-21 16:33:26 -06001777 }
Tobin Ehlisee471462016-05-26 11:21:59 -06001778 }
1779 }
Tobin Ehlis5d749ea2016-07-18 13:14:01 -06001780
Mark Lobodzinskibdc3b022017-04-24 09:11:35 -06001781 return skip;
Tobin Ehlisee471462016-05-26 11:21:59 -06001782}
1783// Decrement allocated sets from the pool and insert new sets into set_map
Tobin Ehlis4e380592016-06-02 12:41:47 -06001784void cvdescriptorset::PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *p_alloc_info,
1785 const VkDescriptorSet *descriptor_sets,
1786 const AllocateDescriptorSetsData *ds_data,
Tobin Ehlisbd711bd2016-10-12 14:27:30 -06001787 std::unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_STATE *> *pool_map,
Tobin Ehlis4e380592016-06-02 12:41:47 -06001788 std::unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> *set_map,
John Zulauf48a6a702017-12-22 17:14:54 -07001789 layer_data *dev_data) {
Tobin Ehlisee471462016-05-26 11:21:59 -06001790 auto pool_state = (*pool_map)[p_alloc_info->descriptorPool];
Mark Lobodzinskic9430182017-06-13 13:00:05 -06001791 // Account for sets and individual descriptors allocated from pool
Tobin Ehlisee471462016-05-26 11:21:59 -06001792 pool_state->availableSets -= p_alloc_info->descriptorSetCount;
Tobin Ehlis68d0adf2016-06-01 11:33:50 -06001793 for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) {
1794 pool_state->availableDescriptorTypeCount[i] -= ds_data->required_descriptors_by_type[i];
1795 }
Mark Lobodzinskic9430182017-06-13 13:00:05 -06001796 // Create tracking object for each descriptor set; insert into global map and the pool's set.
Tobin Ehlisee471462016-05-26 11:21:59 -06001797 for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
Tobin Ehlis93f22372016-10-12 14:34:12 -06001798 auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], p_alloc_info->descriptorPool, ds_data->layout_nodes[i],
1799 dev_data);
Tobin Ehlisee471462016-05-26 11:21:59 -06001800
1801 pool_state->sets.insert(new_ds);
1802 new_ds->in_use.store(0);
1803 (*set_map)[descriptor_sets[i]] = new_ds;
1804 }
1805}
John Zulauf48a6a702017-12-22 17:14:54 -07001806
1807cvdescriptorset::PrefilterBindRequestMap::PrefilterBindRequestMap(cvdescriptorset::DescriptorSet &ds, const BindingReqMap &in_map,
1808 GLOBAL_CB_NODE *cb_state)
1809 : filtered_map_(), orig_map_(in_map) {
1810 if (ds.GetTotalDescriptorCount() > kManyDescriptors_) {
1811 filtered_map_.reset(new std::map<uint32_t, descriptor_req>());
1812 ds.FilterAndTrackBindingReqs(cb_state, orig_map_, filtered_map_.get());
1813 }
1814}
1815cvdescriptorset::PrefilterBindRequestMap::PrefilterBindRequestMap(cvdescriptorset::DescriptorSet &ds, const BindingReqMap &in_map,
1816 GLOBAL_CB_NODE *cb_state, PIPELINE_STATE *pipeline)
1817 : filtered_map_(), orig_map_(in_map) {
1818 if (ds.GetTotalDescriptorCount() > kManyDescriptors_) {
1819 filtered_map_.reset(new std::map<uint32_t, descriptor_req>());
1820 ds.FilterAndTrackBindingReqs(cb_state, pipeline, orig_map_, filtered_map_.get());
1821 }
1822}