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 VkResult
panvk_CreateDescriptorSetLayout(VkDevice _device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorSetLayout * pSetLayout)42 panvk_CreateDescriptorSetLayout(VkDevice _device,
43 const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
44 const VkAllocationCallbacks *pAllocator,
45 VkDescriptorSetLayout *pSetLayout)
46 {
47 VK_FROM_HANDLE(panvk_device, device, _device);
48 struct panvk_descriptor_set_layout *set_layout;
49 VkDescriptorSetLayoutBinding *bindings = NULL;
50 unsigned num_bindings = 0;
51 VkResult result;
52
53 if (pCreateInfo->bindingCount) {
54 result =
55 vk_create_sorted_bindings(pCreateInfo->pBindings,
56 pCreateInfo->bindingCount,
57 &bindings);
58 if (result != VK_SUCCESS)
59 return vk_error(device, result);
60
61 num_bindings = bindings[pCreateInfo->bindingCount - 1].binding + 1;
62 }
63
64 unsigned num_immutable_samplers = 0;
65 for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
66 if (bindings[i].pImmutableSamplers)
67 num_immutable_samplers += bindings[i].descriptorCount;
68 }
69
70 size_t size = sizeof(*set_layout) +
71 (sizeof(struct panvk_descriptor_set_binding_layout) *
72 num_bindings) +
73 (sizeof(struct panvk_sampler *) * num_immutable_samplers);
74 set_layout = vk_object_zalloc(&device->vk, pAllocator, size,
75 VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT);
76 if (!set_layout) {
77 result = VK_ERROR_OUT_OF_HOST_MEMORY;
78 goto err_free_bindings;
79 }
80
81 struct panvk_sampler **immutable_samplers =
82 (struct panvk_sampler **)((uint8_t *)set_layout + sizeof(*set_layout) +
83 (sizeof(struct panvk_descriptor_set_binding_layout) *
84 num_bindings));
85
86 set_layout->flags = pCreateInfo->flags;
87 set_layout->binding_count = num_bindings;
88
89 unsigned sampler_idx = 0, tex_idx = 0, ubo_idx = 0, ssbo_idx = 0;
90 unsigned dynoffset_idx = 0, desc_idx = 0;
91
92 for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
93 const VkDescriptorSetLayoutBinding *binding = &bindings[i];
94 struct panvk_descriptor_set_binding_layout *binding_layout =
95 &set_layout->bindings[binding->binding];
96
97 binding_layout->type = binding->descriptorType;
98 binding_layout->array_size = binding->descriptorCount;
99 binding_layout->shader_stages = binding->stageFlags;
100 if (binding->pImmutableSamplers) {
101 binding_layout->immutable_samplers = immutable_samplers;
102 immutable_samplers += binding_layout->array_size;
103 for (unsigned j = 0; j < binding_layout->array_size; j++) {
104 VK_FROM_HANDLE(panvk_sampler, sampler, binding->pImmutableSamplers[j]);
105 binding_layout->immutable_samplers[j] = sampler;
106 }
107 }
108
109 binding_layout->desc_idx = desc_idx;
110 desc_idx += binding->descriptorCount;
111 switch (binding_layout->type) {
112 case VK_DESCRIPTOR_TYPE_SAMPLER:
113 binding_layout->sampler_idx = sampler_idx;
114 sampler_idx += binding_layout->array_size;
115 break;
116 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
117 binding_layout->sampler_idx = sampler_idx;
118 binding_layout->tex_idx = tex_idx;
119 sampler_idx += binding_layout->array_size;
120 tex_idx += binding_layout->array_size;
121 break;
122 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
123 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
124 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
125 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
126 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
127 binding_layout->tex_idx = tex_idx;
128 tex_idx += binding_layout->array_size;
129 break;
130 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
131 binding_layout->dynoffset_idx = dynoffset_idx;
132 dynoffset_idx += binding_layout->array_size;
133 FALLTHROUGH;
134 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
135 binding_layout->ubo_idx = ubo_idx;
136 ubo_idx += binding_layout->array_size;
137 break;
138 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
139 binding_layout->dynoffset_idx = dynoffset_idx;
140 dynoffset_idx += binding_layout->array_size;
141 FALLTHROUGH;
142 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
143 binding_layout->ssbo_idx = ssbo_idx;
144 ssbo_idx += binding_layout->array_size;
145 break;
146 default:
147 unreachable("Invalid descriptor type");
148 }
149 }
150
151 set_layout->num_descs = desc_idx;
152 set_layout->num_samplers = sampler_idx;
153 set_layout->num_textures = tex_idx;
154 set_layout->num_ubos = ubo_idx;
155 set_layout->num_ssbos = ssbo_idx;
156 set_layout->num_dynoffsets = dynoffset_idx;
157
158 free(bindings);
159 *pSetLayout = panvk_descriptor_set_layout_to_handle(set_layout);
160 return VK_SUCCESS;
161
162 err_free_bindings:
163 free(bindings);
164 return vk_error(device, result);
165 }
166
167 void
panvk_DestroyDescriptorSetLayout(VkDevice _device,VkDescriptorSetLayout _set_layout,const VkAllocationCallbacks * pAllocator)168 panvk_DestroyDescriptorSetLayout(VkDevice _device,
169 VkDescriptorSetLayout _set_layout,
170 const VkAllocationCallbacks *pAllocator)
171 {
172 VK_FROM_HANDLE(panvk_device, device, _device);
173 VK_FROM_HANDLE(panvk_descriptor_set_layout, set_layout, _set_layout);
174
175 if (!set_layout)
176 return;
177
178 vk_object_free(&device->vk, pAllocator, set_layout);
179 }
180
181 /* FIXME: make sure those values are correct */
182 #define PANVK_MAX_TEXTURES (1 << 16)
183 #define PANVK_MAX_SAMPLERS (1 << 16)
184 #define PANVK_MAX_UBOS 255
185
186 void
panvk_GetDescriptorSetLayoutSupport(VkDevice _device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,VkDescriptorSetLayoutSupport * pSupport)187 panvk_GetDescriptorSetLayoutSupport(VkDevice _device,
188 const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
189 VkDescriptorSetLayoutSupport *pSupport)
190 {
191 VK_FROM_HANDLE(panvk_device, device, _device);
192
193 pSupport->supported = false;
194
195 VkDescriptorSetLayoutBinding *bindings;
196 VkResult result =
197 vk_create_sorted_bindings(pCreateInfo->pBindings,
198 pCreateInfo->bindingCount,
199 &bindings);
200 if (result != VK_SUCCESS) {
201 vk_error(device, result);
202 return;
203 }
204
205 unsigned sampler_idx = 0, tex_idx = 0, ubo_idx = 0, ssbo_idx = 0, dynoffset_idx = 0;
206 for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
207 const VkDescriptorSetLayoutBinding *binding = &bindings[i];
208
209 switch (binding->descriptorType) {
210 case VK_DESCRIPTOR_TYPE_SAMPLER:
211 sampler_idx += binding->descriptorCount;
212 break;
213 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
214 sampler_idx += binding->descriptorCount;
215 tex_idx += binding->descriptorCount;
216 break;
217 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
218 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
219 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
220 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
221 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
222 tex_idx += binding->descriptorCount;
223 break;
224 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
225 dynoffset_idx += binding->descriptorCount;
226 FALLTHROUGH;
227 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
228 ubo_idx += binding->descriptorCount;
229 break;
230 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
231 dynoffset_idx += binding->descriptorCount;
232 FALLTHROUGH;
233 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
234 ssbo_idx += binding->descriptorCount;
235 break;
236 default:
237 unreachable("Invalid descriptor type");
238 }
239 }
240
241 /* The maximum values apply to all sets attached to a pipeline since all
242 * sets descriptors have to be merged in a single array.
243 */
244 if (tex_idx > PANVK_MAX_TEXTURES / MAX_SETS ||
245 sampler_idx > PANVK_MAX_SAMPLERS / MAX_SETS ||
246 ubo_idx > PANVK_MAX_UBOS / MAX_SETS)
247 return;
248
249 pSupport->supported = true;
250 }
251
252 /*
253 * Pipeline layouts. These have nothing to do with the pipeline. They are
254 * just multiple descriptor set layouts pasted together.
255 */
256
257 VkResult
panvk_CreatePipelineLayout(VkDevice _device,const VkPipelineLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPipelineLayout * pPipelineLayout)258 panvk_CreatePipelineLayout(VkDevice _device,
259 const VkPipelineLayoutCreateInfo *pCreateInfo,
260 const VkAllocationCallbacks *pAllocator,
261 VkPipelineLayout *pPipelineLayout)
262 {
263 VK_FROM_HANDLE(panvk_device, device, _device);
264 struct panvk_pipeline_layout *layout;
265 struct mesa_sha1 ctx;
266
267 layout = vk_object_zalloc(&device->vk, pAllocator, sizeof(*layout),
268 VK_OBJECT_TYPE_PIPELINE_LAYOUT);
269 if (layout == NULL)
270 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
271
272 layout->num_sets = pCreateInfo->setLayoutCount;
273 _mesa_sha1_init(&ctx);
274
275 unsigned sampler_idx = 0, tex_idx = 0, ssbo_idx = 0, ubo_idx = 0, dynoffset_idx = 0;
276 for (unsigned set = 0; set < pCreateInfo->setLayoutCount; set++) {
277 VK_FROM_HANDLE(panvk_descriptor_set_layout, set_layout,
278 pCreateInfo->pSetLayouts[set]);
279 layout->sets[set].layout = set_layout;
280 layout->sets[set].sampler_offset = sampler_idx;
281 layout->sets[set].tex_offset = tex_idx;
282 layout->sets[set].ubo_offset = ubo_idx;
283 layout->sets[set].ssbo_offset = ssbo_idx;
284 layout->sets[set].dynoffset_offset = dynoffset_idx;
285 sampler_idx += set_layout->num_samplers;
286 tex_idx += set_layout->num_textures;
287 ubo_idx += set_layout->num_ubos + (set_layout->num_dynoffsets != 0);
288 ssbo_idx += set_layout->num_ssbos;
289 dynoffset_idx += set_layout->num_dynoffsets;
290
291 for (unsigned b = 0; b < set_layout->binding_count; b++) {
292 struct panvk_descriptor_set_binding_layout *binding_layout =
293 &set_layout->bindings[b];
294
295 if (binding_layout->immutable_samplers) {
296 for (unsigned s = 0; s < binding_layout->array_size; s++) {
297 struct panvk_sampler *sampler = binding_layout->immutable_samplers[s];
298
299 _mesa_sha1_update(&ctx, &sampler->desc, sizeof(sampler->desc));
300 }
301 }
302 _mesa_sha1_update(&ctx, &binding_layout->type, sizeof(binding_layout->type));
303 _mesa_sha1_update(&ctx, &binding_layout->array_size, sizeof(binding_layout->array_size));
304 _mesa_sha1_update(&ctx, &binding_layout->desc_idx, sizeof(binding_layout->sampler_idx));
305 _mesa_sha1_update(&ctx, &binding_layout->shader_stages, sizeof(binding_layout->shader_stages));
306 }
307 }
308
309 layout->num_samplers = sampler_idx;
310 layout->num_textures = tex_idx;
311 layout->num_ubos = ubo_idx;
312 layout->num_ssbos = ssbo_idx;
313 layout->num_dynoffsets = dynoffset_idx;
314
315 _mesa_sha1_final(&ctx, layout->sha1);
316
317 *pPipelineLayout = panvk_pipeline_layout_to_handle(layout);
318 return VK_SUCCESS;
319 }
320
321 void
panvk_DestroyPipelineLayout(VkDevice _device,VkPipelineLayout _pipelineLayout,const VkAllocationCallbacks * pAllocator)322 panvk_DestroyPipelineLayout(VkDevice _device,
323 VkPipelineLayout _pipelineLayout,
324 const VkAllocationCallbacks *pAllocator)
325 {
326 VK_FROM_HANDLE(panvk_device, device, _device);
327 VK_FROM_HANDLE(panvk_pipeline_layout, pipeline_layout, _pipelineLayout);
328
329 if (!pipeline_layout)
330 return;
331
332 vk_object_free(&device->vk, pAllocator, pipeline_layout);
333 }
334
335 VkResult
panvk_CreateDescriptorPool(VkDevice _device,const VkDescriptorPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorPool * pDescriptorPool)336 panvk_CreateDescriptorPool(VkDevice _device,
337 const VkDescriptorPoolCreateInfo *pCreateInfo,
338 const VkAllocationCallbacks *pAllocator,
339 VkDescriptorPool *pDescriptorPool)
340 {
341 VK_FROM_HANDLE(panvk_device, device, _device);
342 struct panvk_descriptor_pool *pool;
343
344 pool = vk_object_zalloc(&device->vk, pAllocator,
345 sizeof(struct panvk_descriptor_pool),
346 VK_OBJECT_TYPE_DESCRIPTOR_POOL);
347 if (!pool)
348 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
349
350 pool->max.sets = pCreateInfo->maxSets;
351
352 for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
353 unsigned desc_count = pCreateInfo->pPoolSizes[i].descriptorCount;
354
355 switch(pCreateInfo->pPoolSizes[i].type) {
356 case VK_DESCRIPTOR_TYPE_SAMPLER:
357 pool->max.samplers += desc_count;
358 break;
359 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
360 pool->max.combined_image_samplers += desc_count;
361 break;
362 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
363 pool->max.sampled_images += desc_count;
364 break;
365 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
366 pool->max.storage_images += desc_count;
367 break;
368 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
369 pool->max.uniform_texel_bufs += desc_count;
370 break;
371 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
372 pool->max.storage_texel_bufs += desc_count;
373 break;
374 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
375 pool->max.input_attachments += desc_count;
376 break;
377 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
378 pool->max.uniform_bufs += desc_count;
379 break;
380 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
381 pool->max.storage_bufs += desc_count;
382 break;
383 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
384 pool->max.uniform_dyn_bufs += desc_count;
385 break;
386 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
387 pool->max.storage_dyn_bufs += desc_count;
388 break;
389 default:
390 unreachable("Invalid descriptor type");
391 }
392 }
393
394 *pDescriptorPool = panvk_descriptor_pool_to_handle(pool);
395 return VK_SUCCESS;
396 }
397
398 void
panvk_DestroyDescriptorPool(VkDevice _device,VkDescriptorPool _pool,const VkAllocationCallbacks * pAllocator)399 panvk_DestroyDescriptorPool(VkDevice _device,
400 VkDescriptorPool _pool,
401 const VkAllocationCallbacks *pAllocator)
402 {
403 VK_FROM_HANDLE(panvk_device, device, _device);
404 VK_FROM_HANDLE(panvk_descriptor_pool, pool, _pool);
405
406 if (pool)
407 vk_object_free(&device->vk, pAllocator, pool);
408 }
409
410 VkResult
panvk_ResetDescriptorPool(VkDevice _device,VkDescriptorPool _pool,VkDescriptorPoolResetFlags flags)411 panvk_ResetDescriptorPool(VkDevice _device,
412 VkDescriptorPool _pool,
413 VkDescriptorPoolResetFlags flags)
414 {
415 VK_FROM_HANDLE(panvk_descriptor_pool, pool, _pool);
416 memset(&pool->cur, 0, sizeof(pool->cur));
417 return VK_SUCCESS;
418 }
419
420 static void
panvk_descriptor_set_destroy(struct panvk_device * device,struct panvk_descriptor_pool * pool,struct panvk_descriptor_set * set)421 panvk_descriptor_set_destroy(struct panvk_device *device,
422 struct panvk_descriptor_pool *pool,
423 struct panvk_descriptor_set *set)
424 {
425 vk_free(&device->vk.alloc, set->textures);
426 vk_free(&device->vk.alloc, set->samplers);
427 vk_free(&device->vk.alloc, set->ubos);
428 vk_free(&device->vk.alloc, set->descs);
429 vk_object_free(&device->vk, NULL, set);
430 }
431
432 VkResult
panvk_FreeDescriptorSets(VkDevice _device,VkDescriptorPool descriptorPool,uint32_t count,const VkDescriptorSet * pDescriptorSets)433 panvk_FreeDescriptorSets(VkDevice _device,
434 VkDescriptorPool descriptorPool,
435 uint32_t count,
436 const VkDescriptorSet *pDescriptorSets)
437 {
438 VK_FROM_HANDLE(panvk_device, device, _device);
439 VK_FROM_HANDLE(panvk_descriptor_pool, pool, descriptorPool);
440
441 for (unsigned i = 0; i < count; i++) {
442 VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorSets[i]);
443
444 if (set)
445 panvk_descriptor_set_destroy(device, pool, set);
446 }
447 return VK_SUCCESS;
448 }
449
450 VkResult
panvk_CreateDescriptorUpdateTemplate(VkDevice _device,const VkDescriptorUpdateTemplateCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorUpdateTemplate * pDescriptorUpdateTemplate)451 panvk_CreateDescriptorUpdateTemplate(VkDevice _device,
452 const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
453 const VkAllocationCallbacks *pAllocator,
454 VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)
455 {
456 panvk_stub();
457 return VK_SUCCESS;
458 }
459
460 void
panvk_DestroyDescriptorUpdateTemplate(VkDevice _device,VkDescriptorUpdateTemplate descriptorUpdateTemplate,const VkAllocationCallbacks * pAllocator)461 panvk_DestroyDescriptorUpdateTemplate(VkDevice _device,
462 VkDescriptorUpdateTemplate descriptorUpdateTemplate,
463 const VkAllocationCallbacks *pAllocator)
464 {
465 panvk_stub();
466 }
467
468 void
panvk_UpdateDescriptorSetWithTemplate(VkDevice _device,VkDescriptorSet descriptorSet,VkDescriptorUpdateTemplate descriptorUpdateTemplate,const void * pData)469 panvk_UpdateDescriptorSetWithTemplate(VkDevice _device,
470 VkDescriptorSet descriptorSet,
471 VkDescriptorUpdateTemplate descriptorUpdateTemplate,
472 const void *pData)
473 {
474 panvk_stub();
475 }
476
477 VkResult
panvk_CreateSamplerYcbcrConversion(VkDevice device,const VkSamplerYcbcrConversionCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSamplerYcbcrConversion * pYcbcrConversion)478 panvk_CreateSamplerYcbcrConversion(VkDevice device,
479 const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
480 const VkAllocationCallbacks *pAllocator,
481 VkSamplerYcbcrConversion *pYcbcrConversion)
482 {
483 panvk_stub();
484 return VK_SUCCESS;
485 }
486
487 void
panvk_DestroySamplerYcbcrConversion(VkDevice device,VkSamplerYcbcrConversion ycbcrConversion,const VkAllocationCallbacks * pAllocator)488 panvk_DestroySamplerYcbcrConversion(VkDevice device,
489 VkSamplerYcbcrConversion ycbcrConversion,
490 const VkAllocationCallbacks *pAllocator)
491 {
492 panvk_stub();
493 }
494