xref: /aosp_15_r20/external/vulkan-validation-layers/layers/descriptor_sets.h (revision b7893ccf7851cd6a48cc5a1e965257d8a5cdcc70)
1*b7893ccfSSadaf Ebrahimi /* Copyright (c) 2015-2019 The Khronos Group Inc.
2*b7893ccfSSadaf Ebrahimi  * Copyright (c) 2015-2019 Valve Corporation
3*b7893ccfSSadaf Ebrahimi  * Copyright (c) 2015-2019 LunarG, Inc.
4*b7893ccfSSadaf Ebrahimi  * Copyright (C) 2015-2019 Google Inc.
5*b7893ccfSSadaf Ebrahimi  *
6*b7893ccfSSadaf Ebrahimi  * Licensed under the Apache License, Version 2.0 (the "License");
7*b7893ccfSSadaf Ebrahimi  * you may not use this file except in compliance with the License.
8*b7893ccfSSadaf Ebrahimi  * You may obtain a copy of the License at
9*b7893ccfSSadaf Ebrahimi  *
10*b7893ccfSSadaf Ebrahimi  *     http://www.apache.org/licenses/LICENSE-2.0
11*b7893ccfSSadaf Ebrahimi  *
12*b7893ccfSSadaf Ebrahimi  * Unless required by applicable law or agreed to in writing, software
13*b7893ccfSSadaf Ebrahimi  * distributed under the License is distributed on an "AS IS" BASIS,
14*b7893ccfSSadaf Ebrahimi  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*b7893ccfSSadaf Ebrahimi  * See the License for the specific language governing permissions and
16*b7893ccfSSadaf Ebrahimi  * limitations under the License.
17*b7893ccfSSadaf Ebrahimi  *
18*b7893ccfSSadaf Ebrahimi  * Author: Tobin Ehlis <[email protected]>
19*b7893ccfSSadaf Ebrahimi  *         John Zulauf <[email protected]>
20*b7893ccfSSadaf Ebrahimi  */
21*b7893ccfSSadaf Ebrahimi #ifndef CORE_VALIDATION_DESCRIPTOR_SETS_H_
22*b7893ccfSSadaf Ebrahimi #define CORE_VALIDATION_DESCRIPTOR_SETS_H_
23*b7893ccfSSadaf Ebrahimi 
24*b7893ccfSSadaf Ebrahimi #include "hash_vk_types.h"
25*b7893ccfSSadaf Ebrahimi #include "vk_layer_logging.h"
26*b7893ccfSSadaf Ebrahimi #include "vk_layer_utils.h"
27*b7893ccfSSadaf Ebrahimi #include "vk_safe_struct.h"
28*b7893ccfSSadaf Ebrahimi #include "vulkan/vk_layer.h"
29*b7893ccfSSadaf Ebrahimi #include "vk_object_types.h"
30*b7893ccfSSadaf Ebrahimi #include <map>
31*b7893ccfSSadaf Ebrahimi #include <memory>
32*b7893ccfSSadaf Ebrahimi #include <set>
33*b7893ccfSSadaf Ebrahimi #include <unordered_map>
34*b7893ccfSSadaf Ebrahimi #include <unordered_set>
35*b7893ccfSSadaf Ebrahimi #include <vector>
36*b7893ccfSSadaf Ebrahimi 
37*b7893ccfSSadaf Ebrahimi class CoreChecks;
38*b7893ccfSSadaf Ebrahimi class ValidationStateTracker;
39*b7893ccfSSadaf Ebrahimi 
40*b7893ccfSSadaf Ebrahimi // Descriptor Data structures
41*b7893ccfSSadaf Ebrahimi namespace cvdescriptorset {
42*b7893ccfSSadaf Ebrahimi 
43*b7893ccfSSadaf Ebrahimi // Utility structs/classes/types
44*b7893ccfSSadaf Ebrahimi // Index range for global indices below, end is exclusive, i.e. [start,end)
45*b7893ccfSSadaf Ebrahimi struct IndexRange {
IndexRangeIndexRange46*b7893ccfSSadaf Ebrahimi     IndexRange(uint32_t start_in, uint32_t end_in) : start(start_in), end(end_in) {}
47*b7893ccfSSadaf Ebrahimi     IndexRange() = default;
48*b7893ccfSSadaf Ebrahimi     uint32_t start;
49*b7893ccfSSadaf Ebrahimi     uint32_t end;
50*b7893ccfSSadaf Ebrahimi };
51*b7893ccfSSadaf Ebrahimi 
52*b7893ccfSSadaf Ebrahimi /*
53*b7893ccfSSadaf Ebrahimi  * DescriptorSetLayoutDef/DescriptorSetLayout classes
54*b7893ccfSSadaf Ebrahimi  *
55*b7893ccfSSadaf Ebrahimi  * Overview - These two classes encapsulate the Vulkan VkDescriptorSetLayout data (layout).
56*b7893ccfSSadaf Ebrahimi  *   A layout consists of some number of bindings, each of which has a binding#, a
57*b7893ccfSSadaf Ebrahimi  *   type, descriptor count, stage flags, and pImmutableSamplers.
58*b7893ccfSSadaf Ebrahimi 
59*b7893ccfSSadaf Ebrahimi  *   The DescriptorSetLayoutDef represents a canonicalization of the input data and contains
60*b7893ccfSSadaf Ebrahimi  *   neither per handle or per device state.  It is possible for different handles on
61*b7893ccfSSadaf Ebrahimi  *   different devices to share a common def.  This is used and useful for quick compatibiltiy
62*b7893ccfSSadaf Ebrahimi  *   validation.  The DescriptorSetLayout refers to a DescriptorSetLayoutDef and contains
63*b7893ccfSSadaf Ebrahimi  *   all per handle state.
64*b7893ccfSSadaf Ebrahimi  *
65*b7893ccfSSadaf Ebrahimi  * Index vs Binding - A layout is created with an array of VkDescriptorSetLayoutBinding
66*b7893ccfSSadaf Ebrahimi  *  where each array index will have a corresponding binding# that is defined in that struct.
67*b7893ccfSSadaf Ebrahimi  *  The binding#, then, is decoupled from VkDescriptorSetLayoutBinding index, which allows
68*b7893ccfSSadaf Ebrahimi  *  bindings to be defined out-of-order. This DescriptorSetLayout class, however, stores
69*b7893ccfSSadaf Ebrahimi  *  the bindings internally in-order. This is useful for operations which may "roll over"
70*b7893ccfSSadaf Ebrahimi  *  from a single binding to the next consecutive binding.
71*b7893ccfSSadaf Ebrahimi  *
72*b7893ccfSSadaf Ebrahimi  *  Note that although the bindings are stored in-order, there still may be "gaps" in the
73*b7893ccfSSadaf Ebrahimi  *  binding#. For example, if the binding creation order is 8, 7, 10, 3, 4, then the
74*b7893ccfSSadaf Ebrahimi  *  internal binding array will have five entries stored in binding order 3, 4, 7, 8, 10.
75*b7893ccfSSadaf Ebrahimi  *  To process all of the bindings in a layout you can iterate from 0 to GetBindingCount()
76*b7893ccfSSadaf Ebrahimi  *  and use the Get*FromIndex() functions for each index. To just process a single binding,
77*b7893ccfSSadaf Ebrahimi  *  use the Get*FromBinding() functions.
78*b7893ccfSSadaf Ebrahimi  *
79*b7893ccfSSadaf Ebrahimi  * Global Index - The binding vector index has as many indices as there are bindings.
80*b7893ccfSSadaf Ebrahimi  *  This class also has the concept of a Global Index. For the global index functions,
81*b7893ccfSSadaf Ebrahimi  *  there are as many global indices as there are descriptors in the layout.
82*b7893ccfSSadaf Ebrahimi  *  For the global index, consider all of the bindings to be a flat array where
83*b7893ccfSSadaf Ebrahimi  *  descriptor 0 of of the lowest binding# is index 0 and each descriptor in the layout
84*b7893ccfSSadaf Ebrahimi  *  increments from there. So if the lowest binding# in this example had descriptorCount of
85*b7893ccfSSadaf Ebrahimi  *  10, then the GlobalStartIndex of the 2nd lowest binding# will be 10 where 0-9 are the
86*b7893ccfSSadaf Ebrahimi  *  global indices for the lowest binding#.
87*b7893ccfSSadaf Ebrahimi  */
88*b7893ccfSSadaf Ebrahimi class DescriptorSetLayoutDef {
89*b7893ccfSSadaf Ebrahimi    public:
90*b7893ccfSSadaf Ebrahimi     // Constructors and destructor
91*b7893ccfSSadaf Ebrahimi     DescriptorSetLayoutDef(const VkDescriptorSetLayoutCreateInfo *p_create_info);
92*b7893ccfSSadaf Ebrahimi     size_t hash() const;
93*b7893ccfSSadaf Ebrahimi 
GetTotalDescriptorCount()94*b7893ccfSSadaf Ebrahimi     uint32_t GetTotalDescriptorCount() const { return descriptor_count_; };
GetDynamicDescriptorCount()95*b7893ccfSSadaf Ebrahimi     uint32_t GetDynamicDescriptorCount() const { return dynamic_descriptor_count_; };
GetCreateFlags()96*b7893ccfSSadaf Ebrahimi     VkDescriptorSetLayoutCreateFlags GetCreateFlags() const { return flags_; }
97*b7893ccfSSadaf Ebrahimi     // For a given binding, return the number of descriptors in that binding and all successive bindings
GetBindingCount()98*b7893ccfSSadaf Ebrahimi     uint32_t GetBindingCount() const { return binding_count_; };
99*b7893ccfSSadaf Ebrahimi     // Non-empty binding numbers in order
GetSortedBindingSet()100*b7893ccfSSadaf Ebrahimi     const std::set<uint32_t> &GetSortedBindingSet() const { return non_empty_bindings_; }
101*b7893ccfSSadaf Ebrahimi     // Return true if given binding is present in this layout
HasBinding(const uint32_t binding)102*b7893ccfSSadaf Ebrahimi     bool HasBinding(const uint32_t binding) const { return binding_to_index_map_.count(binding) > 0; };
103*b7893ccfSSadaf Ebrahimi     // Return true if binding 1 beyond given exists and has same type, stageFlags & immutable sampler use
104*b7893ccfSSadaf Ebrahimi     bool IsNextBindingConsistent(const uint32_t) const;
105*b7893ccfSSadaf Ebrahimi     uint32_t GetIndexFromBinding(uint32_t binding) const;
106*b7893ccfSSadaf Ebrahimi     // Various Get functions that can either be passed a binding#, which will
107*b7893ccfSSadaf Ebrahimi     //  be automatically translated into the appropriate index, or the index# can be passed in directly
GetMaxBinding()108*b7893ccfSSadaf Ebrahimi     uint32_t GetMaxBinding() const { return bindings_[bindings_.size() - 1].binding; }
109*b7893ccfSSadaf Ebrahimi     VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromIndex(const uint32_t) const;
GetDescriptorSetLayoutBindingPtrFromBinding(uint32_t binding)110*b7893ccfSSadaf Ebrahimi     VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromBinding(uint32_t binding) const {
111*b7893ccfSSadaf Ebrahimi         return GetDescriptorSetLayoutBindingPtrFromIndex(GetIndexFromBinding(binding));
112*b7893ccfSSadaf Ebrahimi     }
GetBindings()113*b7893ccfSSadaf Ebrahimi     const std::vector<safe_VkDescriptorSetLayoutBinding> &GetBindings() const { return bindings_; }
GetBindingFlags()114*b7893ccfSSadaf Ebrahimi     const std::vector<VkDescriptorBindingFlagsEXT> &GetBindingFlags() const { return binding_flags_; }
115*b7893ccfSSadaf Ebrahimi     uint32_t GetDescriptorCountFromIndex(const uint32_t) const;
GetDescriptorCountFromBinding(const uint32_t binding)116*b7893ccfSSadaf Ebrahimi     uint32_t GetDescriptorCountFromBinding(const uint32_t binding) const {
117*b7893ccfSSadaf Ebrahimi         return GetDescriptorCountFromIndex(GetIndexFromBinding(binding));
118*b7893ccfSSadaf Ebrahimi     }
119*b7893ccfSSadaf Ebrahimi     VkDescriptorType GetTypeFromIndex(const uint32_t) const;
GetTypeFromBinding(const uint32_t binding)120*b7893ccfSSadaf Ebrahimi     VkDescriptorType GetTypeFromBinding(const uint32_t binding) const { return GetTypeFromIndex(GetIndexFromBinding(binding)); }
121*b7893ccfSSadaf Ebrahimi     VkShaderStageFlags GetStageFlagsFromIndex(const uint32_t) const;
GetStageFlagsFromBinding(const uint32_t binding)122*b7893ccfSSadaf Ebrahimi     VkShaderStageFlags GetStageFlagsFromBinding(const uint32_t binding) const {
123*b7893ccfSSadaf Ebrahimi         return GetStageFlagsFromIndex(GetIndexFromBinding(binding));
124*b7893ccfSSadaf Ebrahimi     }
125*b7893ccfSSadaf Ebrahimi     VkDescriptorBindingFlagsEXT GetDescriptorBindingFlagsFromIndex(const uint32_t) const;
GetDescriptorBindingFlagsFromBinding(const uint32_t binding)126*b7893ccfSSadaf Ebrahimi     VkDescriptorBindingFlagsEXT GetDescriptorBindingFlagsFromBinding(const uint32_t binding) const {
127*b7893ccfSSadaf Ebrahimi         return GetDescriptorBindingFlagsFromIndex(GetIndexFromBinding(binding));
128*b7893ccfSSadaf Ebrahimi     }
129*b7893ccfSSadaf Ebrahimi     VkSampler const *GetImmutableSamplerPtrFromBinding(const uint32_t) const;
130*b7893ccfSSadaf Ebrahimi     VkSampler const *GetImmutableSamplerPtrFromIndex(const uint32_t) const;
131*b7893ccfSSadaf Ebrahimi     // For a given binding and array index, return the corresponding index into the dynamic offset array
GetDynamicOffsetIndexFromBinding(uint32_t binding)132*b7893ccfSSadaf Ebrahimi     int32_t GetDynamicOffsetIndexFromBinding(uint32_t binding) const {
133*b7893ccfSSadaf Ebrahimi         auto dyn_off = binding_to_dynamic_array_idx_map_.find(binding);
134*b7893ccfSSadaf Ebrahimi         if (dyn_off == binding_to_dynamic_array_idx_map_.end()) {
135*b7893ccfSSadaf Ebrahimi             assert(0);  // Requesting dyn offset for invalid binding/array idx pair
136*b7893ccfSSadaf Ebrahimi             return -1;
137*b7893ccfSSadaf Ebrahimi         }
138*b7893ccfSSadaf Ebrahimi         return dyn_off->second;
139*b7893ccfSSadaf Ebrahimi     }
140*b7893ccfSSadaf Ebrahimi     // For a particular binding, get the global index range
141*b7893ccfSSadaf Ebrahimi     //  This call should be guarded by a call to "HasBinding(binding)" to verify that the given binding exists
142*b7893ccfSSadaf Ebrahimi     const IndexRange &GetGlobalIndexRangeFromBinding(const uint32_t) const;
143*b7893ccfSSadaf Ebrahimi     const cvdescriptorset::IndexRange &GetGlobalIndexRangeFromIndex(uint32_t index) const;
144*b7893ccfSSadaf Ebrahimi 
145*b7893ccfSSadaf Ebrahimi     // Helper function to get the next valid binding for a descriptor
146*b7893ccfSSadaf Ebrahimi     uint32_t GetNextValidBinding(const uint32_t) const;
IsPushDescriptor()147*b7893ccfSSadaf Ebrahimi     bool IsPushDescriptor() const { return GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; };
148*b7893ccfSSadaf Ebrahimi 
149*b7893ccfSSadaf Ebrahimi     struct BindingTypeStats {
150*b7893ccfSSadaf Ebrahimi         uint32_t dynamic_buffer_count;
151*b7893ccfSSadaf Ebrahimi         uint32_t non_dynamic_buffer_count;
152*b7893ccfSSadaf Ebrahimi         uint32_t image_sampler_count;
153*b7893ccfSSadaf Ebrahimi     };
GetBindingTypeStats()154*b7893ccfSSadaf Ebrahimi     const BindingTypeStats &GetBindingTypeStats() const { return binding_type_stats_; }
155*b7893ccfSSadaf Ebrahimi 
156*b7893ccfSSadaf Ebrahimi    private:
157*b7893ccfSSadaf Ebrahimi     // Only the first three data members are used for hash and equality checks, the other members are derived from them, and are
158*b7893ccfSSadaf Ebrahimi     // used to speed up the various lookups/queries/validations
159*b7893ccfSSadaf Ebrahimi     VkDescriptorSetLayoutCreateFlags flags_;
160*b7893ccfSSadaf Ebrahimi     std::vector<safe_VkDescriptorSetLayoutBinding> bindings_;
161*b7893ccfSSadaf Ebrahimi     std::vector<VkDescriptorBindingFlagsEXT> binding_flags_;
162*b7893ccfSSadaf Ebrahimi 
163*b7893ccfSSadaf Ebrahimi     // Convenience data structures for rapid lookup of various descriptor set layout properties
164*b7893ccfSSadaf Ebrahimi     std::set<uint32_t> non_empty_bindings_;  // Containing non-emtpy bindings in numerical order
165*b7893ccfSSadaf Ebrahimi     std::unordered_map<uint32_t, uint32_t> binding_to_index_map_;
166*b7893ccfSSadaf Ebrahimi     // The following map allows an non-iterative lookup of a binding from a global index...
167*b7893ccfSSadaf Ebrahimi     std::vector<IndexRange> global_index_range_;  // range is exclusive of .end
168*b7893ccfSSadaf Ebrahimi     // For a given binding map to associated index in the dynamic offset array
169*b7893ccfSSadaf Ebrahimi     std::unordered_map<uint32_t, uint32_t> binding_to_dynamic_array_idx_map_;
170*b7893ccfSSadaf Ebrahimi 
171*b7893ccfSSadaf Ebrahimi     uint32_t binding_count_;     // # of bindings in this layout
172*b7893ccfSSadaf Ebrahimi     uint32_t descriptor_count_;  // total # descriptors in this layout
173*b7893ccfSSadaf Ebrahimi     uint32_t dynamic_descriptor_count_;
174*b7893ccfSSadaf Ebrahimi     BindingTypeStats binding_type_stats_;
175*b7893ccfSSadaf Ebrahimi };
176*b7893ccfSSadaf Ebrahimi 
177*b7893ccfSSadaf Ebrahimi static inline bool operator==(const DescriptorSetLayoutDef &lhs, const DescriptorSetLayoutDef &rhs) {
178*b7893ccfSSadaf Ebrahimi     bool result = (lhs.GetCreateFlags() == rhs.GetCreateFlags()) && (lhs.GetBindings() == rhs.GetBindings()) &&
179*b7893ccfSSadaf Ebrahimi                   (lhs.GetBindingFlags() == rhs.GetBindingFlags());
180*b7893ccfSSadaf Ebrahimi     return result;
181*b7893ccfSSadaf Ebrahimi }
182*b7893ccfSSadaf Ebrahimi 
183*b7893ccfSSadaf Ebrahimi // Canonical dictionary of DSL definitions -- independent of device or handle
184*b7893ccfSSadaf Ebrahimi using DescriptorSetLayoutDict = hash_util::Dictionary<DescriptorSetLayoutDef, hash_util::HasHashMember<DescriptorSetLayoutDef>>;
185*b7893ccfSSadaf Ebrahimi using DescriptorSetLayoutId = DescriptorSetLayoutDict::Id;
186*b7893ccfSSadaf Ebrahimi 
187*b7893ccfSSadaf Ebrahimi class DescriptorSetLayout {
188*b7893ccfSSadaf Ebrahimi    public:
189*b7893ccfSSadaf Ebrahimi     // Constructors and destructor
190*b7893ccfSSadaf Ebrahimi     DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info, const VkDescriptorSetLayout layout);
HasBinding(const uint32_t binding)191*b7893ccfSSadaf Ebrahimi     bool HasBinding(const uint32_t binding) const { return layout_id_->HasBinding(binding); }
192*b7893ccfSSadaf Ebrahimi     // Return true if this layout is compatible with passed in layout from a pipelineLayout,
193*b7893ccfSSadaf Ebrahimi     //   else return false and update error_msg with description of incompatibility
194*b7893ccfSSadaf Ebrahimi     // Return true if this layout is compatible with passed in layout
195*b7893ccfSSadaf Ebrahimi     bool IsCompatible(DescriptorSetLayout const *rh_ds_layout) const;
196*b7893ccfSSadaf Ebrahimi     // Straightforward Get functions
GetDescriptorSetLayout()197*b7893ccfSSadaf Ebrahimi     VkDescriptorSetLayout GetDescriptorSetLayout() const { return layout_; };
IsDestroyed()198*b7893ccfSSadaf Ebrahimi     bool IsDestroyed() const { return layout_destroyed_; }
MarkDestroyed()199*b7893ccfSSadaf Ebrahimi     void MarkDestroyed() { layout_destroyed_ = true; }
GetLayoutDef()200*b7893ccfSSadaf Ebrahimi     const DescriptorSetLayoutDef *GetLayoutDef() const { return layout_id_.get(); }
GetLayoutId()201*b7893ccfSSadaf Ebrahimi     DescriptorSetLayoutId GetLayoutId() const { return layout_id_; }
GetTotalDescriptorCount()202*b7893ccfSSadaf Ebrahimi     uint32_t GetTotalDescriptorCount() const { return layout_id_->GetTotalDescriptorCount(); };
GetDynamicDescriptorCount()203*b7893ccfSSadaf Ebrahimi     uint32_t GetDynamicDescriptorCount() const { return layout_id_->GetDynamicDescriptorCount(); };
GetBindingCount()204*b7893ccfSSadaf Ebrahimi     uint32_t GetBindingCount() const { return layout_id_->GetBindingCount(); };
GetCreateFlags()205*b7893ccfSSadaf Ebrahimi     VkDescriptorSetLayoutCreateFlags GetCreateFlags() const { return layout_id_->GetCreateFlags(); }
206*b7893ccfSSadaf Ebrahimi     bool IsNextBindingConsistent(const uint32_t) const;
GetIndexFromBinding(uint32_t binding)207*b7893ccfSSadaf Ebrahimi     uint32_t GetIndexFromBinding(uint32_t binding) const { return layout_id_->GetIndexFromBinding(binding); }
208*b7893ccfSSadaf Ebrahimi     // Various Get functions that can either be passed a binding#, which will
209*b7893ccfSSadaf Ebrahimi     //  be automatically translated into the appropriate index, or the index# can be passed in directly
GetMaxBinding()210*b7893ccfSSadaf Ebrahimi     uint32_t GetMaxBinding() const { return layout_id_->GetMaxBinding(); }
GetDescriptorSetLayoutBindingPtrFromIndex(const uint32_t index)211*b7893ccfSSadaf Ebrahimi     VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromIndex(const uint32_t index) const {
212*b7893ccfSSadaf Ebrahimi         return layout_id_->GetDescriptorSetLayoutBindingPtrFromIndex(index);
213*b7893ccfSSadaf Ebrahimi     }
GetDescriptorSetLayoutBindingPtrFromBinding(uint32_t binding)214*b7893ccfSSadaf Ebrahimi     VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromBinding(uint32_t binding) const {
215*b7893ccfSSadaf Ebrahimi         return layout_id_->GetDescriptorSetLayoutBindingPtrFromBinding(binding);
216*b7893ccfSSadaf Ebrahimi     }
GetBindings()217*b7893ccfSSadaf Ebrahimi     const std::vector<safe_VkDescriptorSetLayoutBinding> &GetBindings() const { return layout_id_->GetBindings(); }
GetSortedBindingSet()218*b7893ccfSSadaf Ebrahimi     const std::set<uint32_t> &GetSortedBindingSet() const { return layout_id_->GetSortedBindingSet(); }
GetDescriptorCountFromIndex(const uint32_t index)219*b7893ccfSSadaf Ebrahimi     uint32_t GetDescriptorCountFromIndex(const uint32_t index) const { return layout_id_->GetDescriptorCountFromIndex(index); }
GetDescriptorCountFromBinding(const uint32_t binding)220*b7893ccfSSadaf Ebrahimi     uint32_t GetDescriptorCountFromBinding(const uint32_t binding) const {
221*b7893ccfSSadaf Ebrahimi         return layout_id_->GetDescriptorCountFromBinding(binding);
222*b7893ccfSSadaf Ebrahimi     }
GetTypeFromIndex(const uint32_t index)223*b7893ccfSSadaf Ebrahimi     VkDescriptorType GetTypeFromIndex(const uint32_t index) const { return layout_id_->GetTypeFromIndex(index); }
GetTypeFromBinding(const uint32_t binding)224*b7893ccfSSadaf Ebrahimi     VkDescriptorType GetTypeFromBinding(const uint32_t binding) const { return layout_id_->GetTypeFromBinding(binding); }
GetStageFlagsFromIndex(const uint32_t index)225*b7893ccfSSadaf Ebrahimi     VkShaderStageFlags GetStageFlagsFromIndex(const uint32_t index) const { return layout_id_->GetStageFlagsFromIndex(index); }
GetStageFlagsFromBinding(const uint32_t binding)226*b7893ccfSSadaf Ebrahimi     VkShaderStageFlags GetStageFlagsFromBinding(const uint32_t binding) const {
227*b7893ccfSSadaf Ebrahimi         return layout_id_->GetStageFlagsFromBinding(binding);
228*b7893ccfSSadaf Ebrahimi     }
GetDescriptorBindingFlagsFromIndex(const uint32_t index)229*b7893ccfSSadaf Ebrahimi     VkDescriptorBindingFlagsEXT GetDescriptorBindingFlagsFromIndex(const uint32_t index) const {
230*b7893ccfSSadaf Ebrahimi         return layout_id_->GetDescriptorBindingFlagsFromIndex(index);
231*b7893ccfSSadaf Ebrahimi     }
GetDescriptorBindingFlagsFromBinding(const uint32_t binding)232*b7893ccfSSadaf Ebrahimi     VkDescriptorBindingFlagsEXT GetDescriptorBindingFlagsFromBinding(const uint32_t binding) const {
233*b7893ccfSSadaf Ebrahimi         return layout_id_->GetDescriptorBindingFlagsFromBinding(binding);
234*b7893ccfSSadaf Ebrahimi     }
GetImmutableSamplerPtrFromBinding(const uint32_t binding)235*b7893ccfSSadaf Ebrahimi     VkSampler const *GetImmutableSamplerPtrFromBinding(const uint32_t binding) const {
236*b7893ccfSSadaf Ebrahimi         return layout_id_->GetImmutableSamplerPtrFromBinding(binding);
237*b7893ccfSSadaf Ebrahimi     }
GetImmutableSamplerPtrFromIndex(const uint32_t index)238*b7893ccfSSadaf Ebrahimi     VkSampler const *GetImmutableSamplerPtrFromIndex(const uint32_t index) const {
239*b7893ccfSSadaf Ebrahimi         return layout_id_->GetImmutableSamplerPtrFromIndex(index);
240*b7893ccfSSadaf Ebrahimi     }
241*b7893ccfSSadaf Ebrahimi     // For a given binding and array index, return the corresponding index into the dynamic offset array
GetDynamicOffsetIndexFromBinding(uint32_t binding)242*b7893ccfSSadaf Ebrahimi     int32_t GetDynamicOffsetIndexFromBinding(uint32_t binding) const {
243*b7893ccfSSadaf Ebrahimi         return layout_id_->GetDynamicOffsetIndexFromBinding(binding);
244*b7893ccfSSadaf Ebrahimi     }
245*b7893ccfSSadaf Ebrahimi     // For a particular binding, get the global index range
246*b7893ccfSSadaf Ebrahimi     //  This call should be guarded by a call to "HasBinding(binding)" to verify that the given binding exists
GetGlobalIndexRangeFromBinding(const uint32_t binding)247*b7893ccfSSadaf Ebrahimi     const IndexRange &GetGlobalIndexRangeFromBinding(const uint32_t binding) const {
248*b7893ccfSSadaf Ebrahimi         return layout_id_->GetGlobalIndexRangeFromBinding(binding);
249*b7893ccfSSadaf Ebrahimi     }
GetGlobalIndexRangeFromIndex(uint32_t index)250*b7893ccfSSadaf Ebrahimi     const IndexRange &GetGlobalIndexRangeFromIndex(uint32_t index) const { return layout_id_->GetGlobalIndexRangeFromIndex(index); }
251*b7893ccfSSadaf Ebrahimi 
252*b7893ccfSSadaf Ebrahimi     // Helper function to get the next valid binding for a descriptor
GetNextValidBinding(const uint32_t binding)253*b7893ccfSSadaf Ebrahimi     uint32_t GetNextValidBinding(const uint32_t binding) const { return layout_id_->GetNextValidBinding(binding); }
IsPushDescriptor()254*b7893ccfSSadaf Ebrahimi     bool IsPushDescriptor() const { return layout_id_->IsPushDescriptor(); }
IsVariableDescriptorCountFromIndex(uint32_t index)255*b7893ccfSSadaf Ebrahimi     bool IsVariableDescriptorCountFromIndex(uint32_t index) const {
256*b7893ccfSSadaf Ebrahimi         return !!(GetDescriptorBindingFlagsFromIndex(index) & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT);
257*b7893ccfSSadaf Ebrahimi     }
IsVariableDescriptorCount(uint32_t binding)258*b7893ccfSSadaf Ebrahimi     bool IsVariableDescriptorCount(uint32_t binding) const {
259*b7893ccfSSadaf Ebrahimi         return IsVariableDescriptorCountFromIndex(GetIndexFromBinding(binding));
260*b7893ccfSSadaf Ebrahimi     }
261*b7893ccfSSadaf Ebrahimi 
262*b7893ccfSSadaf Ebrahimi     using BindingTypeStats = DescriptorSetLayoutDef::BindingTypeStats;
GetBindingTypeStats()263*b7893ccfSSadaf Ebrahimi     const BindingTypeStats &GetBindingTypeStats() const { return layout_id_->GetBindingTypeStats(); }
264*b7893ccfSSadaf Ebrahimi 
265*b7893ccfSSadaf Ebrahimi     // Binding Iterator
266*b7893ccfSSadaf Ebrahimi     class ConstBindingIterator {
267*b7893ccfSSadaf Ebrahimi        public:
268*b7893ccfSSadaf Ebrahimi         ConstBindingIterator() = delete;
269*b7893ccfSSadaf Ebrahimi         ConstBindingIterator(const ConstBindingIterator &other) = default;
270*b7893ccfSSadaf Ebrahimi         ConstBindingIterator &operator=(const ConstBindingIterator &rhs) = default;
271*b7893ccfSSadaf Ebrahimi 
ConstBindingIterator(const DescriptorSetLayout * layout)272*b7893ccfSSadaf Ebrahimi         ConstBindingIterator(const DescriptorSetLayout *layout) : layout_(layout), index_(0) { assert(layout); }
ConstBindingIterator(const DescriptorSetLayout * layout,uint32_t binding)273*b7893ccfSSadaf Ebrahimi         ConstBindingIterator(const DescriptorSetLayout *layout, uint32_t binding) : ConstBindingIterator(layout) {
274*b7893ccfSSadaf Ebrahimi             index_ = layout->GetIndexFromBinding(binding);
275*b7893ccfSSadaf Ebrahimi         }
276*b7893ccfSSadaf Ebrahimi 
GetDescriptorSetLayoutBindingPtr()277*b7893ccfSSadaf Ebrahimi         VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtr() const {
278*b7893ccfSSadaf Ebrahimi             return layout_->GetDescriptorSetLayoutBindingPtrFromIndex(index_);
279*b7893ccfSSadaf Ebrahimi         }
GetDescriptorCount()280*b7893ccfSSadaf Ebrahimi         uint32_t GetDescriptorCount() const { return layout_->GetDescriptorCountFromIndex(index_); }
GetType()281*b7893ccfSSadaf Ebrahimi         VkDescriptorType GetType() const { return layout_->GetTypeFromIndex(index_); }
GetStageFlags()282*b7893ccfSSadaf Ebrahimi         VkShaderStageFlags GetStageFlags() const { return layout_->GetStageFlagsFromIndex(index_); }
283*b7893ccfSSadaf Ebrahimi 
GetDescriptorBindingFlags()284*b7893ccfSSadaf Ebrahimi         VkDescriptorBindingFlagsEXT GetDescriptorBindingFlags() const {
285*b7893ccfSSadaf Ebrahimi             return layout_->GetDescriptorBindingFlagsFromIndex(index_);
286*b7893ccfSSadaf Ebrahimi         }
287*b7893ccfSSadaf Ebrahimi 
IsVariableDescriptorCount()288*b7893ccfSSadaf Ebrahimi         bool IsVariableDescriptorCount() const { return layout_->IsVariableDescriptorCountFromIndex(index_); }
289*b7893ccfSSadaf Ebrahimi 
GetImmutableSamplerPtr()290*b7893ccfSSadaf Ebrahimi         VkSampler const *GetImmutableSamplerPtr() const { return layout_->GetImmutableSamplerPtrFromIndex(index_); }
GetGlobalIndexRange()291*b7893ccfSSadaf Ebrahimi         const IndexRange &GetGlobalIndexRange() const { return layout_->GetGlobalIndexRangeFromIndex(index_); }
AtEnd()292*b7893ccfSSadaf Ebrahimi         bool AtEnd() const { return index_ == layout_->GetBindingCount(); }
293*b7893ccfSSadaf Ebrahimi 
294*b7893ccfSSadaf Ebrahimi         // Return index into dynamic offset array for given binding
GetDynamicOffsetIndex()295*b7893ccfSSadaf Ebrahimi         int32_t GetDynamicOffsetIndex() const {
296*b7893ccfSSadaf Ebrahimi             return layout_->GetDynamicOffsetIndexFromBinding(Binding());  //  There is only binding mapped access in layout_
297*b7893ccfSSadaf Ebrahimi         }
298*b7893ccfSSadaf Ebrahimi 
299*b7893ccfSSadaf Ebrahimi         bool operator==(const ConstBindingIterator &rhs) { return (index_ = rhs.index_) && (layout_ == rhs.layout_); }
300*b7893ccfSSadaf Ebrahimi 
301*b7893ccfSSadaf Ebrahimi         ConstBindingIterator &operator++() {
302*b7893ccfSSadaf Ebrahimi             if (!AtEnd()) {
303*b7893ccfSSadaf Ebrahimi                 index_++;
304*b7893ccfSSadaf Ebrahimi             }
305*b7893ccfSSadaf Ebrahimi             return *this;
306*b7893ccfSSadaf Ebrahimi         }
307*b7893ccfSSadaf Ebrahimi 
IsConsistent(const ConstBindingIterator & other)308*b7893ccfSSadaf Ebrahimi         bool IsConsistent(const ConstBindingIterator &other) const {
309*b7893ccfSSadaf Ebrahimi             if (AtEnd() || other.AtEnd()) {
310*b7893ccfSSadaf Ebrahimi                 return false;
311*b7893ccfSSadaf Ebrahimi             }
312*b7893ccfSSadaf Ebrahimi             const auto *binding_ci = GetDescriptorSetLayoutBindingPtr();
313*b7893ccfSSadaf Ebrahimi             const auto *other_binding_ci = other.GetDescriptorSetLayoutBindingPtr();
314*b7893ccfSSadaf Ebrahimi             assert((binding_ci != nullptr) && (other_binding_ci != nullptr));
315*b7893ccfSSadaf Ebrahimi 
316*b7893ccfSSadaf Ebrahimi             if ((binding_ci->descriptorType != other_binding_ci->descriptorType) ||
317*b7893ccfSSadaf Ebrahimi                 (binding_ci->stageFlags != other_binding_ci->stageFlags) ||
318*b7893ccfSSadaf Ebrahimi                 (!hash_util::similar_for_nullity(binding_ci->pImmutableSamplers, other_binding_ci->pImmutableSamplers)) ||
319*b7893ccfSSadaf Ebrahimi                 (GetDescriptorBindingFlags() != other.GetDescriptorBindingFlags())) {
320*b7893ccfSSadaf Ebrahimi                 return false;
321*b7893ccfSSadaf Ebrahimi             }
322*b7893ccfSSadaf Ebrahimi             return true;
323*b7893ccfSSadaf Ebrahimi         }
324*b7893ccfSSadaf Ebrahimi 
Layout()325*b7893ccfSSadaf Ebrahimi         const DescriptorSetLayout *Layout() const { return layout_; }
Binding()326*b7893ccfSSadaf Ebrahimi         uint32_t Binding() const { return layout_->GetBindings()[index_].binding; }
Next()327*b7893ccfSSadaf Ebrahimi         ConstBindingIterator Next() {
328*b7893ccfSSadaf Ebrahimi             ConstBindingIterator next(*this);
329*b7893ccfSSadaf Ebrahimi             ++next;
330*b7893ccfSSadaf Ebrahimi             return next;
331*b7893ccfSSadaf Ebrahimi         }
332*b7893ccfSSadaf Ebrahimi 
333*b7893ccfSSadaf Ebrahimi        private:
334*b7893ccfSSadaf Ebrahimi         const DescriptorSetLayout *layout_;
335*b7893ccfSSadaf Ebrahimi         uint32_t index_;
336*b7893ccfSSadaf Ebrahimi     };
end()337*b7893ccfSSadaf Ebrahimi     ConstBindingIterator end() const { return ConstBindingIterator(this, GetBindingCount()); }
338*b7893ccfSSadaf Ebrahimi 
339*b7893ccfSSadaf Ebrahimi    private:
340*b7893ccfSSadaf Ebrahimi     VkDescriptorSetLayout layout_;
341*b7893ccfSSadaf Ebrahimi     bool layout_destroyed_;
342*b7893ccfSSadaf Ebrahimi     DescriptorSetLayoutId layout_id_;
343*b7893ccfSSadaf Ebrahimi };
344*b7893ccfSSadaf Ebrahimi 
345*b7893ccfSSadaf Ebrahimi /*
346*b7893ccfSSadaf Ebrahimi  * Descriptor classes
347*b7893ccfSSadaf Ebrahimi  *  Descriptor is an abstract base class from which 5 separate descriptor types are derived.
348*b7893ccfSSadaf Ebrahimi  *   This allows the WriteUpdate() and CopyUpdate() operations to be specialized per
349*b7893ccfSSadaf Ebrahimi  *   descriptor type, but all descriptors in a set can be accessed via the common Descriptor*.
350*b7893ccfSSadaf Ebrahimi  */
351*b7893ccfSSadaf Ebrahimi 
352*b7893ccfSSadaf Ebrahimi // Slightly broader than type, each c++ "class" will has a corresponding "DescriptorClass"
353*b7893ccfSSadaf Ebrahimi enum DescriptorClass { PlainSampler, ImageSampler, Image, TexelBuffer, GeneralBuffer, InlineUniform, AccelerationStructure };
354*b7893ccfSSadaf Ebrahimi 
355*b7893ccfSSadaf Ebrahimi class Descriptor {
356*b7893ccfSSadaf Ebrahimi    public:
~Descriptor()357*b7893ccfSSadaf Ebrahimi     virtual ~Descriptor(){};
358*b7893ccfSSadaf Ebrahimi     virtual void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) = 0;
359*b7893ccfSSadaf Ebrahimi     virtual void CopyUpdate(const Descriptor *) = 0;
360*b7893ccfSSadaf Ebrahimi     // Create binding between resources of this descriptor and given cb_node
361*b7893ccfSSadaf Ebrahimi     virtual void UpdateDrawState(ValidationStateTracker *, CMD_BUFFER_STATE *) = 0;
GetClass()362*b7893ccfSSadaf Ebrahimi     virtual DescriptorClass GetClass() const { return descriptor_class; };
363*b7893ccfSSadaf Ebrahimi     // Special fast-path check for SamplerDescriptors that are immutable
IsImmutableSampler()364*b7893ccfSSadaf Ebrahimi     virtual bool IsImmutableSampler() const { return false; };
365*b7893ccfSSadaf Ebrahimi     // Check for dynamic descriptor type
IsDynamic()366*b7893ccfSSadaf Ebrahimi     virtual bool IsDynamic() const { return false; };
367*b7893ccfSSadaf Ebrahimi     // Check for storage descriptor type
IsStorage()368*b7893ccfSSadaf Ebrahimi     virtual bool IsStorage() const { return false; };
369*b7893ccfSSadaf Ebrahimi     bool updated;  // Has descriptor been updated?
370*b7893ccfSSadaf Ebrahimi     DescriptorClass descriptor_class;
371*b7893ccfSSadaf Ebrahimi };
372*b7893ccfSSadaf Ebrahimi 
373*b7893ccfSSadaf Ebrahimi // Return true if this layout is compatible with passed in layout from a pipelineLayout,
374*b7893ccfSSadaf Ebrahimi //   else return false and update error_msg with description of incompatibility
375*b7893ccfSSadaf Ebrahimi bool VerifySetLayoutCompatibility(DescriptorSetLayout const *lh_ds_layout, DescriptorSetLayout const *rh_ds_layout,
376*b7893ccfSSadaf Ebrahimi                                   std::string *error_msg);
377*b7893ccfSSadaf Ebrahimi bool ValidateDescriptorSetLayoutCreateInfo(const debug_report_data *report_data, const VkDescriptorSetLayoutCreateInfo *create_info,
378*b7893ccfSSadaf Ebrahimi                                            const bool push_descriptor_ext, const uint32_t max_push_descriptors,
379*b7893ccfSSadaf Ebrahimi                                            const bool descriptor_indexing_ext,
380*b7893ccfSSadaf Ebrahimi                                            const VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing_features,
381*b7893ccfSSadaf Ebrahimi                                            const VkPhysicalDeviceInlineUniformBlockFeaturesEXT *inline_uniform_block_features,
382*b7893ccfSSadaf Ebrahimi                                            const VkPhysicalDeviceInlineUniformBlockPropertiesEXT *inline_uniform_block_props,
383*b7893ccfSSadaf Ebrahimi                                            const DeviceExtensions *device_extensions);
384*b7893ccfSSadaf Ebrahimi 
385*b7893ccfSSadaf Ebrahimi class SamplerDescriptor : public Descriptor {
386*b7893ccfSSadaf Ebrahimi    public:
387*b7893ccfSSadaf Ebrahimi     SamplerDescriptor(const VkSampler *);
388*b7893ccfSSadaf Ebrahimi     void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
389*b7893ccfSSadaf Ebrahimi     void CopyUpdate(const Descriptor *) override;
390*b7893ccfSSadaf Ebrahimi     void UpdateDrawState(ValidationStateTracker *, CMD_BUFFER_STATE *) override;
IsImmutableSampler()391*b7893ccfSSadaf Ebrahimi     virtual bool IsImmutableSampler() const override { return immutable_; };
GetSampler()392*b7893ccfSSadaf Ebrahimi     VkSampler GetSampler() const { return sampler_; }
393*b7893ccfSSadaf Ebrahimi 
394*b7893ccfSSadaf Ebrahimi    private:
395*b7893ccfSSadaf Ebrahimi     VkSampler sampler_;
396*b7893ccfSSadaf Ebrahimi     bool immutable_;
397*b7893ccfSSadaf Ebrahimi };
398*b7893ccfSSadaf Ebrahimi 
399*b7893ccfSSadaf Ebrahimi class ImageSamplerDescriptor : public Descriptor {
400*b7893ccfSSadaf Ebrahimi    public:
401*b7893ccfSSadaf Ebrahimi     ImageSamplerDescriptor(const VkSampler *);
402*b7893ccfSSadaf Ebrahimi     void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
403*b7893ccfSSadaf Ebrahimi     void CopyUpdate(const Descriptor *) override;
404*b7893ccfSSadaf Ebrahimi     void UpdateDrawState(ValidationStateTracker *, CMD_BUFFER_STATE *) override;
IsImmutableSampler()405*b7893ccfSSadaf Ebrahimi     virtual bool IsImmutableSampler() const override { return immutable_; };
GetSampler()406*b7893ccfSSadaf Ebrahimi     VkSampler GetSampler() const { return sampler_; }
GetImageView()407*b7893ccfSSadaf Ebrahimi     VkImageView GetImageView() const { return image_view_; }
GetImageLayout()408*b7893ccfSSadaf Ebrahimi     VkImageLayout GetImageLayout() const { return image_layout_; }
409*b7893ccfSSadaf Ebrahimi 
410*b7893ccfSSadaf Ebrahimi    private:
411*b7893ccfSSadaf Ebrahimi     VkSampler sampler_;
412*b7893ccfSSadaf Ebrahimi     bool immutable_;
413*b7893ccfSSadaf Ebrahimi     VkImageView image_view_;
414*b7893ccfSSadaf Ebrahimi     VkImageLayout image_layout_;
415*b7893ccfSSadaf Ebrahimi };
416*b7893ccfSSadaf Ebrahimi 
417*b7893ccfSSadaf Ebrahimi class ImageDescriptor : public Descriptor {
418*b7893ccfSSadaf Ebrahimi    public:
419*b7893ccfSSadaf Ebrahimi     ImageDescriptor(const VkDescriptorType);
420*b7893ccfSSadaf Ebrahimi     void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
421*b7893ccfSSadaf Ebrahimi     void CopyUpdate(const Descriptor *) override;
422*b7893ccfSSadaf Ebrahimi     void UpdateDrawState(ValidationStateTracker *, CMD_BUFFER_STATE *) override;
IsStorage()423*b7893ccfSSadaf Ebrahimi     virtual bool IsStorage() const override { return storage_; }
GetImageView()424*b7893ccfSSadaf Ebrahimi     VkImageView GetImageView() const { return image_view_; }
GetImageLayout()425*b7893ccfSSadaf Ebrahimi     VkImageLayout GetImageLayout() const { return image_layout_; }
426*b7893ccfSSadaf Ebrahimi 
427*b7893ccfSSadaf Ebrahimi    private:
428*b7893ccfSSadaf Ebrahimi     bool storage_;
429*b7893ccfSSadaf Ebrahimi     VkImageView image_view_;
430*b7893ccfSSadaf Ebrahimi     VkImageLayout image_layout_;
431*b7893ccfSSadaf Ebrahimi };
432*b7893ccfSSadaf Ebrahimi 
433*b7893ccfSSadaf Ebrahimi class TexelDescriptor : public Descriptor {
434*b7893ccfSSadaf Ebrahimi    public:
435*b7893ccfSSadaf Ebrahimi     TexelDescriptor(const VkDescriptorType);
436*b7893ccfSSadaf Ebrahimi     void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
437*b7893ccfSSadaf Ebrahimi     void CopyUpdate(const Descriptor *) override;
438*b7893ccfSSadaf Ebrahimi     void UpdateDrawState(ValidationStateTracker *, CMD_BUFFER_STATE *) override;
IsStorage()439*b7893ccfSSadaf Ebrahimi     virtual bool IsStorage() const override { return storage_; }
GetBufferView()440*b7893ccfSSadaf Ebrahimi     VkBufferView GetBufferView() const { return buffer_view_; }
441*b7893ccfSSadaf Ebrahimi 
442*b7893ccfSSadaf Ebrahimi    private:
443*b7893ccfSSadaf Ebrahimi     VkBufferView buffer_view_;
444*b7893ccfSSadaf Ebrahimi     bool storage_;
445*b7893ccfSSadaf Ebrahimi };
446*b7893ccfSSadaf Ebrahimi 
447*b7893ccfSSadaf Ebrahimi class BufferDescriptor : public Descriptor {
448*b7893ccfSSadaf Ebrahimi    public:
449*b7893ccfSSadaf Ebrahimi     BufferDescriptor(const VkDescriptorType);
450*b7893ccfSSadaf Ebrahimi     void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
451*b7893ccfSSadaf Ebrahimi     void CopyUpdate(const Descriptor *) override;
452*b7893ccfSSadaf Ebrahimi     void UpdateDrawState(ValidationStateTracker *, CMD_BUFFER_STATE *) override;
IsDynamic()453*b7893ccfSSadaf Ebrahimi     virtual bool IsDynamic() const override { return dynamic_; }
IsStorage()454*b7893ccfSSadaf Ebrahimi     virtual bool IsStorage() const override { return storage_; }
GetBuffer()455*b7893ccfSSadaf Ebrahimi     VkBuffer GetBuffer() const { return buffer_; }
GetOffset()456*b7893ccfSSadaf Ebrahimi     VkDeviceSize GetOffset() const { return offset_; }
GetRange()457*b7893ccfSSadaf Ebrahimi     VkDeviceSize GetRange() const { return range_; }
458*b7893ccfSSadaf Ebrahimi 
459*b7893ccfSSadaf Ebrahimi    private:
460*b7893ccfSSadaf Ebrahimi     bool storage_;
461*b7893ccfSSadaf Ebrahimi     bool dynamic_;
462*b7893ccfSSadaf Ebrahimi     VkBuffer buffer_;
463*b7893ccfSSadaf Ebrahimi     VkDeviceSize offset_;
464*b7893ccfSSadaf Ebrahimi     VkDeviceSize range_;
465*b7893ccfSSadaf Ebrahimi };
466*b7893ccfSSadaf Ebrahimi 
467*b7893ccfSSadaf Ebrahimi class InlineUniformDescriptor : public Descriptor {
468*b7893ccfSSadaf Ebrahimi    public:
InlineUniformDescriptor(const VkDescriptorType)469*b7893ccfSSadaf Ebrahimi     InlineUniformDescriptor(const VkDescriptorType) {
470*b7893ccfSSadaf Ebrahimi         updated = false;
471*b7893ccfSSadaf Ebrahimi         descriptor_class = InlineUniform;
472*b7893ccfSSadaf Ebrahimi     }
WriteUpdate(const VkWriteDescriptorSet *,const uint32_t)473*b7893ccfSSadaf Ebrahimi     void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override { updated = true; }
CopyUpdate(const Descriptor *)474*b7893ccfSSadaf Ebrahimi     void CopyUpdate(const Descriptor *) override { updated = true; }
UpdateDrawState(ValidationStateTracker *,CMD_BUFFER_STATE *)475*b7893ccfSSadaf Ebrahimi     void UpdateDrawState(ValidationStateTracker *, CMD_BUFFER_STATE *) override {}
476*b7893ccfSSadaf Ebrahimi };
477*b7893ccfSSadaf Ebrahimi 
478*b7893ccfSSadaf Ebrahimi class AccelerationStructureDescriptor : public Descriptor {
479*b7893ccfSSadaf Ebrahimi    public:
AccelerationStructureDescriptor(const VkDescriptorType)480*b7893ccfSSadaf Ebrahimi     AccelerationStructureDescriptor(const VkDescriptorType) {
481*b7893ccfSSadaf Ebrahimi         updated = false;
482*b7893ccfSSadaf Ebrahimi         descriptor_class = AccelerationStructure;
483*b7893ccfSSadaf Ebrahimi     }
WriteUpdate(const VkWriteDescriptorSet *,const uint32_t)484*b7893ccfSSadaf Ebrahimi     void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override { updated = true; }
CopyUpdate(const Descriptor *)485*b7893ccfSSadaf Ebrahimi     void CopyUpdate(const Descriptor *) override { updated = true; }
UpdateDrawState(ValidationStateTracker *,CMD_BUFFER_STATE *)486*b7893ccfSSadaf Ebrahimi     void UpdateDrawState(ValidationStateTracker *, CMD_BUFFER_STATE *) override {}
487*b7893ccfSSadaf Ebrahimi };
488*b7893ccfSSadaf Ebrahimi 
489*b7893ccfSSadaf Ebrahimi // Structs to contain common elements that need to be shared between Validate* and Perform* calls below
490*b7893ccfSSadaf Ebrahimi struct AllocateDescriptorSetsData {
491*b7893ccfSSadaf Ebrahimi     std::map<uint32_t, uint32_t> required_descriptors_by_type;
492*b7893ccfSSadaf Ebrahimi     std::vector<std::shared_ptr<DescriptorSetLayout const>> layout_nodes;
493*b7893ccfSSadaf Ebrahimi     AllocateDescriptorSetsData(uint32_t);
494*b7893ccfSSadaf Ebrahimi };
495*b7893ccfSSadaf Ebrahimi // Helper functions for descriptor set functions that cross multiple sets
496*b7893ccfSSadaf Ebrahimi // "Validate" will make sure an update is ok without actually performing it
497*b7893ccfSSadaf Ebrahimi bool ValidateUpdateDescriptorSets(const debug_report_data *, const CoreChecks *, uint32_t, const VkWriteDescriptorSet *, uint32_t,
498*b7893ccfSSadaf Ebrahimi                                   const VkCopyDescriptorSet *, const char *func_name);
499*b7893ccfSSadaf Ebrahimi // "Perform" does the update with the assumption that ValidateUpdateDescriptorSets() has passed for the given update
500*b7893ccfSSadaf Ebrahimi void PerformUpdateDescriptorSets(ValidationStateTracker *, uint32_t, const VkWriteDescriptorSet *, uint32_t,
501*b7893ccfSSadaf Ebrahimi                                  const VkCopyDescriptorSet *);
502*b7893ccfSSadaf Ebrahimi 
503*b7893ccfSSadaf Ebrahimi // Core Validation specific validation checks using DescriptorSet and DescriptorSetLayoutAccessors
504*b7893ccfSSadaf Ebrahimi // TODO: migrate out of descriptor_set.cpp/h
505*b7893ccfSSadaf Ebrahimi // For a particular binding starting at offset and having update_count descriptors
506*b7893ccfSSadaf Ebrahimi // updated, verify that for any binding boundaries crossed, the update is consistent
507*b7893ccfSSadaf Ebrahimi bool VerifyUpdateConsistency(DescriptorSetLayout::ConstBindingIterator current_binding, uint32_t offset, uint32_t update_count,
508*b7893ccfSSadaf Ebrahimi                              const char *type, const VkDescriptorSet set, std::string *error_msg);
509*b7893ccfSSadaf Ebrahimi 
510*b7893ccfSSadaf Ebrahimi // Validate buffer descriptor update info
511*b7893ccfSSadaf Ebrahimi bool ValidateBufferUsage(BUFFER_STATE const *buffer_node, VkDescriptorType type, std::string *error_code, std::string *error_msg);
512*b7893ccfSSadaf Ebrahimi 
513*b7893ccfSSadaf Ebrahimi // Helper class to encapsulate the descriptor update template decoding logic
514*b7893ccfSSadaf Ebrahimi struct DecodedTemplateUpdate {
515*b7893ccfSSadaf Ebrahimi     std::vector<VkWriteDescriptorSet> desc_writes;
516*b7893ccfSSadaf Ebrahimi     std::vector<VkWriteDescriptorSetInlineUniformBlockEXT> inline_infos;
517*b7893ccfSSadaf Ebrahimi     DecodedTemplateUpdate(const ValidationStateTracker *device_data, VkDescriptorSet descriptorSet,
518*b7893ccfSSadaf Ebrahimi                           const TEMPLATE_STATE *template_state, const void *pData,
519*b7893ccfSSadaf Ebrahimi                           VkDescriptorSetLayout push_layout = VK_NULL_HANDLE);
520*b7893ccfSSadaf Ebrahimi };
521*b7893ccfSSadaf Ebrahimi 
522*b7893ccfSSadaf Ebrahimi /*
523*b7893ccfSSadaf Ebrahimi  * DescriptorSet class
524*b7893ccfSSadaf Ebrahimi  *
525*b7893ccfSSadaf Ebrahimi  * Overview - This class encapsulates the Vulkan VkDescriptorSet data (set).
526*b7893ccfSSadaf Ebrahimi  *   A set has an underlying layout which defines the bindings in the set and the
527*b7893ccfSSadaf Ebrahimi  *   types and numbers of descriptors in each descriptor slot. Most of the layout
528*b7893ccfSSadaf Ebrahimi  *   interfaces are exposed through identically-named functions in the set class.
529*b7893ccfSSadaf Ebrahimi  *   Please refer to the DescriptorSetLayout comment above for a description of
530*b7893ccfSSadaf Ebrahimi  *   index, binding, and global index.
531*b7893ccfSSadaf Ebrahimi  *
532*b7893ccfSSadaf Ebrahimi  * At construction a vector of Descriptor* is created with types corresponding to the
533*b7893ccfSSadaf Ebrahimi  *   layout. The primary operation performed on the descriptors is to update them
534*b7893ccfSSadaf Ebrahimi  *   via write or copy updates, and validate that the update contents are correct.
535*b7893ccfSSadaf Ebrahimi  *   In order to validate update contents, the DescriptorSet stores a bunch of ptrs
536*b7893ccfSSadaf Ebrahimi  *   to data maps where various Vulkan objects can be looked up. The management of
537*b7893ccfSSadaf Ebrahimi  *   those maps is performed externally. The set class relies on their contents to
538*b7893ccfSSadaf Ebrahimi  *   be correct at the time of update.
539*b7893ccfSSadaf Ebrahimi  */
540*b7893ccfSSadaf Ebrahimi class DescriptorSet : public BASE_NODE {
541*b7893ccfSSadaf Ebrahimi    public:
542*b7893ccfSSadaf Ebrahimi     using StateTracker = ValidationStateTracker;
543*b7893ccfSSadaf Ebrahimi     DescriptorSet(const VkDescriptorSet, const VkDescriptorPool, const std::shared_ptr<DescriptorSetLayout const> &,
544*b7893ccfSSadaf Ebrahimi                   uint32_t variable_count, StateTracker *);
545*b7893ccfSSadaf Ebrahimi     ~DescriptorSet();
546*b7893ccfSSadaf Ebrahimi     // A number of common Get* functions that return data based on layout from which this set was created
GetTotalDescriptorCount()547*b7893ccfSSadaf Ebrahimi     uint32_t GetTotalDescriptorCount() const { return p_layout_->GetTotalDescriptorCount(); };
GetDynamicDescriptorCount()548*b7893ccfSSadaf Ebrahimi     uint32_t GetDynamicDescriptorCount() const { return p_layout_->GetDynamicDescriptorCount(); };
GetBindingCount()549*b7893ccfSSadaf Ebrahimi     uint32_t GetBindingCount() const { return p_layout_->GetBindingCount(); };
GetTypeFromIndex(const uint32_t index)550*b7893ccfSSadaf Ebrahimi     VkDescriptorType GetTypeFromIndex(const uint32_t index) const { return p_layout_->GetTypeFromIndex(index); };
GetTypeFromBinding(const uint32_t binding)551*b7893ccfSSadaf Ebrahimi     VkDescriptorType GetTypeFromBinding(const uint32_t binding) const { return p_layout_->GetTypeFromBinding(binding); };
GetDescriptorCountFromIndex(const uint32_t index)552*b7893ccfSSadaf Ebrahimi     uint32_t GetDescriptorCountFromIndex(const uint32_t index) const { return p_layout_->GetDescriptorCountFromIndex(index); };
GetDescriptorCountFromBinding(const uint32_t binding)553*b7893ccfSSadaf Ebrahimi     uint32_t GetDescriptorCountFromBinding(const uint32_t binding) const {
554*b7893ccfSSadaf Ebrahimi         return p_layout_->GetDescriptorCountFromBinding(binding);
555*b7893ccfSSadaf Ebrahimi     };
556*b7893ccfSSadaf Ebrahimi     // Return index into dynamic offset array for given binding
GetDynamicOffsetIndexFromBinding(uint32_t binding)557*b7893ccfSSadaf Ebrahimi     int32_t GetDynamicOffsetIndexFromBinding(uint32_t binding) const {
558*b7893ccfSSadaf Ebrahimi         return p_layout_->GetDynamicOffsetIndexFromBinding(binding);
559*b7893ccfSSadaf Ebrahimi     }
560*b7893ccfSSadaf Ebrahimi     // Return true if given binding is present in this set
HasBinding(const uint32_t binding)561*b7893ccfSSadaf Ebrahimi     bool HasBinding(const uint32_t binding) const { return p_layout_->HasBinding(binding); };
562*b7893ccfSSadaf Ebrahimi 
563*b7893ccfSSadaf Ebrahimi     std::string StringifySetAndLayout() const;
564*b7893ccfSSadaf Ebrahimi 
565*b7893ccfSSadaf Ebrahimi     // Perform a push update whose contents were just validated using ValidatePushDescriptorsUpdate
566*b7893ccfSSadaf Ebrahimi     void PerformPushDescriptorsUpdate(uint32_t write_count, const VkWriteDescriptorSet *p_wds);
567*b7893ccfSSadaf Ebrahimi     // Perform a WriteUpdate whose contents were just validated using ValidateWriteUpdate
568*b7893ccfSSadaf Ebrahimi     void PerformWriteUpdate(const VkWriteDescriptorSet *);
569*b7893ccfSSadaf Ebrahimi     // Perform a CopyUpdate whose contents were just validated using ValidateCopyUpdate
570*b7893ccfSSadaf Ebrahimi     void PerformCopyUpdate(const VkCopyDescriptorSet *, const DescriptorSet *);
571*b7893ccfSSadaf Ebrahimi 
GetLayout()572*b7893ccfSSadaf Ebrahimi     const std::shared_ptr<DescriptorSetLayout const> GetLayout() const { return p_layout_; };
GetDescriptorSetLayout()573*b7893ccfSSadaf Ebrahimi     VkDescriptorSetLayout GetDescriptorSetLayout() const { return p_layout_->GetDescriptorSetLayout(); }
GetSet()574*b7893ccfSSadaf Ebrahimi     VkDescriptorSet GetSet() const { return set_; };
575*b7893ccfSSadaf Ebrahimi     // Return unordered_set of all command buffers that this set is bound to
GetBoundCmdBuffers()576*b7893ccfSSadaf Ebrahimi     std::unordered_set<CMD_BUFFER_STATE *> GetBoundCmdBuffers() const { return cb_bindings; }
577*b7893ccfSSadaf Ebrahimi     // Bind given cmd_buffer to this descriptor set and
578*b7893ccfSSadaf Ebrahimi     // update CB image layout map with image/imagesampler descriptor image layouts
579*b7893ccfSSadaf Ebrahimi     void UpdateDrawState(ValidationStateTracker *, CMD_BUFFER_STATE *, const std::map<uint32_t, descriptor_req> &);
580*b7893ccfSSadaf Ebrahimi 
581*b7893ccfSSadaf Ebrahimi     // Track work that has been bound or validated to avoid duplicate work, important when large descriptor arrays
582*b7893ccfSSadaf Ebrahimi     // are present
583*b7893ccfSSadaf Ebrahimi     typedef std::unordered_set<uint32_t> TrackedBindings;
584*b7893ccfSSadaf Ebrahimi     static void FilterOneBindingReq(const BindingReqMap::value_type &binding_req_pair, BindingReqMap *out_req,
585*b7893ccfSSadaf Ebrahimi                                     const TrackedBindings &set, uint32_t limit);
586*b7893ccfSSadaf Ebrahimi     void FilterBindingReqs(const CMD_BUFFER_STATE &, const PIPELINE_STATE &, const BindingReqMap &in_req,
587*b7893ccfSSadaf Ebrahimi                            BindingReqMap *out_req) const;
588*b7893ccfSSadaf Ebrahimi     void UpdateValidationCache(const CMD_BUFFER_STATE &cb_state, const PIPELINE_STATE &pipeline,
589*b7893ccfSSadaf Ebrahimi                                const BindingReqMap &updated_bindings);
ClearCachedDynamicDescriptorValidation(CMD_BUFFER_STATE * cb_state)590*b7893ccfSSadaf Ebrahimi     void ClearCachedDynamicDescriptorValidation(CMD_BUFFER_STATE *cb_state) {
591*b7893ccfSSadaf Ebrahimi         cached_validation_[cb_state].dynamic_buffers.clear();
592*b7893ccfSSadaf Ebrahimi     }
ClearCachedValidation(CMD_BUFFER_STATE * cb_state)593*b7893ccfSSadaf Ebrahimi     void ClearCachedValidation(CMD_BUFFER_STATE *cb_state) { cached_validation_.erase(cb_state); }
594*b7893ccfSSadaf Ebrahimi     // If given cmd_buffer is in the cb_bindings set, remove it
RemoveBoundCommandBuffer(CMD_BUFFER_STATE * cb_node)595*b7893ccfSSadaf Ebrahimi     void RemoveBoundCommandBuffer(CMD_BUFFER_STATE *cb_node) {
596*b7893ccfSSadaf Ebrahimi         cb_bindings.erase(cb_node);
597*b7893ccfSSadaf Ebrahimi         ClearCachedValidation(cb_node);
598*b7893ccfSSadaf Ebrahimi     }
GetImmutableSamplerPtrFromBinding(const uint32_t index)599*b7893ccfSSadaf Ebrahimi     VkSampler const *GetImmutableSamplerPtrFromBinding(const uint32_t index) const {
600*b7893ccfSSadaf Ebrahimi         return p_layout_->GetImmutableSamplerPtrFromBinding(index);
601*b7893ccfSSadaf Ebrahimi     };
602*b7893ccfSSadaf Ebrahimi     // For a particular binding, get the global index
603*b7893ccfSSadaf Ebrahimi     const IndexRange GetGlobalIndexRangeFromBinding(const uint32_t binding, bool actual_length = false) const {
604*b7893ccfSSadaf Ebrahimi         if (actual_length && binding == p_layout_->GetMaxBinding() && IsVariableDescriptorCount(binding)) {
605*b7893ccfSSadaf Ebrahimi             IndexRange range = p_layout_->GetGlobalIndexRangeFromBinding(binding);
606*b7893ccfSSadaf Ebrahimi             auto diff = GetDescriptorCountFromBinding(binding) - GetVariableDescriptorCount();
607*b7893ccfSSadaf Ebrahimi             range.end -= diff;
608*b7893ccfSSadaf Ebrahimi             return range;
609*b7893ccfSSadaf Ebrahimi         }
610*b7893ccfSSadaf Ebrahimi         return p_layout_->GetGlobalIndexRangeFromBinding(binding);
611*b7893ccfSSadaf Ebrahimi     };
612*b7893ccfSSadaf Ebrahimi     // Return true if any part of set has ever been updated
IsUpdated()613*b7893ccfSSadaf Ebrahimi     bool IsUpdated() const { return some_update_; };
IsPushDescriptor()614*b7893ccfSSadaf Ebrahimi     bool IsPushDescriptor() const { return p_layout_->IsPushDescriptor(); };
IsVariableDescriptorCount(uint32_t binding)615*b7893ccfSSadaf Ebrahimi     bool IsVariableDescriptorCount(uint32_t binding) const { return p_layout_->IsVariableDescriptorCount(binding); }
IsUpdateAfterBind(uint32_t binding)616*b7893ccfSSadaf Ebrahimi     bool IsUpdateAfterBind(uint32_t binding) const {
617*b7893ccfSSadaf Ebrahimi         return !!(p_layout_->GetDescriptorBindingFlagsFromBinding(binding) & VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT);
618*b7893ccfSSadaf Ebrahimi     }
GetVariableDescriptorCount()619*b7893ccfSSadaf Ebrahimi     uint32_t GetVariableDescriptorCount() const { return variable_count_; }
GetPoolState()620*b7893ccfSSadaf Ebrahimi     DESCRIPTOR_POOL_STATE *GetPoolState() const { return pool_state_; }
GetDescriptorFromGlobalIndex(const uint32_t index)621*b7893ccfSSadaf Ebrahimi     const Descriptor *GetDescriptorFromGlobalIndex(const uint32_t index) const { return descriptors_[index].get(); }
GetChangeCount()622*b7893ccfSSadaf Ebrahimi     uint64_t GetChangeCount() const { return change_count_; }
623*b7893ccfSSadaf Ebrahimi 
624*b7893ccfSSadaf Ebrahimi    private:
625*b7893ccfSSadaf Ebrahimi     // Private helper to set all bound cmd buffers to INVALID state
626*b7893ccfSSadaf Ebrahimi     void InvalidateBoundCmdBuffers();
627*b7893ccfSSadaf Ebrahimi     bool some_update_;  // has any part of the set ever been updated?
628*b7893ccfSSadaf Ebrahimi     VkDescriptorSet set_;
629*b7893ccfSSadaf Ebrahimi     DESCRIPTOR_POOL_STATE *pool_state_;
630*b7893ccfSSadaf Ebrahimi     const std::shared_ptr<DescriptorSetLayout const> p_layout_;
631*b7893ccfSSadaf Ebrahimi     std::vector<std::unique_ptr<Descriptor>> descriptors_;
632*b7893ccfSSadaf Ebrahimi     StateTracker *state_data_;
633*b7893ccfSSadaf Ebrahimi     uint32_t variable_count_;
634*b7893ccfSSadaf Ebrahimi     uint64_t change_count_;
635*b7893ccfSSadaf Ebrahimi 
636*b7893ccfSSadaf Ebrahimi     // Cached binding and validation support:
637*b7893ccfSSadaf Ebrahimi     //
638*b7893ccfSSadaf Ebrahimi     // For the lifespan of a given command buffer recording, do lazy evaluation, caching, and dirtying of
639*b7893ccfSSadaf Ebrahimi     // expensive validation operation (typically per-draw)
640*b7893ccfSSadaf Ebrahimi     typedef std::unordered_map<CMD_BUFFER_STATE *, TrackedBindings> TrackedBindingMap;
641*b7893ccfSSadaf Ebrahimi     // Track the validation caching of bindings vs. the command buffer and draw state
642*b7893ccfSSadaf Ebrahimi     typedef std::unordered_map<uint32_t, CMD_BUFFER_STATE::ImageLayoutUpdateCount> VersionedBindings;
643*b7893ccfSSadaf Ebrahimi     struct CachedValidation {
644*b7893ccfSSadaf Ebrahimi         TrackedBindings command_binding_and_usage;                                     // Persistent for the life of the recording
645*b7893ccfSSadaf Ebrahimi         TrackedBindings non_dynamic_buffers;                                           // Persistent for the life of the recording
646*b7893ccfSSadaf Ebrahimi         TrackedBindings dynamic_buffers;                                               // Dirtied (flushed) each BindDescriptorSet
647*b7893ccfSSadaf Ebrahimi         std::unordered_map<const PIPELINE_STATE *, VersionedBindings> image_samplers;  // Tested vs. changes to CB's ImageLayout
648*b7893ccfSSadaf Ebrahimi     };
649*b7893ccfSSadaf Ebrahimi     typedef std::unordered_map<const CMD_BUFFER_STATE *, CachedValidation> CachedValidationMap;
650*b7893ccfSSadaf Ebrahimi     // Image and ImageView bindings are validated per pipeline and not invalidate by repeated binding
651*b7893ccfSSadaf Ebrahimi     CachedValidationMap cached_validation_;
652*b7893ccfSSadaf Ebrahimi };
653*b7893ccfSSadaf Ebrahimi // For the "bindless" style resource usage with many descriptors, need to optimize binding and validation
654*b7893ccfSSadaf Ebrahimi class PrefilterBindRequestMap {
655*b7893ccfSSadaf Ebrahimi    public:
656*b7893ccfSSadaf Ebrahimi     static const uint32_t kManyDescriptors_ = 64;  // TODO base this number on measured data
657*b7893ccfSSadaf Ebrahimi     std::unique_ptr<BindingReqMap> filtered_map_;
658*b7893ccfSSadaf Ebrahimi     const BindingReqMap &orig_map_;
659*b7893ccfSSadaf Ebrahimi     const DescriptorSet &descriptor_set_;
660*b7893ccfSSadaf Ebrahimi 
PrefilterBindRequestMap(const DescriptorSet & ds,const BindingReqMap & in_map)661*b7893ccfSSadaf Ebrahimi     PrefilterBindRequestMap(const DescriptorSet &ds, const BindingReqMap &in_map)
662*b7893ccfSSadaf Ebrahimi         : filtered_map_(), orig_map_(in_map), descriptor_set_(ds) {}
663*b7893ccfSSadaf Ebrahimi     const BindingReqMap &FilteredMap(const CMD_BUFFER_STATE &cb_state, const PIPELINE_STATE &);
IsManyDescriptors()664*b7893ccfSSadaf Ebrahimi     bool IsManyDescriptors() const { return descriptor_set_.GetTotalDescriptorCount() > kManyDescriptors_; }
665*b7893ccfSSadaf Ebrahimi };
666*b7893ccfSSadaf Ebrahimi }  // namespace cvdescriptorset
667*b7893ccfSSadaf Ebrahimi #endif  // CORE_VALIDATION_DESCRIPTOR_SETS_H_
668