xref: /aosp_15_r20/external/mesa3d/src/panfrost/vulkan/panvk_vX_descriptor_set_layout.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2024 Collabora Ltd.
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include <assert.h>
7 #include <fcntl.h>
8 #include <stdbool.h>
9 #include <string.h>
10 #include <unistd.h>
11 
12 #include "util/mesa-blake3.h"
13 
14 #include "vk_descriptor_update_template.h"
15 #include "vk_descriptors.h"
16 #include "vk_format.h"
17 #include "vk_log.h"
18 #include "vk_util.h"
19 
20 #include "util/bitset.h"
21 
22 #include "genxml/gen_macros.h"
23 
24 #include "panvk_descriptor_set_layout.h"
25 #include "panvk_device.h"
26 #include "panvk_entrypoints.h"
27 #include "panvk_macros.h"
28 #include "panvk_sampler.h"
29 
30 #define PANVK_MAX_DESCS_PER_SET (1 << 24)
31 
32 static bool
binding_has_immutable_samplers(const VkDescriptorSetLayoutBinding * binding)33 binding_has_immutable_samplers(const VkDescriptorSetLayoutBinding *binding)
34 {
35    switch (binding->descriptorType) {
36    case VK_DESCRIPTOR_TYPE_SAMPLER:
37    case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
38       return binding->pImmutableSamplers != NULL;
39 
40    default:
41       return false;
42    }
43 }
44 
45 static bool
is_sampler(const VkDescriptorSetLayoutBinding * binding)46 is_sampler(const VkDescriptorSetLayoutBinding *binding)
47 {
48    switch (binding->descriptorType) {
49    case VK_DESCRIPTOR_TYPE_SAMPLER:
50    case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
51       return true;
52    default:
53       return false;
54    }
55 }
56 
57 static bool
is_texture(const VkDescriptorSetLayoutBinding * binding)58 is_texture(const VkDescriptorSetLayoutBinding *binding)
59 {
60    switch (binding->descriptorType) {
61    case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
62    case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
63    case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
64    case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
65       return true;
66    default:
67       return false;
68    }
69 }
70 
71 VkResult
panvk_per_arch(CreateDescriptorSetLayout)72 panvk_per_arch(CreateDescriptorSetLayout)(
73    VkDevice _device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
74    const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout)
75 {
76    VK_FROM_HANDLE(panvk_device, device, _device);
77    VkDescriptorSetLayoutBinding *bindings = NULL;
78    unsigned num_bindings = 0;
79    VkResult result;
80 
81    unsigned immutable_sampler_count = 0;
82    for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
83       const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[j];
84       num_bindings = MAX2(num_bindings, binding->binding + 1);
85 
86       /* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding:
87        *
88        *    "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or
89        *    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then
90        *    pImmutableSamplers can be used to initialize a set of immutable
91        *    samplers. [...]  If descriptorType is not one of these descriptor
92        *    types, then pImmutableSamplers is ignored.
93        *
94        * We need to be careful here and only parse pImmutableSamplers if we
95        * have one of the right descriptor types.
96        */
97       if (binding_has_immutable_samplers(binding))
98          immutable_sampler_count += binding->descriptorCount;
99    }
100 
101    if (pCreateInfo->bindingCount) {
102       result = vk_create_sorted_bindings(pCreateInfo->pBindings,
103                                          pCreateInfo->bindingCount, &bindings);
104       if (result != VK_SUCCESS)
105          return vk_error(device, result);
106 
107       num_bindings = bindings[pCreateInfo->bindingCount - 1].binding + 1;
108    }
109 
110    VK_MULTIALLOC(ma);
111    VK_MULTIALLOC_DECL(&ma, struct panvk_descriptor_set_layout, layout, 1);
112    VK_MULTIALLOC_DECL(&ma, struct panvk_descriptor_set_binding_layout,
113                       binding_layouts, num_bindings);
114    VK_MULTIALLOC_DECL(&ma, struct mali_sampler_packed, samplers,
115                       immutable_sampler_count);
116 
117    if (!vk_descriptor_set_layout_multizalloc(&device->vk, &ma)) {
118       free(bindings);
119       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
120    }
121 
122    layout->flags = pCreateInfo->flags;
123    layout->bindings = binding_layouts;
124    layout->binding_count = num_bindings;
125 
126    const VkDescriptorSetLayoutBindingFlagsCreateInfo *binding_flags_info =
127       vk_find_struct_const(pCreateInfo->pNext,
128                            DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO);
129 
130    unsigned desc_idx = 0;
131    unsigned dyn_buf_idx = 0;
132    for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
133       const VkDescriptorSetLayoutBinding *binding = &bindings[i];
134       struct panvk_descriptor_set_binding_layout *binding_layout =
135          &layout->bindings[binding->binding];
136 
137       if (binding->descriptorCount == 0)
138          continue;
139 
140       binding_layout->type = binding->descriptorType;
141 
142       if (binding_flags_info && binding_flags_info->bindingCount > 0) {
143          assert(binding_flags_info->bindingCount == pCreateInfo->bindingCount);
144          binding_layout->flags = binding_flags_info->pBindingFlags[i];
145       }
146 
147       binding_layout->desc_count = binding->descriptorCount;
148 
149       if (binding_has_immutable_samplers(binding)) {
150          binding_layout->immutable_samplers = samplers;
151          samplers += binding->descriptorCount;
152          for (uint32_t j = 0; j < binding->descriptorCount; j++) {
153             VK_FROM_HANDLE(panvk_sampler, sampler,
154                            binding->pImmutableSamplers[j]);
155             binding_layout->immutable_samplers[j] = sampler->desc;
156          }
157       }
158 
159       if (binding_layout->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
160           binding_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
161          binding_layout->desc_idx = dyn_buf_idx;
162          dyn_buf_idx += binding_layout->desc_count;
163       } else {
164          binding_layout->desc_idx = desc_idx;
165          desc_idx += panvk_get_desc_stride(binding_layout->type) *
166                      binding_layout->desc_count;
167       }
168    }
169 
170    layout->desc_count = desc_idx;
171    layout->dyn_buf_count = dyn_buf_idx;
172 
173    struct mesa_blake3 hash_ctx;
174    _mesa_blake3_init(&hash_ctx);
175 
176    _mesa_blake3_update(&hash_ctx, &layout->binding_count,
177                        sizeof(layout->binding_count));
178    _mesa_blake3_update(&hash_ctx, &layout->desc_count,
179                        sizeof(layout->desc_count));
180    _mesa_blake3_update(&hash_ctx, &layout->dyn_buf_count,
181                        sizeof(layout->dyn_buf_count));
182 
183    for (uint32_t b = 0; b < num_bindings; b++) {
184       _mesa_blake3_update(&hash_ctx, &layout->bindings[b].type,
185                           sizeof(layout->bindings[b].type));
186       _mesa_blake3_update(&hash_ctx, &layout->bindings[b].flags,
187                           sizeof(layout->bindings[b].flags));
188       _mesa_blake3_update(&hash_ctx, &layout->bindings[b].desc_count,
189                           sizeof(layout->bindings[b].desc_count));
190       /* Immutable samplers are ignored for now */
191    }
192 
193    _mesa_blake3_final(&hash_ctx, layout->hash);
194 
195    free(bindings);
196    *pSetLayout = panvk_descriptor_set_layout_to_handle(layout);
197 
198    return VK_SUCCESS;
199 }
200 
201 void
panvk_per_arch(GetDescriptorSetLayoutSupport)202 panvk_per_arch(GetDescriptorSetLayoutSupport)(
203    VkDevice _device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
204    VkDescriptorSetLayoutSupport *pSupport)
205 {
206    pSupport->supported = false;
207 
208    unsigned desc_count = 0, dyn_buf_count = 0;
209    for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
210       const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[i];
211       VkDescriptorType type = binding->descriptorType;
212 
213       if (type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
214           type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)
215          dyn_buf_count += binding->descriptorCount;
216       else
217          desc_count += panvk_get_desc_stride(type) * binding->descriptorCount;
218    }
219 
220    if (desc_count > PANVK_MAX_DESCS_PER_SET ||
221        dyn_buf_count > MAX_DYNAMIC_BUFFERS)
222       return;
223 
224    pSupport->supported = true;
225 }
226