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