1 /*
2 * Copyright © 2021 Collabora Ltd.
3 *
4 * Derived from:
5 * Copyright © 2016 Red Hat.
6 * Copyright © 2016 Bas Nieuwenhuizen
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 */
27 #include "panvk_private.h"
28
29 #include <assert.h>
30 #include <fcntl.h>
31 #include <stdbool.h>
32 #include <string.h>
33 #include <unistd.h>
34
35 #include "util/mesa-sha1.h"
36 #include "vk_descriptors.h"
37 #include "vk_util.h"
38
39 #include "pan_bo.h"
40
41 /* FIXME: make sure those values are correct */
42 #define PANVK_MAX_TEXTURES (1 << 16)
43 #define PANVK_MAX_IMAGES (1 << 8)
44 #define PANVK_MAX_SAMPLERS (1 << 16)
45 #define PANVK_MAX_UBOS 255
46
47 void
panvk_GetDescriptorSetLayoutSupport(VkDevice _device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,VkDescriptorSetLayoutSupport * pSupport)48 panvk_GetDescriptorSetLayoutSupport(VkDevice _device,
49 const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
50 VkDescriptorSetLayoutSupport *pSupport)
51 {
52 VK_FROM_HANDLE(panvk_device, device, _device);
53
54 pSupport->supported = false;
55
56 VkDescriptorSetLayoutBinding *bindings;
57 VkResult result =
58 vk_create_sorted_bindings(pCreateInfo->pBindings,
59 pCreateInfo->bindingCount,
60 &bindings);
61 if (result != VK_SUCCESS) {
62 vk_error(device, result);
63 return;
64 }
65
66 unsigned sampler_idx = 0, tex_idx = 0, ubo_idx = 0;
67 unsigned dynoffset_idx = 0, img_idx = 0;
68
69 for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
70 const VkDescriptorSetLayoutBinding *binding = &bindings[i];
71
72 switch (binding->descriptorType) {
73 case VK_DESCRIPTOR_TYPE_SAMPLER:
74 sampler_idx += binding->descriptorCount;
75 break;
76 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
77 sampler_idx += binding->descriptorCount;
78 tex_idx += binding->descriptorCount;
79 break;
80 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
81 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
82 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
83 tex_idx += binding->descriptorCount;
84 break;
85 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
86 dynoffset_idx += binding->descriptorCount;
87 FALLTHROUGH;
88 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
89 ubo_idx += binding->descriptorCount;
90 break;
91 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
92 dynoffset_idx += binding->descriptorCount;
93 FALLTHROUGH;
94 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
95 break;
96 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
97 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
98 img_idx += binding->descriptorCount;
99 break;
100 default:
101 unreachable("Invalid descriptor type");
102 }
103 }
104
105 /* The maximum values apply to all sets attached to a pipeline since all
106 * sets descriptors have to be merged in a single array.
107 */
108 if (tex_idx > PANVK_MAX_TEXTURES / MAX_SETS ||
109 sampler_idx > PANVK_MAX_SAMPLERS / MAX_SETS ||
110 ubo_idx > PANVK_MAX_UBOS / MAX_SETS ||
111 img_idx > PANVK_MAX_IMAGES / MAX_SETS)
112 return;
113
114 pSupport->supported = true;
115 }
116
117 /*
118 * Pipeline layouts. These have nothing to do with the pipeline. They are
119 * just multiple descriptor set layouts pasted together.
120 */
121
122 VkResult
panvk_CreatePipelineLayout(VkDevice _device,const VkPipelineLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPipelineLayout * pPipelineLayout)123 panvk_CreatePipelineLayout(VkDevice _device,
124 const VkPipelineLayoutCreateInfo *pCreateInfo,
125 const VkAllocationCallbacks *pAllocator,
126 VkPipelineLayout *pPipelineLayout)
127 {
128 VK_FROM_HANDLE(panvk_device, device, _device);
129 struct panvk_pipeline_layout *layout;
130 struct mesa_sha1 ctx;
131
132 layout = vk_pipeline_layout_zalloc(&device->vk, sizeof(*layout),
133 pCreateInfo);
134 if (layout == NULL)
135 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
136
137 _mesa_sha1_init(&ctx);
138
139 unsigned sampler_idx = 0, tex_idx = 0, ubo_idx = 0;
140 unsigned dyn_ubo_idx = 0, dyn_ssbo_idx = 0, img_idx = 0;
141 for (unsigned set = 0; set < pCreateInfo->setLayoutCount; set++) {
142 const struct panvk_descriptor_set_layout *set_layout =
143 vk_to_panvk_descriptor_set_layout(layout->vk.set_layouts[set]);
144
145 layout->sets[set].sampler_offset = sampler_idx;
146 layout->sets[set].tex_offset = tex_idx;
147 layout->sets[set].ubo_offset = ubo_idx;
148 layout->sets[set].dyn_ubo_offset = dyn_ubo_idx;
149 layout->sets[set].dyn_ssbo_offset = dyn_ssbo_idx;
150 layout->sets[set].img_offset = img_idx;
151 sampler_idx += set_layout->num_samplers;
152 tex_idx += set_layout->num_textures;
153 ubo_idx += set_layout->num_ubos;
154 dyn_ubo_idx += set_layout->num_dyn_ubos;
155 dyn_ssbo_idx += set_layout->num_dyn_ssbos;
156 img_idx += set_layout->num_imgs;
157
158 for (unsigned b = 0; b < set_layout->binding_count; b++) {
159 const struct panvk_descriptor_set_binding_layout *binding_layout =
160 &set_layout->bindings[b];
161
162 if (binding_layout->immutable_samplers) {
163 for (unsigned s = 0; s < binding_layout->array_size; s++) {
164 struct panvk_sampler *sampler = binding_layout->immutable_samplers[s];
165
166 _mesa_sha1_update(&ctx, &sampler->desc, sizeof(sampler->desc));
167 }
168 }
169 _mesa_sha1_update(&ctx, &binding_layout->type, sizeof(binding_layout->type));
170 _mesa_sha1_update(&ctx, &binding_layout->array_size, sizeof(binding_layout->array_size));
171 _mesa_sha1_update(&ctx, &binding_layout->shader_stages, sizeof(binding_layout->shader_stages));
172 }
173 }
174
175 for (unsigned range = 0; range < pCreateInfo->pushConstantRangeCount; range++) {
176 layout->push_constants.size =
177 MAX2(pCreateInfo->pPushConstantRanges[range].offset +
178 pCreateInfo->pPushConstantRanges[range].size,
179 layout->push_constants.size);
180 }
181
182 layout->num_samplers = sampler_idx;
183 layout->num_textures = tex_idx;
184 layout->num_ubos = ubo_idx;
185 layout->num_dyn_ubos = dyn_ubo_idx;
186 layout->num_dyn_ssbos = dyn_ssbo_idx;
187 layout->num_imgs = img_idx;
188
189 /* Some NIR texture operations don't require a sampler, but Bifrost/Midgard
190 * ones always expect one. Add a dummy sampler to deal with this limitation.
191 */
192 if (layout->num_textures) {
193 layout->num_samplers++;
194 for (unsigned set = 0; set < pCreateInfo->setLayoutCount; set++)
195 layout->sets[set].sampler_offset++;
196 }
197
198 _mesa_sha1_final(&ctx, layout->sha1);
199
200 *pPipelineLayout = panvk_pipeline_layout_to_handle(layout);
201 return VK_SUCCESS;
202 }
203
204 VkResult
panvk_CreateDescriptorPool(VkDevice _device,const VkDescriptorPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorPool * pDescriptorPool)205 panvk_CreateDescriptorPool(VkDevice _device,
206 const VkDescriptorPoolCreateInfo *pCreateInfo,
207 const VkAllocationCallbacks *pAllocator,
208 VkDescriptorPool *pDescriptorPool)
209 {
210 VK_FROM_HANDLE(panvk_device, device, _device);
211 struct panvk_descriptor_pool *pool;
212
213 pool = vk_object_zalloc(&device->vk, pAllocator,
214 sizeof(struct panvk_descriptor_pool),
215 VK_OBJECT_TYPE_DESCRIPTOR_POOL);
216 if (!pool)
217 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
218
219 pool->max.sets = pCreateInfo->maxSets;
220
221 for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
222 unsigned desc_count = pCreateInfo->pPoolSizes[i].descriptorCount;
223
224 switch(pCreateInfo->pPoolSizes[i].type) {
225 case VK_DESCRIPTOR_TYPE_SAMPLER:
226 pool->max.samplers += desc_count;
227 break;
228 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
229 pool->max.combined_image_samplers += desc_count;
230 break;
231 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
232 pool->max.sampled_images += desc_count;
233 break;
234 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
235 pool->max.storage_images += desc_count;
236 break;
237 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
238 pool->max.uniform_texel_bufs += desc_count;
239 break;
240 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
241 pool->max.storage_texel_bufs += desc_count;
242 break;
243 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
244 pool->max.input_attachments += desc_count;
245 break;
246 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
247 pool->max.uniform_bufs += desc_count;
248 break;
249 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
250 pool->max.storage_bufs += desc_count;
251 break;
252 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
253 pool->max.uniform_dyn_bufs += desc_count;
254 break;
255 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
256 pool->max.storage_dyn_bufs += desc_count;
257 break;
258 default:
259 unreachable("Invalid descriptor type");
260 }
261 }
262
263 *pDescriptorPool = panvk_descriptor_pool_to_handle(pool);
264 return VK_SUCCESS;
265 }
266
267 void
panvk_DestroyDescriptorPool(VkDevice _device,VkDescriptorPool _pool,const VkAllocationCallbacks * pAllocator)268 panvk_DestroyDescriptorPool(VkDevice _device,
269 VkDescriptorPool _pool,
270 const VkAllocationCallbacks *pAllocator)
271 {
272 VK_FROM_HANDLE(panvk_device, device, _device);
273 VK_FROM_HANDLE(panvk_descriptor_pool, pool, _pool);
274
275 if (pool)
276 vk_object_free(&device->vk, pAllocator, pool);
277 }
278
279 VkResult
panvk_ResetDescriptorPool(VkDevice _device,VkDescriptorPool _pool,VkDescriptorPoolResetFlags flags)280 panvk_ResetDescriptorPool(VkDevice _device,
281 VkDescriptorPool _pool,
282 VkDescriptorPoolResetFlags flags)
283 {
284 VK_FROM_HANDLE(panvk_descriptor_pool, pool, _pool);
285 memset(&pool->cur, 0, sizeof(pool->cur));
286 return VK_SUCCESS;
287 }
288
289 static void
panvk_descriptor_set_destroy(struct panvk_device * device,struct panvk_descriptor_pool * pool,struct panvk_descriptor_set * set)290 panvk_descriptor_set_destroy(struct panvk_device *device,
291 struct panvk_descriptor_pool *pool,
292 struct panvk_descriptor_set *set)
293 {
294 vk_free(&device->vk.alloc, set->textures);
295 vk_free(&device->vk.alloc, set->samplers);
296 vk_free(&device->vk.alloc, set->ubos);
297 vk_free(&device->vk.alloc, set->dyn_ubos);
298 vk_free(&device->vk.alloc, set->dyn_ssbos);
299 vk_free(&device->vk.alloc, set->img_fmts);
300 vk_free(&device->vk.alloc, set->img_attrib_bufs);
301 if (set->desc_bo)
302 panfrost_bo_unreference(set->desc_bo);
303 vk_object_free(&device->vk, NULL, set);
304 }
305
306 VkResult
panvk_FreeDescriptorSets(VkDevice _device,VkDescriptorPool descriptorPool,uint32_t count,const VkDescriptorSet * pDescriptorSets)307 panvk_FreeDescriptorSets(VkDevice _device,
308 VkDescriptorPool descriptorPool,
309 uint32_t count,
310 const VkDescriptorSet *pDescriptorSets)
311 {
312 VK_FROM_HANDLE(panvk_device, device, _device);
313 VK_FROM_HANDLE(panvk_descriptor_pool, pool, descriptorPool);
314
315 for (unsigned i = 0; i < count; i++) {
316 VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorSets[i]);
317
318 if (set)
319 panvk_descriptor_set_destroy(device, pool, set);
320 }
321 return VK_SUCCESS;
322 }
323
324 VkResult
panvk_CreateDescriptorUpdateTemplate(VkDevice _device,const VkDescriptorUpdateTemplateCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorUpdateTemplate * pDescriptorUpdateTemplate)325 panvk_CreateDescriptorUpdateTemplate(VkDevice _device,
326 const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
327 const VkAllocationCallbacks *pAllocator,
328 VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)
329 {
330 panvk_stub();
331 return VK_SUCCESS;
332 }
333
334 void
panvk_DestroyDescriptorUpdateTemplate(VkDevice _device,VkDescriptorUpdateTemplate descriptorUpdateTemplate,const VkAllocationCallbacks * pAllocator)335 panvk_DestroyDescriptorUpdateTemplate(VkDevice _device,
336 VkDescriptorUpdateTemplate descriptorUpdateTemplate,
337 const VkAllocationCallbacks *pAllocator)
338 {
339 panvk_stub();
340 }
341
342 void
panvk_UpdateDescriptorSetWithTemplate(VkDevice _device,VkDescriptorSet descriptorSet,VkDescriptorUpdateTemplate descriptorUpdateTemplate,const void * pData)343 panvk_UpdateDescriptorSetWithTemplate(VkDevice _device,
344 VkDescriptorSet descriptorSet,
345 VkDescriptorUpdateTemplate descriptorUpdateTemplate,
346 const void *pData)
347 {
348 panvk_stub();
349 }
350
351 VkResult
panvk_CreateSamplerYcbcrConversion(VkDevice device,const VkSamplerYcbcrConversionCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSamplerYcbcrConversion * pYcbcrConversion)352 panvk_CreateSamplerYcbcrConversion(VkDevice device,
353 const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
354 const VkAllocationCallbacks *pAllocator,
355 VkSamplerYcbcrConversion *pYcbcrConversion)
356 {
357 panvk_stub();
358 return VK_SUCCESS;
359 }
360
361 void
panvk_DestroySamplerYcbcrConversion(VkDevice device,VkSamplerYcbcrConversion ycbcrConversion,const VkAllocationCallbacks * pAllocator)362 panvk_DestroySamplerYcbcrConversion(VkDevice device,
363 VkSamplerYcbcrConversion ycbcrConversion,
364 const VkAllocationCallbacks *pAllocator)
365 {
366 panvk_stub();
367 }
368