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 
28 #include "genxml/gen_macros.h"
29 
30 #include "panvk_private.h"
31 
32 #include <assert.h>
33 #include <fcntl.h>
34 #include <stdbool.h>
35 #include <string.h>
36 #include <unistd.h>
37 
38 #include "util/mesa-sha1.h"
39 #include "vk_descriptors.h"
40 #include "vk_util.h"
41 
42 #include "pan_bo.h"
43 #include "panvk_cs.h"
44 
45 static VkResult
panvk_per_arch(descriptor_set_create)46 panvk_per_arch(descriptor_set_create)(struct panvk_device *device,
47                                       struct panvk_descriptor_pool *pool,
48                                       const struct panvk_descriptor_set_layout *layout,
49                                       struct panvk_descriptor_set **out_set)
50 {
51    struct panvk_descriptor_set *set;
52 
53    /* TODO: Allocate from the pool! */
54    set = vk_object_zalloc(&device->vk, NULL,
55                           sizeof(struct panvk_descriptor_set),
56                           VK_OBJECT_TYPE_DESCRIPTOR_SET);
57    if (!set)
58       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
59 
60    set->layout = layout;
61    set->descs = vk_alloc(&device->vk.alloc,
62                          sizeof(*set->descs) * layout->num_descs, 8,
63                          VK_OBJECT_TYPE_DESCRIPTOR_SET);
64    if (!set->descs)
65       goto err_free_set;
66 
67    if (layout->num_ubos) {
68       set->ubos = vk_zalloc(&device->vk.alloc,
69                             pan_size(UNIFORM_BUFFER) * layout->num_ubos, 8,
70                             VK_OBJECT_TYPE_DESCRIPTOR_SET);
71       if (!set->ubos)
72          goto err_free_set;
73    }
74 
75    if (layout->num_dyn_ubos) {
76       set->dyn_ubos = vk_zalloc(&device->vk.alloc,
77                             sizeof(*set->dyn_ubos) * layout->num_dyn_ubos, 8,
78                             VK_OBJECT_TYPE_DESCRIPTOR_SET);
79       if (!set->dyn_ubos)
80          goto err_free_set;
81    }
82 
83    if (layout->num_ssbos) {
84       set->ssbos = vk_zalloc(&device->vk.alloc,
85                             sizeof(*set->ssbos) * layout->num_ssbos, 8,
86                             VK_OBJECT_TYPE_DESCRIPTOR_SET);
87       if (!set->ssbos)
88          goto err_free_set;
89    }
90 
91    if (layout->num_dyn_ssbos) {
92       set->dyn_ssbos = vk_zalloc(&device->vk.alloc,
93                             sizeof(*set->dyn_ssbos) * layout->num_dyn_ssbos, 8,
94                             VK_OBJECT_TYPE_DESCRIPTOR_SET);
95       if (!set->dyn_ssbos)
96          goto err_free_set;
97    }
98 
99    if (layout->num_samplers) {
100       set->samplers = vk_zalloc(&device->vk.alloc,
101                                 pan_size(SAMPLER) * layout->num_samplers, 8,
102                                 VK_OBJECT_TYPE_DESCRIPTOR_SET);
103       if (!set->samplers)
104          goto err_free_set;
105    }
106 
107    if (layout->num_textures) {
108       set->textures =
109          vk_zalloc(&device->vk.alloc,
110                    (PAN_ARCH >= 6 ? pan_size(TEXTURE) : sizeof(mali_ptr)) *
111                    layout->num_textures,
112                    8, VK_OBJECT_TYPE_DESCRIPTOR_SET);
113       if (!set->textures)
114          goto err_free_set;
115    }
116 
117    if (layout->num_imgs) {
118       set->img_fmts =
119          vk_zalloc(&device->vk.alloc,
120                    sizeof(*set->img_fmts) * layout->num_imgs,
121                    8, VK_OBJECT_TYPE_DESCRIPTOR_SET);
122       if (!set->img_fmts)
123          goto err_free_set;
124 
125       set->img_attrib_bufs =
126          vk_zalloc(&device->vk.alloc,
127                    pan_size(ATTRIBUTE_BUFFER) * 2 * layout->num_imgs,
128                    8, VK_OBJECT_TYPE_DESCRIPTOR_SET);
129       if (!set->img_attrib_bufs)
130          goto err_free_set;
131    }
132 
133    for (unsigned i = 0; i < layout->binding_count; i++) {
134       if (!layout->bindings[i].immutable_samplers)
135          continue;
136 
137       for (unsigned j = 0; j < layout->bindings[i].array_size; j++) {
138          set->descs[layout->bindings[i].desc_idx].image.sampler =
139             layout->bindings[i].immutable_samplers[j];
140       }
141    }
142 
143    *out_set = set;
144    return VK_SUCCESS;
145 
146 err_free_set:
147    vk_free(&device->vk.alloc, set->textures);
148    vk_free(&device->vk.alloc, set->samplers);
149    vk_free(&device->vk.alloc, set->ssbos);
150    vk_free(&device->vk.alloc, set->dyn_ssbos);
151    vk_free(&device->vk.alloc, set->ubos);
152    vk_free(&device->vk.alloc, set->dyn_ubos);
153    vk_free(&device->vk.alloc, set->img_fmts);
154    vk_free(&device->vk.alloc, set->img_attrib_bufs);
155    vk_free(&device->vk.alloc, set->descs);
156    vk_object_free(&device->vk, NULL, set);
157    return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
158 }
159 
160 VkResult
panvk_per_arch(AllocateDescriptorSets)161 panvk_per_arch(AllocateDescriptorSets)(VkDevice _device,
162                                        const VkDescriptorSetAllocateInfo *pAllocateInfo,
163                                        VkDescriptorSet *pDescriptorSets)
164 {
165    VK_FROM_HANDLE(panvk_device, device, _device);
166    VK_FROM_HANDLE(panvk_descriptor_pool, pool, pAllocateInfo->descriptorPool);
167    VkResult result;
168    unsigned i;
169 
170    for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
171       VK_FROM_HANDLE(panvk_descriptor_set_layout, layout,
172                      pAllocateInfo->pSetLayouts[i]);
173       struct panvk_descriptor_set *set = NULL;
174 
175       result = panvk_per_arch(descriptor_set_create)(device, pool, layout, &set);
176       if (result != VK_SUCCESS)
177          goto err_free_sets;
178 
179       pDescriptorSets[i] = panvk_descriptor_set_to_handle(set);
180    }
181 
182    return VK_SUCCESS;
183 
184 err_free_sets:
185    panvk_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool, i, pDescriptorSets);
186    for (i = 0; i < pAllocateInfo->descriptorSetCount; i++)
187       pDescriptorSets[i] = VK_NULL_HANDLE;
188 
189    return result;
190 }
191 
192 static void
panvk_set_buffer_desc(struct panvk_buffer_desc * bdesc,const VkDescriptorBufferInfo * pBufferInfo)193 panvk_set_buffer_desc(struct panvk_buffer_desc *bdesc,
194                       const VkDescriptorBufferInfo *pBufferInfo)
195 {
196    VK_FROM_HANDLE(panvk_buffer, buffer, pBufferInfo->buffer);
197 
198    bdesc->buffer = buffer;
199    bdesc->offset = pBufferInfo->offset;
200    bdesc->size = pBufferInfo->range;
201 }
202 
203 static void
panvk_per_arch(set_ubo_desc)204 panvk_per_arch(set_ubo_desc)(void *ubo,
205                              const VkDescriptorBufferInfo *pBufferInfo)
206 {
207    VK_FROM_HANDLE(panvk_buffer, buffer, pBufferInfo->buffer);
208    size_t size = pBufferInfo->range == VK_WHOLE_SIZE ?
209                  (buffer->bo->size - pBufferInfo->offset) :
210                  pBufferInfo->range;
211 
212    panvk_per_arch(emit_ubo)(buffer->bo->ptr.gpu + pBufferInfo->offset, size,  ubo);
213 }
214 
215 static void
panvk_set_sampler_desc(void * desc,const VkDescriptorImageInfo * pImageInfo)216 panvk_set_sampler_desc(void *desc,
217                        const VkDescriptorImageInfo *pImageInfo)
218 {
219    VK_FROM_HANDLE(panvk_sampler, sampler, pImageInfo->sampler);
220 
221    memcpy(desc, &sampler->desc, sizeof(sampler->desc));
222 }
223 
224 static void
panvk_per_arch(set_texture_desc)225 panvk_per_arch(set_texture_desc)(struct panvk_descriptor_set *set,
226                                  unsigned idx,
227                                  const VkDescriptorImageInfo *pImageInfo)
228 {
229    VK_FROM_HANDLE(panvk_image_view, view, pImageInfo->imageView);
230 
231 #if PAN_ARCH >= 6
232    memcpy(&((struct mali_texture_packed *)set->textures)[idx],
233           view->descs.tex, pan_size(TEXTURE));
234 #else
235    ((mali_ptr *)set->textures)[idx] = view->bo->ptr.gpu;
236 #endif
237 }
238 
239 static void
panvk_set_tex_buf_desc(struct panvk_device * dev,struct panvk_descriptor_set * set,unsigned idx,const VkBufferView bufferView)240 panvk_set_tex_buf_desc(struct panvk_device *dev,
241                        struct panvk_descriptor_set *set,
242                        unsigned idx,
243                        const VkBufferView bufferView)
244 {
245    VK_FROM_HANDLE(panvk_buffer_view, view, bufferView);
246 
247 #if PAN_ARCH >= 6
248    memcpy(&((struct mali_texture_packed *)set->textures)[idx],
249           view->descs.tex, pan_size(TEXTURE));
250 #else
251    ((mali_ptr *)set->textures)[idx] = view->bo->ptr.gpu;
252 #endif
253 }
254 
255 static void
panvk_set_img_desc(struct panvk_device * dev,struct panvk_descriptor_set * set,unsigned idx,const VkDescriptorImageInfo * pImageInfo)256 panvk_set_img_desc(struct panvk_device *dev,
257                    struct panvk_descriptor_set *set,
258                    unsigned idx,
259                    const VkDescriptorImageInfo *pImageInfo)
260 {
261    const struct panfrost_device *pdev = &dev->physical_device->pdev;
262    VK_FROM_HANDLE(panvk_image_view, view, pImageInfo->imageView);
263    void *attrib_buf = (uint8_t *)set->img_attrib_bufs + (pan_size(ATTRIBUTE_BUFFER) * 2 * idx);
264 
265    set->img_fmts[idx] = pdev->formats[view->pview.format].hw;
266    memcpy(attrib_buf, view->descs.img_attrib_buf, pan_size(ATTRIBUTE_BUFFER) * 2);
267 }
268 
269 static void
panvk_set_img_buf_desc(struct panvk_device * dev,struct panvk_descriptor_set * set,unsigned idx,const VkBufferView bufferView)270 panvk_set_img_buf_desc(struct panvk_device *dev,
271                        struct panvk_descriptor_set *set,
272                        unsigned idx,
273                        const VkBufferView bufferView)
274 {
275    const struct panfrost_device *pdev = &dev->physical_device->pdev;
276    VK_FROM_HANDLE(panvk_buffer_view, view, bufferView);
277 
278    void *attrib_buf = (uint8_t *)set->img_attrib_bufs + (pan_size(ATTRIBUTE_BUFFER) * 2 * idx);
279 
280    set->img_fmts[idx] = pdev->formats[view->fmt].hw;
281    memcpy(attrib_buf, view->descs.img_attrib_buf, pan_size(ATTRIBUTE_BUFFER) * 2);
282 }
283 
284 static void
panvk_per_arch(write_descriptor_set)285 panvk_per_arch(write_descriptor_set)(struct panvk_device *dev,
286                                      const VkWriteDescriptorSet *pDescriptorWrite)
287 {
288    VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorWrite->dstSet);
289    const struct panvk_descriptor_set_layout *layout = set->layout;
290    unsigned dest_offset = pDescriptorWrite->dstArrayElement;
291    unsigned binding = pDescriptorWrite->dstBinding;
292    struct mali_uniform_buffer_packed *ubos = set->ubos;
293    struct mali_sampler_packed *samplers = set->samplers;
294    unsigned src_offset = 0;
295 
296    while (src_offset < pDescriptorWrite->descriptorCount &&
297           binding < layout->binding_count) {
298       const struct panvk_descriptor_set_binding_layout *binding_layout =
299          &layout->bindings[binding];
300 
301       if (!binding_layout->array_size) {
302          binding++;
303          dest_offset = 0;
304          continue;
305       }
306 
307       assert(pDescriptorWrite->descriptorType == binding_layout->type);
308       unsigned ndescs = MIN2(pDescriptorWrite->descriptorCount - src_offset,
309                              binding_layout->array_size - dest_offset);
310       assert(binding_layout->desc_idx + dest_offset + ndescs <= set->layout->num_descs);
311 
312       switch (pDescriptorWrite->descriptorType) {
313       case VK_DESCRIPTOR_TYPE_SAMPLER:
314       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
315       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
316          for (unsigned i = 0; i < ndescs; i++) {
317             const VkDescriptorImageInfo *info = &pDescriptorWrite->pImageInfo[src_offset + i];
318 
319             if ((pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
320                  pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
321                 !binding_layout->immutable_samplers) {
322                unsigned sampler = binding_layout->sampler_idx + dest_offset + i;
323 
324                panvk_set_sampler_desc(&samplers[sampler], info);
325             }
326 
327             if (pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
328                 pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
329                unsigned tex = binding_layout->tex_idx + dest_offset + i;
330 
331                panvk_per_arch(set_texture_desc)(set, tex, info);
332             }
333          }
334          break;
335 
336       case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
337          for (unsigned i = 0; i < ndescs; i++) {
338             unsigned tex = binding_layout->tex_idx + dest_offset + i;
339             panvk_set_tex_buf_desc(dev, set, tex,
340                                    pDescriptorWrite->pTexelBufferView[src_offset + i]);
341          }
342          break;
343 
344       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
345       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
346          for (unsigned i = 0; i < ndescs; i++) {
347             const VkDescriptorImageInfo *info = &pDescriptorWrite->pImageInfo[src_offset + i];
348             unsigned img = binding_layout->img_idx + dest_offset + i;
349 
350             panvk_set_img_desc(dev, set, img, info);
351          }
352          break;
353 
354       case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
355          for (unsigned i = 0; i < ndescs; i++) {
356             unsigned img = binding_layout->img_idx + dest_offset + i;
357             panvk_set_img_buf_desc(dev, set, img,
358                                    pDescriptorWrite->pTexelBufferView[src_offset + i]);
359          }
360          break;
361 
362       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
363          for (unsigned i = 0; i < ndescs; i++) {
364             unsigned ubo = binding_layout->ubo_idx + dest_offset + i;
365             panvk_per_arch(set_ubo_desc)(&ubos[ubo],
366                                          &pDescriptorWrite->pBufferInfo[src_offset + i]);
367          }
368          break;
369       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
370          for (unsigned i = 0; i < ndescs; i++) {
371             unsigned ubo = binding_layout->dyn_ubo_idx + dest_offset + i;
372             panvk_set_buffer_desc(&set->dyn_ubos[ubo], &pDescriptorWrite->pBufferInfo[src_offset + i]);
373          }
374          break;
375       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
376          for (unsigned i = 0; i < ndescs; i++) {
377             unsigned ssbo = binding_layout->ssbo_idx + dest_offset + i;
378             panvk_set_buffer_desc(&set->ssbos[ssbo], &pDescriptorWrite->pBufferInfo[src_offset + i]);
379          }
380          break;
381       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
382          for (unsigned i = 0; i < ndescs; i++) {
383             unsigned ssbo = binding_layout->dyn_ssbo_idx + dest_offset + i;
384             panvk_set_buffer_desc(&set->dyn_ssbos[ssbo], &pDescriptorWrite->pBufferInfo[src_offset + i]);
385          }
386          break;
387       default:
388          unreachable("Invalid type");
389       }
390 
391       src_offset += ndescs;
392       binding++;
393       dest_offset = 0;
394    }
395 }
396 
397 static void
panvk_copy_descriptor_set(struct panvk_device * dev,const VkCopyDescriptorSet * pDescriptorCopy)398 panvk_copy_descriptor_set(struct panvk_device *dev,
399                           const VkCopyDescriptorSet *pDescriptorCopy)
400 {
401    VK_FROM_HANDLE(panvk_descriptor_set, dest_set, pDescriptorCopy->dstSet);
402    VK_FROM_HANDLE(panvk_descriptor_set, src_set, pDescriptorCopy->srcSet);
403    const struct panvk_descriptor_set_layout *dest_layout = dest_set->layout;
404    const struct panvk_descriptor_set_layout *src_layout = dest_set->layout;
405    unsigned dest_offset = pDescriptorCopy->dstArrayElement;
406    unsigned src_offset = pDescriptorCopy->srcArrayElement;
407    unsigned dest_binding = pDescriptorCopy->dstBinding;
408    unsigned src_binding = pDescriptorCopy->srcBinding;
409    unsigned desc_count = pDescriptorCopy->descriptorCount;
410 
411    while (desc_count && src_binding < src_layout->binding_count &&
412           dest_binding < dest_layout->binding_count) {
413       const struct panvk_descriptor_set_binding_layout *dest_binding_layout =
414          &src_layout->bindings[dest_binding];
415 
416       if (!dest_binding_layout->array_size) {
417          dest_binding++;
418          dest_offset = 0;
419          continue;
420       }
421 
422       const struct panvk_descriptor_set_binding_layout *src_binding_layout =
423          &src_layout->bindings[src_binding];
424 
425       if (!src_binding_layout->array_size) {
426          src_binding++;
427          src_offset = 0;
428          continue;
429       }
430 
431       assert(dest_binding_layout->type == src_binding_layout->type);
432 
433       unsigned ndescs = MAX3(desc_count,
434                              dest_binding_layout->array_size - dest_offset,
435                              src_binding_layout->array_size - src_offset);
436 
437       struct panvk_descriptor *dest_descs = dest_set->descs + dest_binding_layout->desc_idx + dest_offset;
438       struct panvk_descriptor *src_descs = src_set->descs + src_binding_layout->desc_idx + src_offset;
439       memcpy(dest_descs, src_descs, ndescs * sizeof(*dest_descs));
440       desc_count -= ndescs;
441       dest_offset += ndescs;
442       if (dest_offset == dest_binding_layout->array_size) {
443          dest_binding++;
444          dest_offset = 0;
445          continue;
446       }
447       src_offset += ndescs;
448       if (src_offset == src_binding_layout->array_size) {
449          src_binding++;
450          src_offset = 0;
451          continue;
452       }
453    }
454 
455    assert(!desc_count);
456 }
457 
458 void
panvk_per_arch(UpdateDescriptorSets)459 panvk_per_arch(UpdateDescriptorSets)(VkDevice _device,
460                                      uint32_t descriptorWriteCount,
461                                      const VkWriteDescriptorSet *pDescriptorWrites,
462                                      uint32_t descriptorCopyCount,
463                                      const VkCopyDescriptorSet *pDescriptorCopies)
464 {
465    VK_FROM_HANDLE(panvk_device, dev, _device);
466 
467    for (unsigned i = 0; i < descriptorWriteCount; i++)
468       panvk_per_arch(write_descriptor_set)(dev, &pDescriptorWrites[i]);
469    for (unsigned i = 0; i < descriptorCopyCount; i++)
470       panvk_copy_descriptor_set(dev, &pDescriptorCopies[i]);
471 }
472