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 VkResult
panvk_per_arch(CreateDescriptorSetLayout)46 panvk_per_arch(CreateDescriptorSetLayout)(
47 VkDevice _device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
48 const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout)
49 {
50 VK_FROM_HANDLE(panvk_device, device, _device);
51 VkDescriptorSetLayoutBinding *bindings = NULL;
52 unsigned num_bindings = 0;
53 VkResult result;
54
55 unsigned immutable_sampler_count = 0;
56 for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
57 const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[j];
58 num_bindings = MAX2(num_bindings, binding->binding + 1);
59
60 /* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding:
61 *
62 * "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or
63 * VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then
64 * pImmutableSamplers can be used to initialize a set of immutable
65 * samplers. [...] If descriptorType is not one of these descriptor
66 * types, then pImmutableSamplers is ignored.
67 *
68 * We need to be careful here and only parse pImmutableSamplers if we
69 * have one of the right descriptor types.
70 */
71 if (binding_has_immutable_samplers(binding))
72 immutable_sampler_count += binding->descriptorCount;
73 }
74
75 if (pCreateInfo->bindingCount) {
76 result = vk_create_sorted_bindings(pCreateInfo->pBindings,
77 pCreateInfo->bindingCount, &bindings);
78 if (result != VK_SUCCESS)
79 return panvk_error(device, result);
80
81 num_bindings = bindings[pCreateInfo->bindingCount - 1].binding + 1;
82 }
83
84 VK_MULTIALLOC(ma);
85 VK_MULTIALLOC_DECL(&ma, struct panvk_descriptor_set_layout, layout, 1);
86 VK_MULTIALLOC_DECL(&ma, struct panvk_descriptor_set_binding_layout,
87 binding_layouts, num_bindings);
88 VK_MULTIALLOC_DECL(&ma, struct mali_sampler_packed, samplers,
89 immutable_sampler_count);
90
91 if (!vk_descriptor_set_layout_multizalloc(&device->vk, &ma)) {
92 free(bindings);
93 return panvk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
94 }
95
96 layout->flags = pCreateInfo->flags;
97 layout->bindings = binding_layouts;
98 layout->binding_count = num_bindings;
99
100 const VkDescriptorSetLayoutBindingFlagsCreateInfo *binding_flags_info =
101 vk_find_struct_const(pCreateInfo->pNext,
102 DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO);
103
104 unsigned desc_idx = 0;
105 unsigned dyn_buf_idx = 0;
106 for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
107 const VkDescriptorSetLayoutBinding *binding = &bindings[i];
108 struct panvk_descriptor_set_binding_layout *binding_layout =
109 &layout->bindings[binding->binding];
110
111 if (binding->descriptorCount == 0)
112 continue;
113
114 binding_layout->type = binding->descriptorType;
115
116 if (binding_flags_info && binding_flags_info->bindingCount > 0) {
117 assert(binding_flags_info->bindingCount == pCreateInfo->bindingCount);
118 binding_layout->flags = binding_flags_info->pBindingFlags[i];
119 }
120
121 binding_layout->desc_count = binding->descriptorCount;
122
123 if (binding_has_immutable_samplers(binding)) {
124 binding_layout->immutable_samplers = samplers;
125 samplers += binding->descriptorCount;
126 for (uint32_t j = 0; j < binding->descriptorCount; j++) {
127 VK_FROM_HANDLE(panvk_sampler, sampler,
128 binding->pImmutableSamplers[j]);
129 binding_layout->immutable_samplers[j] = sampler->desc;
130 }
131 }
132
133 if (vk_descriptor_type_is_dynamic(binding_layout->type)) {
134 binding_layout->desc_idx = dyn_buf_idx;
135 dyn_buf_idx += binding_layout->desc_count;
136 } else {
137 binding_layout->desc_idx = desc_idx;
138 desc_idx += panvk_get_desc_stride(binding_layout->type) *
139 binding_layout->desc_count;
140 }
141 }
142
143 layout->desc_count = desc_idx;
144 layout->dyn_buf_count = dyn_buf_idx;
145
146 struct mesa_blake3 hash_ctx;
147 _mesa_blake3_init(&hash_ctx);
148
149 _mesa_blake3_update(&hash_ctx, &layout->binding_count,
150 sizeof(layout->binding_count));
151 _mesa_blake3_update(&hash_ctx, &layout->desc_count,
152 sizeof(layout->desc_count));
153 _mesa_blake3_update(&hash_ctx, &layout->dyn_buf_count,
154 sizeof(layout->dyn_buf_count));
155
156 for (uint32_t b = 0; b < num_bindings; b++) {
157 _mesa_blake3_update(&hash_ctx, &layout->bindings[b].type,
158 sizeof(layout->bindings[b].type));
159 _mesa_blake3_update(&hash_ctx, &layout->bindings[b].flags,
160 sizeof(layout->bindings[b].flags));
161 _mesa_blake3_update(&hash_ctx, &layout->bindings[b].desc_count,
162 sizeof(layout->bindings[b].desc_count));
163 /* Immutable samplers are ignored for now */
164 }
165
166 _mesa_blake3_final(&hash_ctx, layout->vk.blake3);
167
168 free(bindings);
169 *pSetLayout = panvk_descriptor_set_layout_to_handle(layout);
170
171 return VK_SUCCESS;
172 }
173
174 void
panvk_per_arch(GetDescriptorSetLayoutSupport)175 panvk_per_arch(GetDescriptorSetLayoutSupport)(
176 VkDevice _device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
177 VkDescriptorSetLayoutSupport *pSupport)
178 {
179 pSupport->supported = false;
180
181 unsigned desc_count = 0, dyn_buf_count = 0;
182 for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
183 const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[i];
184 VkDescriptorType type = binding->descriptorType;
185
186 if (vk_descriptor_type_is_dynamic(type))
187 dyn_buf_count += binding->descriptorCount;
188 else
189 desc_count += panvk_get_desc_stride(type) * binding->descriptorCount;
190 }
191
192 if (desc_count > PANVK_MAX_DESCS_PER_SET ||
193 dyn_buf_count > MAX_DYNAMIC_BUFFERS)
194 return;
195
196 pSupport->supported = true;
197 }
198