blob: 1562a6d1710af5d22be15e2fc023372a25c91e8e [file] [log] [blame]
Jeremy Hayese4224ee2019-01-04 14:41:48 -07001/* Copyright (c) 2015-2019 The Khronos Group Inc.
2 * Copyright (c) 2015-2019 Valve Corporation
3 * Copyright (c) 2015-2019 LunarG, Inc.
4 * Copyright (C) 2015-2019 Google Inc.
Tobin Ehlis2d9deec2016-04-21 14:19:26 -06005 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Tobin Ehlis <tobine@google.com>
John Zulaufc483f442017-12-15 14:02:06 -070019 * John Zulauf <jzulauf@lunarg.com>
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060020 */
21#ifndef CORE_VALIDATION_DESCRIPTOR_SETS_H_
22#define CORE_VALIDATION_DESCRIPTOR_SETS_H_
23
John Zulaufd47d0612018-02-16 13:00:34 -070024#include "hash_vk_types.h"
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060025#include "vk_layer_logging.h"
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060026#include "vk_layer_utils.h"
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060027#include "vk_safe_struct.h"
28#include "vulkan/vk_layer.h"
Mark Lobodzinski33826372017-04-13 11:10:11 -060029#include "vk_object_types.h"
Tobin Ehliscebc4c02016-08-22 10:10:43 -060030#include <map>
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060031#include <memory>
John Zulaufb6d71202017-12-22 16:47:09 -070032#include <set>
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060033#include <unordered_map>
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060034#include <unordered_set>
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060035#include <vector>
36
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -070037class CoreChecks;
Tobin Ehlis58c884f2017-02-08 12:15:27 -070038
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060039// Descriptor Data structures
John Zulaufc483f442017-12-15 14:02:06 -070040namespace cvdescriptorset {
41
John Zulauf48a6a702017-12-22 17:14:54 -070042// Utility structs/classes/types
John Zulaufc483f442017-12-15 14:02:06 -070043// Index range for global indices below, end is exclusive, i.e. [start,end)
44struct IndexRange {
45 IndexRange(uint32_t start_in, uint32_t end_in) : start(start_in), end(end_in) {}
46 IndexRange() = default;
47 uint32_t start;
48 uint32_t end;
49};
John Zulauf48a6a702017-12-22 17:14:54 -070050typedef std::map<uint32_t, descriptor_req> BindingReqMap;
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060051
52/*
John Zulauf34ebf272018-02-16 13:08:47 -070053 * DescriptorSetLayoutDef/DescriptorSetLayout classes
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060054 *
John Zulauf34ebf272018-02-16 13:08:47 -070055 * Overview - These two classes encapsulate the Vulkan VkDescriptorSetLayout data (layout).
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060056 * A layout consists of some number of bindings, each of which has a binding#, a
57 * type, descriptor count, stage flags, and pImmutableSamplers.
John Zulauf34ebf272018-02-16 13:08:47 -070058
59 * The DescriptorSetLayoutDef represents a canonicalization of the input data and contains
60 * neither per handle or per device state. It is possible for different handles on
61 * different devices to share a common def. This is used and useful for quick compatibiltiy
62 * validation. The DescriptorSetLayout refers to a DescriptorSetLayoutDef and contains
63 * all per handle state.
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060064 *
65 * Index vs Binding - A layout is created with an array of VkDescriptorSetLayoutBinding
66 * where each array index will have a corresponding binding# that is defined in that struct.
Tobin Ehlis9637fb22016-12-12 15:59:34 -070067 * The binding#, then, is decoupled from VkDescriptorSetLayoutBinding index, which allows
68 * bindings to be defined out-of-order. This DescriptorSetLayout class, however, stores
69 * the bindings internally in-order. This is useful for operations which may "roll over"
70 * from a single binding to the next consecutive binding.
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060071 *
Tobin Ehlis9637fb22016-12-12 15:59:34 -070072 * Note that although the bindings are stored in-order, there still may be "gaps" in the
73 * binding#. For example, if the binding creation order is 8, 7, 10, 3, 4, then the
74 * internal binding array will have five entries stored in binding order 3, 4, 7, 8, 10.
75 * To process all of the bindings in a layout you can iterate from 0 to GetBindingCount()
76 * and use the Get*FromIndex() functions for each index. To just process a single binding,
77 * use the Get*FromBinding() functions.
78 *
79 * Global Index - The binding vector index has as many indices as there are bindings.
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060080 * This class also has the concept of a Global Index. For the global index functions,
81 * there are as many global indices as there are descriptors in the layout.
82 * For the global index, consider all of the bindings to be a flat array where
Tobin Ehlis9637fb22016-12-12 15:59:34 -070083 * descriptor 0 of of the lowest binding# is index 0 and each descriptor in the layout
84 * increments from there. So if the lowest binding# in this example had descriptorCount of
85 * 10, then the GlobalStartIndex of the 2nd lowest binding# will be 10 where 0-9 are the
86 * global indices for the lowest binding#.
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060087 */
John Zulauf1f8174b2018-02-16 12:58:37 -070088class DescriptorSetLayoutDef {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -070089 public:
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060090 // Constructors and destructor
John Zulauf1f8174b2018-02-16 12:58:37 -070091 DescriptorSetLayoutDef(const VkDescriptorSetLayoutCreateInfo *p_create_info);
92 size_t hash() const;
93
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060094 uint32_t GetTotalDescriptorCount() const { return descriptor_count_; };
95 uint32_t GetDynamicDescriptorCount() const { return dynamic_descriptor_count_; };
Józef Kucia1bb00972017-09-10 11:24:08 +020096 VkDescriptorSetLayoutCreateFlags GetCreateFlags() const { return flags_; }
Tobin Ehlisf922ef82016-11-30 10:19:14 -070097 // For a given binding, return the number of descriptors in that binding and all successive bindings
Tobin Ehlis0a43bde2016-05-03 08:31:08 -060098 uint32_t GetBindingCount() const { return binding_count_; };
John Zulaufb6d71202017-12-22 16:47:09 -070099 // Non-empty binding numbers in order
100 const std::set<uint32_t> &GetSortedBindingSet() const { return non_empty_bindings_; }
Tobin Ehlis2d9deec2016-04-21 14:19:26 -0600101 // Return true if given binding is present in this layout
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600102 bool HasBinding(const uint32_t binding) const { return binding_to_index_map_.count(binding) > 0; };
John Zulaufdf3c5c12018-03-06 16:44:43 -0700103 // Return true if this DSL Def (referenced by the 1st layout) is compatible with another DSL Def (ref'd from the 2nd layout)
104 // else return false and update error_msg with description of incompatibility
John Zulauf1f8174b2018-02-16 12:58:37 -0700105 bool IsCompatible(VkDescriptorSetLayout, VkDescriptorSetLayout, DescriptorSetLayoutDef const *const, std::string *) const;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600106 // Return true if binding 1 beyond given exists and has same type, stageFlags & immutable sampler use
107 bool IsNextBindingConsistent(const uint32_t) const;
John Zulaufb6d71202017-12-22 16:47:09 -0700108 uint32_t GetIndexFromBinding(uint32_t binding) const;
Tobin Ehlis2d9deec2016-04-21 14:19:26 -0600109 // Various Get functions that can either be passed a binding#, which will
Tobin Ehlis9637fb22016-12-12 15:59:34 -0700110 // be automatically translated into the appropriate index, or the index# can be passed in directly
John Zulaufb6d71202017-12-22 16:47:09 -0700111 uint32_t GetMaxBinding() const { return bindings_[bindings_.size() - 1].binding; }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600112 VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromIndex(const uint32_t) const;
John Zulaufb6d71202017-12-22 16:47:09 -0700113 VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromBinding(uint32_t binding) const {
114 return GetDescriptorSetLayoutBindingPtrFromIndex(GetIndexFromBinding(binding));
115 }
John Zulauf1f8174b2018-02-16 12:58:37 -0700116 const std::vector<safe_VkDescriptorSetLayoutBinding> &GetBindings() const { return bindings_; }
John Zulauf223b69d2018-11-09 16:00:59 -0700117 const std::vector<VkDescriptorBindingFlagsEXT> &GetBindingFlags() const { return binding_flags_; }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600118 uint32_t GetDescriptorCountFromIndex(const uint32_t) const;
John Zulaufb6d71202017-12-22 16:47:09 -0700119 uint32_t GetDescriptorCountFromBinding(const uint32_t binding) const {
120 return GetDescriptorCountFromIndex(GetIndexFromBinding(binding));
121 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600122 VkDescriptorType GetTypeFromIndex(const uint32_t) const;
John Zulaufb6d71202017-12-22 16:47:09 -0700123 VkDescriptorType GetTypeFromBinding(const uint32_t binding) const { return GetTypeFromIndex(GetIndexFromBinding(binding)); }
124 VkShaderStageFlags GetStageFlagsFromIndex(const uint32_t) const;
125 VkShaderStageFlags GetStageFlagsFromBinding(const uint32_t binding) const {
126 return GetStageFlagsFromIndex(GetIndexFromBinding(binding));
127 }
Jeff Bolzfdf96072018-04-10 14:32:18 -0500128 VkDescriptorBindingFlagsEXT GetDescriptorBindingFlagsFromIndex(const uint32_t) const;
129 VkDescriptorBindingFlagsEXT GetDescriptorBindingFlagsFromBinding(const uint32_t binding) const {
130 return GetDescriptorBindingFlagsFromIndex(GetIndexFromBinding(binding));
131 }
John Zulaufb6d71202017-12-22 16:47:09 -0700132 uint32_t GetIndexFromGlobalIndex(const uint32_t global_index) const;
133 VkDescriptorType GetTypeFromGlobalIndex(const uint32_t global_index) const {
134 return GetTypeFromIndex(GetIndexFromGlobalIndex(global_index));
135 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600136 VkSampler const *GetImmutableSamplerPtrFromBinding(const uint32_t) const;
137 VkSampler const *GetImmutableSamplerPtrFromIndex(const uint32_t) const;
Tobin Ehlisa3525e02016-11-17 10:50:52 -0700138 // For a given binding and array index, return the corresponding index into the dynamic offset array
139 int32_t GetDynamicOffsetIndexFromBinding(uint32_t binding) const {
140 auto dyn_off = binding_to_dynamic_array_idx_map_.find(binding);
141 if (dyn_off == binding_to_dynamic_array_idx_map_.end()) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700142 assert(0); // Requesting dyn offset for invalid binding/array idx pair
Tobin Ehlisa3525e02016-11-17 10:50:52 -0700143 return -1;
144 }
145 return dyn_off->second;
146 }
John Zulaufc483f442017-12-15 14:02:06 -0700147 // For a particular binding, get the global index range
148 // This call should be guarded by a call to "HasBinding(binding)" to verify that the given binding exists
149 const IndexRange &GetGlobalIndexRangeFromBinding(const uint32_t) const;
150
Mark Lobodzinski4aa479d2017-03-10 09:14:00 -0700151 // Helper function to get the next valid binding for a descriptor
152 uint32_t GetNextValidBinding(const uint32_t) const;
Tobin Ehlis1f946f82016-05-05 12:03:44 -0600153 // For a particular binding starting at offset and having update_count descriptors
154 // updated, verify that for any binding boundaries crossed, the update is consistent
155 bool VerifyUpdateConsistency(uint32_t, uint32_t, uint32_t, const char *, const VkDescriptorSet, std::string *) const;
Józef Kuciaf0c94d42017-10-25 22:15:22 +0200156 bool IsPushDescriptor() const { return GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; };
Tobin Ehlis2d9deec2016-04-21 14:19:26 -0600157
John Zulauf48a6a702017-12-22 17:14:54 -0700158 struct BindingTypeStats {
159 uint32_t dynamic_buffer_count;
160 uint32_t non_dynamic_buffer_count;
161 uint32_t image_sampler_count;
162 };
163 const BindingTypeStats &GetBindingTypeStats() const { return binding_type_stats_; }
164
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700165 private:
John Zulauf223b69d2018-11-09 16:00:59 -0700166 // Only the first three data members are used for hash and equality checks, the other members are derived from them, and are
167 // used to speed up the various lookups/queries/validations
John Zulauf1f8174b2018-02-16 12:58:37 -0700168 VkDescriptorSetLayoutCreateFlags flags_;
169 std::vector<safe_VkDescriptorSetLayoutBinding> bindings_;
Jeff Bolzfdf96072018-04-10 14:32:18 -0500170 std::vector<VkDescriptorBindingFlagsEXT> binding_flags_;
John Zulauf1f8174b2018-02-16 12:58:37 -0700171
172 // Convenience data structures for rapid lookup of various descriptor set layout properties
John Zulaufb6d71202017-12-22 16:47:09 -0700173 std::set<uint32_t> non_empty_bindings_; // Containing non-emtpy bindings in numerical order
174 std::unordered_map<uint32_t, uint32_t> binding_to_index_map_;
175 // The following map allows an non-iterative lookup of a binding from a global index...
176 std::map<uint32_t, uint32_t> global_start_to_index_map_; // The index corresponding for a starting global (descriptor) index
John Zulaufc483f442017-12-15 14:02:06 -0700177 std::unordered_map<uint32_t, IndexRange> binding_to_global_index_range_map_; // range is exclusive of .end
Tobin Ehlisa3525e02016-11-17 10:50:52 -0700178 // For a given binding map to associated index in the dynamic offset array
179 std::unordered_map<uint32_t, uint32_t> binding_to_dynamic_array_idx_map_;
John Zulauf1f8174b2018-02-16 12:58:37 -0700180
Jeff Bolzfdf96072018-04-10 14:32:18 -0500181 uint32_t binding_count_; // # of bindings in this layout
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700182 uint32_t descriptor_count_; // total # descriptors in this layout
Tobin Ehlis2d9deec2016-04-21 14:19:26 -0600183 uint32_t dynamic_descriptor_count_;
John Zulauf48a6a702017-12-22 17:14:54 -0700184 BindingTypeStats binding_type_stats_;
Tobin Ehlis2d9deec2016-04-21 14:19:26 -0600185};
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600186
Jeremy Hayese4224ee2019-01-04 14:41:48 -0700187static inline bool operator==(const DescriptorSetLayoutDef &lhs, const DescriptorSetLayoutDef &rhs) {
John Zulauf223b69d2018-11-09 16:00:59 -0700188 bool result = (lhs.GetCreateFlags() == rhs.GetCreateFlags()) && (lhs.GetBindings() == rhs.GetBindings()) &&
189 (lhs.GetBindingFlags() == rhs.GetBindingFlags());
190 return result;
John Zulaufd47d0612018-02-16 13:00:34 -0700191}
192
John Zulauf34ebf272018-02-16 13:08:47 -0700193// Canonical dictionary of DSL definitions -- independent of device or handle
194using DescriptorSetLayoutDict = hash_util::Dictionary<DescriptorSetLayoutDef, hash_util::HasHashMember<DescriptorSetLayoutDef>>;
195using DescriptorSetLayoutId = DescriptorSetLayoutDict::Id;
John Zulauf1f8174b2018-02-16 12:58:37 -0700196
197class DescriptorSetLayout {
198 public:
199 // Constructors and destructor
200 DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info, const VkDescriptorSetLayout layout);
201 // Validate create info - should be called prior to creation
Jeff Bolzfdf96072018-04-10 14:32:18 -0500202 static bool ValidateCreateInfo(const debug_report_data *, const VkDescriptorSetLayoutCreateInfo *, const bool, const uint32_t,
Jeff Bolze54ae892018-09-08 12:16:29 -0500203 const bool, const VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing_features,
204 const VkPhysicalDeviceInlineUniformBlockFeaturesEXT *inline_uniform_block_features,
205 const VkPhysicalDeviceInlineUniformBlockPropertiesEXT *inline_uniform_block_props);
John Zulauf1f8174b2018-02-16 12:58:37 -0700206 bool HasBinding(const uint32_t binding) const { return layout_id_->HasBinding(binding); }
207 // Return true if this layout is compatible with passed in layout from a pipelineLayout,
208 // else return false and update error_msg with description of incompatibility
209 bool IsCompatible(DescriptorSetLayout const *const, std::string *) const;
210 // Straightforward Get functions
211 VkDescriptorSetLayout GetDescriptorSetLayout() const { return layout_; };
212 bool IsDestroyed() const { return layout_destroyed_; }
213 void MarkDestroyed() { layout_destroyed_ = true; }
Shannon McPhersonc06c33d2018-06-28 17:21:12 -0600214 const DescriptorSetLayoutDef *GetLayoutDef() const { return layout_id_.get(); }
215 DescriptorSetLayoutId GetLayoutId() const { return layout_id_; }
John Zulauf1f8174b2018-02-16 12:58:37 -0700216 uint32_t GetTotalDescriptorCount() const { return layout_id_->GetTotalDescriptorCount(); };
217 uint32_t GetDynamicDescriptorCount() const { return layout_id_->GetDynamicDescriptorCount(); };
218 uint32_t GetBindingCount() const { return layout_id_->GetBindingCount(); };
219 VkDescriptorSetLayoutCreateFlags GetCreateFlags() const { return layout_id_->GetCreateFlags(); }
220 bool IsNextBindingConsistent(const uint32_t) const;
221 uint32_t GetIndexFromBinding(uint32_t binding) const { return layout_id_->GetIndexFromBinding(binding); }
222 // Various Get functions that can either be passed a binding#, which will
223 // be automatically translated into the appropriate index, or the index# can be passed in directly
224 uint32_t GetMaxBinding() const { return layout_id_->GetMaxBinding(); }
225 VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromIndex(const uint32_t index) const {
226 return layout_id_->GetDescriptorSetLayoutBindingPtrFromIndex(index);
227 }
228 VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromBinding(uint32_t binding) const {
229 return layout_id_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
230 }
231 const std::vector<safe_VkDescriptorSetLayoutBinding> &GetBindings() const { return layout_id_->GetBindings(); }
Tony-LunarGa77cade2019-03-06 10:49:22 -0700232 const std::set<uint32_t> &GetSortedBindingSet() const { return layout_id_->GetSortedBindingSet(); }
John Zulauf1f8174b2018-02-16 12:58:37 -0700233 uint32_t GetDescriptorCountFromIndex(const uint32_t index) const { return layout_id_->GetDescriptorCountFromIndex(index); }
234 uint32_t GetDescriptorCountFromBinding(const uint32_t binding) const {
235 return layout_id_->GetDescriptorCountFromBinding(binding);
236 }
237 VkDescriptorType GetTypeFromIndex(const uint32_t index) const { return layout_id_->GetTypeFromIndex(index); }
238 VkDescriptorType GetTypeFromBinding(const uint32_t binding) const { return layout_id_->GetTypeFromBinding(binding); }
239 VkShaderStageFlags GetStageFlagsFromIndex(const uint32_t index) const { return layout_id_->GetStageFlagsFromIndex(index); }
240 VkShaderStageFlags GetStageFlagsFromBinding(const uint32_t binding) const {
241 return layout_id_->GetStageFlagsFromBinding(binding);
242 }
Jeff Bolzfdf96072018-04-10 14:32:18 -0500243 VkDescriptorBindingFlagsEXT GetDescriptorBindingFlagsFromIndex(const uint32_t index) const {
244 return layout_id_->GetDescriptorBindingFlagsFromIndex(index);
245 }
246 VkDescriptorBindingFlagsEXT GetDescriptorBindingFlagsFromBinding(const uint32_t binding) const {
247 return layout_id_->GetDescriptorBindingFlagsFromBinding(binding);
248 }
John Zulauf1f8174b2018-02-16 12:58:37 -0700249 uint32_t GetIndexFromGlobalIndex(const uint32_t global_index) const {
250 return layout_id_->GetIndexFromGlobalIndex(global_index);
251 }
252 VkDescriptorType GetTypeFromGlobalIndex(const uint32_t global_index) const {
253 return GetTypeFromIndex(GetIndexFromGlobalIndex(global_index));
254 }
255 VkSampler const *GetImmutableSamplerPtrFromBinding(const uint32_t binding) const {
256 return layout_id_->GetImmutableSamplerPtrFromBinding(binding);
257 }
258 VkSampler const *GetImmutableSamplerPtrFromIndex(const uint32_t index) const {
259 return layout_id_->GetImmutableSamplerPtrFromIndex(index);
260 }
261 // For a given binding and array index, return the corresponding index into the dynamic offset array
262 int32_t GetDynamicOffsetIndexFromBinding(uint32_t binding) const {
263 return layout_id_->GetDynamicOffsetIndexFromBinding(binding);
264 }
265 // For a particular binding, get the global index range
266 // This call should be guarded by a call to "HasBinding(binding)" to verify that the given binding exists
267 const IndexRange &GetGlobalIndexRangeFromBinding(const uint32_t binding) const {
268 return layout_id_->GetGlobalIndexRangeFromBinding(binding);
269 }
270 // Helper function to get the next valid binding for a descriptor
271 uint32_t GetNextValidBinding(const uint32_t binding) const { return layout_id_->GetNextValidBinding(binding); }
272 // For a particular binding starting at offset and having update_count descriptors
273 // updated, verify that for any binding boundaries crossed, the update is consistent
274 bool VerifyUpdateConsistency(uint32_t current_binding, uint32_t offset, uint32_t update_count, const char *type,
275 const VkDescriptorSet set, std::string *error_msg) const {
276 return layout_id_->VerifyUpdateConsistency(current_binding, offset, update_count, type, set, error_msg);
277 }
278 bool IsPushDescriptor() const { return layout_id_->IsPushDescriptor(); }
279
280 using BindingTypeStats = DescriptorSetLayoutDef::BindingTypeStats;
281 const BindingTypeStats &GetBindingTypeStats() const { return layout_id_->GetBindingTypeStats(); }
282
283 private:
284 VkDescriptorSetLayout layout_;
285 bool layout_destroyed_;
286 DescriptorSetLayoutId layout_id_;
287};
288
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600289/*
290 * Descriptor classes
291 * Descriptor is an abstract base class from which 5 separate descriptor types are derived.
292 * This allows the WriteUpdate() and CopyUpdate() operations to be specialized per
293 * descriptor type, but all descriptors in a set can be accessed via the common Descriptor*.
294 */
295
296// Slightly broader than type, each c++ "class" will has a corresponding "DescriptorClass"
Jeff Bolzfbe51582018-09-13 10:01:35 -0500297enum DescriptorClass { PlainSampler, ImageSampler, Image, TexelBuffer, GeneralBuffer, InlineUniform, AccelerationStructure };
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600298
299class Descriptor {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700300 public:
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600301 virtual ~Descriptor(){};
Tobin Ehlis300888c2016-05-18 13:43:26 -0600302 virtual void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) = 0;
303 virtual void CopyUpdate(const Descriptor *) = 0;
Tobin Ehlis8020eea2016-08-17 11:10:41 -0600304 // Create binding between resources of this descriptor and given cb_node
Mark Lobodzinskifae179e2019-03-08 16:47:08 -0700305 virtual void UpdateDrawState(CoreChecks *, GLOBAL_CB_NODE *) = 0;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600306 virtual DescriptorClass GetClass() const { return descriptor_class; };
307 // Special fast-path check for SamplerDescriptors that are immutable
308 virtual bool IsImmutableSampler() const { return false; };
309 // Check for dynamic descriptor type
310 virtual bool IsDynamic() const { return false; };
311 // Check for storage descriptor type
312 virtual bool IsStorage() const { return false; };
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700313 bool updated; // Has descriptor been updated?
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600314 DescriptorClass descriptor_class;
315};
316// Shared helper functions - These are useful because the shared sampler image descriptor type
317// performs common functions with both sampler and image descriptors so they can share their common functions
Mark Lobodzinski3840ca02019-03-08 18:36:11 -0700318bool ValidateSampler(const VkSampler, CoreChecks *);
319bool ValidateImageUpdate(VkImageView, VkImageLayout, VkDescriptorType, CoreChecks *, const char *func_name, std::string *,
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700320 std::string *);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600321
322class SamplerDescriptor : public Descriptor {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700323 public:
Tobin Ehlis300888c2016-05-18 13:43:26 -0600324 SamplerDescriptor(const VkSampler *);
325 void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
326 void CopyUpdate(const Descriptor *) override;
Mark Lobodzinskifae179e2019-03-08 16:47:08 -0700327 void UpdateDrawState(CoreChecks *, GLOBAL_CB_NODE *) override;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600328 virtual bool IsImmutableSampler() const override { return immutable_; };
Tobin Ehlis300888c2016-05-18 13:43:26 -0600329 VkSampler GetSampler() const { return sampler_; }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600330
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700331 private:
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600332 // bool ValidateSampler(const VkSampler) const;
333 VkSampler sampler_;
334 bool immutable_;
Tobin Ehlis546326f2016-04-26 11:06:05 -0600335};
336
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600337class ImageSamplerDescriptor : public Descriptor {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700338 public:
Tobin Ehlis300888c2016-05-18 13:43:26 -0600339 ImageSamplerDescriptor(const VkSampler *);
340 void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
341 void CopyUpdate(const Descriptor *) override;
Mark Lobodzinski3840ca02019-03-08 18:36:11 -0700342 void UpdateDrawState(CoreChecks *, GLOBAL_CB_NODE *) override;
Tobin Ehlisc9625152016-05-24 16:47:36 -0600343 virtual bool IsImmutableSampler() const override { return immutable_; };
Tobin Ehlis300888c2016-05-18 13:43:26 -0600344 VkSampler GetSampler() const { return sampler_; }
345 VkImageView GetImageView() const { return image_view_; }
346 VkImageLayout GetImageLayout() const { return image_layout_; }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600347
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700348 private:
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600349 VkSampler sampler_;
350 bool immutable_;
351 VkImageView image_view_;
352 VkImageLayout image_layout_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600353};
354
355class ImageDescriptor : public Descriptor {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700356 public:
Tobin Ehlis300888c2016-05-18 13:43:26 -0600357 ImageDescriptor(const VkDescriptorType);
358 void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
359 void CopyUpdate(const Descriptor *) override;
Mark Lobodzinskifae179e2019-03-08 16:47:08 -0700360 void UpdateDrawState(CoreChecks *, GLOBAL_CB_NODE *) override;
Norbert Nopper419a1092016-05-15 19:19:41 +0200361 virtual bool IsStorage() const override { return storage_; }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600362 VkImageView GetImageView() const { return image_view_; }
363 VkImageLayout GetImageLayout() const { return image_layout_; }
364
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700365 private:
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600366 bool storage_;
367 VkImageView image_view_;
368 VkImageLayout image_layout_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600369};
370
371class TexelDescriptor : public Descriptor {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700372 public:
Tobin Ehlis300888c2016-05-18 13:43:26 -0600373 TexelDescriptor(const VkDescriptorType);
374 void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
375 void CopyUpdate(const Descriptor *) override;
Mark Lobodzinskifae179e2019-03-08 16:47:08 -0700376 void UpdateDrawState(CoreChecks *, GLOBAL_CB_NODE *) override;
Tobin Ehlisf490f2e2016-05-17 06:43:48 -0600377 virtual bool IsStorage() const override { return storage_; }
378 VkBufferView GetBufferView() const { return buffer_view_; }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600379
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700380 private:
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600381 VkBufferView buffer_view_;
382 bool storage_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600383};
384
385class BufferDescriptor : public Descriptor {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700386 public:
Tobin Ehlis300888c2016-05-18 13:43:26 -0600387 BufferDescriptor(const VkDescriptorType);
388 void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
389 void CopyUpdate(const Descriptor *) override;
Mark Lobodzinskifae179e2019-03-08 16:47:08 -0700390 void UpdateDrawState(CoreChecks *, GLOBAL_CB_NODE *) override;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600391 virtual bool IsDynamic() const override { return dynamic_; }
392 virtual bool IsStorage() const override { return storage_; }
393 VkBuffer GetBuffer() const { return buffer_; }
394 VkDeviceSize GetOffset() const { return offset_; }
395 VkDeviceSize GetRange() const { return range_; }
396
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700397 private:
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600398 bool storage_;
399 bool dynamic_;
400 VkBuffer buffer_;
401 VkDeviceSize offset_;
402 VkDeviceSize range_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600403};
Jeff Bolze54ae892018-09-08 12:16:29 -0500404
405class InlineUniformDescriptor : public Descriptor {
406 public:
Dave Houlton142c4cb2018-10-17 15:04:41 -0600407 InlineUniformDescriptor(const VkDescriptorType) {
408 updated = false;
409 descriptor_class = InlineUniform;
410 }
Jeff Bolze54ae892018-09-08 12:16:29 -0500411 void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override { updated = true; }
Dave Houlton142c4cb2018-10-17 15:04:41 -0600412 void CopyUpdate(const Descriptor *) override { updated = true; }
Mark Lobodzinskifae179e2019-03-08 16:47:08 -0700413 void UpdateDrawState(CoreChecks *, GLOBAL_CB_NODE *) override {}
Jeff Bolze54ae892018-09-08 12:16:29 -0500414};
415
Jeff Bolzfbe51582018-09-13 10:01:35 -0500416class AccelerationStructureDescriptor : public Descriptor {
417 public:
Dave Houlton142c4cb2018-10-17 15:04:41 -0600418 AccelerationStructureDescriptor(const VkDescriptorType) {
419 updated = false;
420 descriptor_class = AccelerationStructure;
421 }
Jeff Bolzfbe51582018-09-13 10:01:35 -0500422 void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override { updated = true; }
Dave Houlton142c4cb2018-10-17 15:04:41 -0600423 void CopyUpdate(const Descriptor *) override { updated = true; }
Mark Lobodzinskifae179e2019-03-08 16:47:08 -0700424 void UpdateDrawState(CoreChecks *, GLOBAL_CB_NODE *) override {}
Jeff Bolzfbe51582018-09-13 10:01:35 -0500425};
426
Tobin Ehlis68d0adf2016-06-01 11:33:50 -0600427// Structs to contain common elements that need to be shared between Validate* and Perform* calls below
428struct AllocateDescriptorSetsData {
Jeff Bolze54ae892018-09-08 12:16:29 -0500429 std::map<uint32_t, uint32_t> required_descriptors_by_type;
Tobin Ehlisa8e46e72017-06-21 10:16:10 -0600430 std::vector<std::shared_ptr<DescriptorSetLayout const>> layout_nodes;
Tobin Ehlis68d0adf2016-06-01 11:33:50 -0600431 AllocateDescriptorSetsData(uint32_t);
432};
Tobin Ehlisee471462016-05-26 11:21:59 -0600433// Helper functions for descriptor set functions that cross multiple sets
434// "Validate" will make sure an update is ok without actually performing it
Mark Lobodzinski3840ca02019-03-08 18:36:11 -0700435bool ValidateUpdateDescriptorSets(const debug_report_data *, const CoreChecks *, uint32_t, const VkWriteDescriptorSet *, uint32_t,
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700436 const VkCopyDescriptorSet *, const char *func_name);
Tobin Ehlisee471462016-05-26 11:21:59 -0600437// "Perform" does the update with the assumption that ValidateUpdateDescriptorSets() has passed for the given update
Mark Lobodzinski3840ca02019-03-08 18:36:11 -0700438void PerformUpdateDescriptorSets(CoreChecks *, uint32_t, const VkWriteDescriptorSet *, uint32_t, const VkCopyDescriptorSet *);
John Zulaufb845eb22018-10-12 11:41:06 -0600439
440// Helper class to encapsulate the descriptor update template decoding logic
441struct DecodedTemplateUpdate {
442 std::vector<VkWriteDescriptorSet> desc_writes;
443 std::vector<VkWriteDescriptorSetInlineUniformBlockEXT> inline_infos;
Mark Lobodzinski3840ca02019-03-08 18:36:11 -0700444 DecodedTemplateUpdate(CoreChecks *device_data, VkDescriptorSet descriptorSet, const TEMPLATE_STATE *template_state,
John Zulauf1d27e0a2018-11-05 10:12:48 -0700445 const void *pData, VkDescriptorSetLayout push_layout = VK_NULL_HANDLE);
John Zulaufb845eb22018-10-12 11:41:06 -0600446};
Tobin Ehlisee471462016-05-26 11:21:59 -0600447
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600448/*
449 * DescriptorSet class
450 *
451 * Overview - This class encapsulates the Vulkan VkDescriptorSet data (set).
452 * A set has an underlying layout which defines the bindings in the set and the
453 * types and numbers of descriptors in each descriptor slot. Most of the layout
454 * interfaces are exposed through identically-named functions in the set class.
455 * Please refer to the DescriptorSetLayout comment above for a description of
456 * index, binding, and global index.
457 *
458 * At construction a vector of Descriptor* is created with types corresponding to the
459 * layout. The primary operation performed on the descriptors is to update them
460 * via write or copy updates, and validate that the update contents are correct.
461 * In order to validate update contents, the DescriptorSet stores a bunch of ptrs
462 * to data maps where various Vulkan objects can be looked up. The management of
463 * those maps is performed externally. The set class relies on their contents to
464 * be correct at the time of update.
465 */
Tobin Ehlis05be5df2016-05-05 08:25:02 -0600466class DescriptorSet : public BASE_NODE {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700467 public:
Tobin Ehlis452b4532017-06-21 09:56:13 -0600468 DescriptorSet(const VkDescriptorSet, const VkDescriptorPool, const std::shared_ptr<DescriptorSetLayout const> &,
Mark Lobodzinski3840ca02019-03-08 18:36:11 -0700469 uint32_t variable_count, CoreChecks *);
Tobin Ehlis9906d9d2016-05-17 14:23:46 -0600470 ~DescriptorSet();
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600471 // A number of common Get* functions that return data based on layout from which this set was created
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600472 uint32_t GetTotalDescriptorCount() const { return p_layout_->GetTotalDescriptorCount(); };
473 uint32_t GetDynamicDescriptorCount() const { return p_layout_->GetDynamicDescriptorCount(); };
474 uint32_t GetBindingCount() const { return p_layout_->GetBindingCount(); };
475 VkDescriptorType GetTypeFromIndex(const uint32_t index) const { return p_layout_->GetTypeFromIndex(index); };
476 VkDescriptorType GetTypeFromGlobalIndex(const uint32_t index) const { return p_layout_->GetTypeFromGlobalIndex(index); };
477 VkDescriptorType GetTypeFromBinding(const uint32_t binding) const { return p_layout_->GetTypeFromBinding(binding); };
478 uint32_t GetDescriptorCountFromIndex(const uint32_t index) const { return p_layout_->GetDescriptorCountFromIndex(index); };
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600479 uint32_t GetDescriptorCountFromBinding(const uint32_t binding) const {
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600480 return p_layout_->GetDescriptorCountFromBinding(binding);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600481 };
Tobin Ehlisa3525e02016-11-17 10:50:52 -0700482 // Return index into dynamic offset array for given binding
483 int32_t GetDynamicOffsetIndexFromBinding(uint32_t binding) const {
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600484 return p_layout_->GetDynamicOffsetIndexFromBinding(binding);
Tobin Ehlisa3525e02016-11-17 10:50:52 -0700485 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600486 // Return true if given binding is present in this set
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600487 bool HasBinding(const uint32_t binding) const { return p_layout_->HasBinding(binding); };
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600488 // Is this set compatible with the given layout?
Tobin Ehlis6dc57dd2017-06-21 10:08:52 -0600489 bool IsCompatible(DescriptorSetLayout const *const, std::string *) const;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600490 // For given bindings validate state at time of draw is correct, returning false on error and writing error details into string*
John Zulauf48a6a702017-12-22 17:14:54 -0700491 bool ValidateDrawState(const std::map<uint32_t, descriptor_req> &, const std::vector<uint32_t> &, GLOBAL_CB_NODE *,
Tobin Ehlisc8266452017-04-07 12:20:30 -0600492 const char *caller, std::string *) const;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600493 // For given set of bindings, add any buffers and images that will be updated to their respective unordered_sets & return number
494 // of objects inserted
Tobin Ehliscebc4c02016-08-22 10:10:43 -0600495 uint32_t GetStorageUpdates(const std::map<uint32_t, descriptor_req> &, std::unordered_set<VkBuffer> *,
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600496 std::unordered_set<VkImageView> *) const;
Tobin Ehlis300888c2016-05-18 13:43:26 -0600497
John Zulauf4e7bcb52018-11-02 10:46:30 -0600498 std::string StringifySetAndLayout() const;
Tobin Ehlis300888c2016-05-18 13:43:26 -0600499 // Descriptor Update functions. These functions validate state and perform update separately
John Zulauf1d27e0a2018-11-05 10:12:48 -0700500 // Validate contents of a push descriptor update
501 bool ValidatePushDescriptorsUpdate(const debug_report_data *report_data, uint32_t write_count,
502 const VkWriteDescriptorSet *p_wds, const char *func_name);
503 // Perform a push update whose contents were just validated using ValidatePushDescriptorsUpdate
504 void PerformPushDescriptorsUpdate(uint32_t write_count, const VkWriteDescriptorSet *p_wds);
Tobin Ehlis300888c2016-05-18 13:43:26 -0600505 // Validate contents of a WriteUpdate
John Zulaufb45fdc32018-10-12 15:14:17 -0600506 bool ValidateWriteUpdate(const debug_report_data *, const VkWriteDescriptorSet *, const char *, std::string *, std::string *);
Tobin Ehlis300888c2016-05-18 13:43:26 -0600507 // Perform a WriteUpdate whose contents were just validated using ValidateWriteUpdate
508 void PerformWriteUpdate(const VkWriteDescriptorSet *);
509 // Validate contents of a CopyUpdate
John Zulaufb45fdc32018-10-12 15:14:17 -0600510 bool ValidateCopyUpdate(const debug_report_data *, const VkCopyDescriptorSet *, const DescriptorSet *, const char *func_name,
511 std::string *, std::string *);
Tobin Ehlis300888c2016-05-18 13:43:26 -0600512 // Perform a CopyUpdate whose contents were just validated using ValidateCopyUpdate
513 void PerformCopyUpdate(const VkCopyDescriptorSet *, const DescriptorSet *);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600514
John Zulauf1f8174b2018-02-16 12:58:37 -0700515 const std::shared_ptr<DescriptorSetLayout const> GetLayout() const { return p_layout_; };
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600516 VkDescriptorSet GetSet() const { return set_; };
517 // Return unordered_set of all command buffers that this set is bound to
Tobin Ehlis2556f5b2016-06-24 17:22:16 -0600518 std::unordered_set<GLOBAL_CB_NODE *> GetBoundCmdBuffers() const { return cb_bindings; }
John Zulauf6f3d2bd2018-10-29 17:08:42 -0600519 // Bind given cmd_buffer to this descriptor set and
520 // update CB image layout map with image/imagesampler descriptor image layouts
Mark Lobodzinskifae179e2019-03-08 16:47:08 -0700521 void UpdateDrawState(CoreChecks *, GLOBAL_CB_NODE *, const std::map<uint32_t, descriptor_req> &);
John Zulauf48a6a702017-12-22 17:14:54 -0700522
523 // Track work that has been bound or validated to avoid duplicate work, important when large descriptor arrays
524 // are present
525 typedef std::unordered_set<uint32_t> TrackedBindings;
526 static void FilterAndTrackOneBindingReq(const BindingReqMap::value_type &binding_req_pair, const BindingReqMap &in_req,
527 BindingReqMap *out_req, TrackedBindings *set);
528 static void FilterAndTrackOneBindingReq(const BindingReqMap::value_type &binding_req_pair, const BindingReqMap &in_req,
529 BindingReqMap *out_req, TrackedBindings *set, uint32_t limit);
530 void FilterAndTrackBindingReqs(GLOBAL_CB_NODE *, const BindingReqMap &in_req, BindingReqMap *out_req);
531 void FilterAndTrackBindingReqs(GLOBAL_CB_NODE *, PIPELINE_STATE *, const BindingReqMap &in_req, BindingReqMap *out_req);
532 void ClearCachedDynamicDescriptorValidation(GLOBAL_CB_NODE *cb_state) { cached_validation_[cb_state].dynamic_buffers.clear(); }
533 void ClearCachedValidation(GLOBAL_CB_NODE *cb_state) { cached_validation_.erase(cb_state); }
Tobin Ehlis2556f5b2016-06-24 17:22:16 -0600534 // If given cmd_buffer is in the cb_bindings set, remove it
John Zulauf48a6a702017-12-22 17:14:54 -0700535 void RemoveBoundCommandBuffer(GLOBAL_CB_NODE *cb_node) {
536 cb_bindings.erase(cb_node);
537 ClearCachedValidation(cb_node);
538 }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600539 VkSampler const *GetImmutableSamplerPtrFromBinding(const uint32_t index) const {
Tobin Ehlis7cd8c792017-06-20 08:30:39 -0600540 return p_layout_->GetImmutableSamplerPtrFromBinding(index);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600541 };
542 // For a particular binding, get the global index
Tony-LunarGa77cade2019-03-06 10:49:22 -0700543 const IndexRange GetGlobalIndexRangeFromBinding(const uint32_t binding, bool actual_length = false) const {
544 if (actual_length && binding == p_layout_->GetMaxBinding() && IsVariableDescriptorCount(binding)) {
545 IndexRange range = p_layout_->GetGlobalIndexRangeFromBinding(binding);
546 auto diff = GetDescriptorCountFromBinding(binding) - GetVariableDescriptorCount();
547 range.end -= diff;
548 return range;
549 }
John Zulaufc483f442017-12-15 14:02:06 -0700550 return p_layout_->GetGlobalIndexRangeFromBinding(binding);
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600551 };
552 // Return true if any part of set has ever been updated
553 bool IsUpdated() const { return some_update_; };
Józef Kuciaf0c94d42017-10-25 22:15:22 +0200554 bool IsPushDescriptor() const { return p_layout_->IsPushDescriptor(); };
Jeff Bolzfdf96072018-04-10 14:32:18 -0500555 bool IsVariableDescriptorCount(uint32_t binding) const {
556 return !!(p_layout_->GetDescriptorBindingFlagsFromBinding(binding) &
557 VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT);
558 }
Tony-LunarG81efe392019-03-07 15:43:27 -0700559 bool IsUpdateAfterBind(uint32_t binding) const {
560 return !!(p_layout_->GetDescriptorBindingFlagsFromBinding(binding) & VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT);
561 }
Jeff Bolzfdf96072018-04-10 14:32:18 -0500562 uint32_t GetVariableDescriptorCount() const { return variable_count_; }
563 DESCRIPTOR_POOL_STATE *GetPoolState() const { return pool_state_; }
Tony-LunarGa77cade2019-03-06 10:49:22 -0700564 const Descriptor *GetDescriptorFromGlobalIndex(const uint32_t index) const { return descriptors_[index].get(); }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600565
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700566 private:
John Zulaufb45fdc32018-10-12 15:14:17 -0600567 bool VerifyWriteUpdateContents(const VkWriteDescriptorSet *, const uint32_t, const char *, std::string *, std::string *) const;
568 bool VerifyCopyUpdateContents(const VkCopyDescriptorSet *, const DescriptorSet *, VkDescriptorType, uint32_t, const char *,
569 std::string *, std::string *) const;
Dave Houlton00c154e2018-05-24 13:20:50 -0600570 bool ValidateBufferUsage(BUFFER_STATE const *, VkDescriptorType, std::string *, std::string *) const;
John Zulaufb45fdc32018-10-12 15:14:17 -0600571 bool ValidateBufferUpdate(VkDescriptorBufferInfo const *, VkDescriptorType, const char *, std::string *, std::string *) const;
Tobin Ehlis9906d9d2016-05-17 14:23:46 -0600572 // Private helper to set all bound cmd buffers to INVALID state
573 void InvalidateBoundCmdBuffers();
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700574 bool some_update_; // has any part of the set ever been updated?
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600575 VkDescriptorSet set_;
Tobin Ehlis7ca20be2016-10-12 15:09:16 -0600576 DESCRIPTOR_POOL_STATE *pool_state_;
Tobin Ehlis452b4532017-06-21 09:56:13 -0600577 const std::shared_ptr<DescriptorSetLayout const> p_layout_;
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600578 std::vector<std::unique_ptr<Descriptor>> descriptors_;
Mark Lobodzinski3840ca02019-03-08 18:36:11 -0700579 CoreChecks *device_data_;
Tobin Ehlisc3b6c4c2017-02-02 17:26:40 -0700580 const VkPhysicalDeviceLimits limits_;
Jeff Bolzfdf96072018-04-10 14:32:18 -0500581 uint32_t variable_count_;
John Zulauf48a6a702017-12-22 17:14:54 -0700582
583 // Cached binding and validation support:
584 //
585 // For the lifespan of a given command buffer recording, do lazy evaluation, caching, and dirtying of
586 // expensive validation operation (typically per-draw)
587 typedef std::unordered_map<GLOBAL_CB_NODE *, TrackedBindings> TrackedBindingMap;
588 typedef std::unordered_map<PIPELINE_STATE *, TrackedBindingMap> ValidatedBindings;
589 // Track the validation caching of bindings vs. the command buffer and draw state
590 typedef std::unordered_map<uint32_t, GLOBAL_CB_NODE::ImageLayoutUpdateCount> VersionedBindings;
591 struct CachedValidation {
592 TrackedBindings command_binding_and_usage; // Persistent for the life of the recording
593 TrackedBindings non_dynamic_buffers; // Persistent for the life of the recording
594 TrackedBindings dynamic_buffers; // Dirtied (flushed) each BindDescriptorSet
595 std::unordered_map<PIPELINE_STATE *, VersionedBindings> image_samplers; // Tested vs. changes to CB's ImageLayout
596 };
597 typedef std::unordered_map<GLOBAL_CB_NODE *, CachedValidation> CachedValidationMap;
598 // Image and ImageView bindings are validated per pipeline and not invalidate by repeated binding
599 CachedValidationMap cached_validation_;
600};
601// For the "bindless" style resource usage with many descriptors, need to optimize binding and validation
602class PrefilterBindRequestMap {
603 public:
604 static const uint32_t kManyDescriptors_ = 64; // TODO base this number on measured data
605 std::unique_ptr<BindingReqMap> filtered_map_;
606 const BindingReqMap &orig_map_;
607
608 PrefilterBindRequestMap(DescriptorSet &ds, const BindingReqMap &in_map, GLOBAL_CB_NODE *cb_state);
609 PrefilterBindRequestMap(DescriptorSet &ds, const BindingReqMap &in_map, GLOBAL_CB_NODE *cb_state, PIPELINE_STATE *);
610 const BindingReqMap &Map() const { return (filtered_map_) ? *filtered_map_ : orig_map_; }
Tobin Ehlis0a43bde2016-05-03 08:31:08 -0600611};
Dave Houltona9df0ce2018-02-07 10:51:23 -0700612} // namespace cvdescriptorset
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700613#endif // CORE_VALIDATION_DESCRIPTOR_SETS_H_