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_samplers) {
76       set->samplers = vk_zalloc(&device->vk.alloc,
77                                 pan_size(SAMPLER) * layout->num_samplers, 8,
78                                 VK_OBJECT_TYPE_DESCRIPTOR_SET);
79       if (!set->samplers)
80          goto err_free_set;
81    }
82 
83    if (layout->num_textures) {
84       set->textures =
85          vk_zalloc(&device->vk.alloc,
86                    (PAN_ARCH >= 6 ? pan_size(TEXTURE) : sizeof(mali_ptr)) *
87                    layout->num_textures,
88                    8, VK_OBJECT_TYPE_DESCRIPTOR_SET);
89       if (!set->textures)
90          goto err_free_set;
91    }
92 
93    for (unsigned i = 0; i < layout->binding_count; i++) {
94       if (!layout->bindings[i].immutable_samplers)
95          continue;
96 
97       for (unsigned j = 0; j < layout->bindings[i].array_size; j++) {
98          set->descs[layout->bindings[i].desc_idx].image.sampler =
99             layout->bindings[i].immutable_samplers[j];
100       }
101    }
102 
103    *out_set = set;
104    return VK_SUCCESS;
105 
106 err_free_set:
107    vk_free(&device->vk.alloc, set->textures);
108    vk_free(&device->vk.alloc, set->samplers);
109    vk_free(&device->vk.alloc, set->ubos);
110    vk_free(&device->vk.alloc, set->descs);
111    vk_object_free(&device->vk, NULL, set);
112    return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
113 }
114 
115 VkResult
panvk_per_arch(AllocateDescriptorSets)116 panvk_per_arch(AllocateDescriptorSets)(VkDevice _device,
117                                        const VkDescriptorSetAllocateInfo *pAllocateInfo,
118                                        VkDescriptorSet *pDescriptorSets)
119 {
120    VK_FROM_HANDLE(panvk_device, device, _device);
121    VK_FROM_HANDLE(panvk_descriptor_pool, pool, pAllocateInfo->descriptorPool);
122    VkResult result;
123    unsigned i;
124 
125    for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
126       VK_FROM_HANDLE(panvk_descriptor_set_layout, layout,
127                      pAllocateInfo->pSetLayouts[i]);
128       struct panvk_descriptor_set *set = NULL;
129 
130       result = panvk_per_arch(descriptor_set_create)(device, pool, layout, &set);
131       if (result != VK_SUCCESS)
132          goto err_free_sets;
133 
134       pDescriptorSets[i] = panvk_descriptor_set_to_handle(set);
135    }
136 
137    return VK_SUCCESS;
138 
139 err_free_sets:
140    panvk_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool, i, pDescriptorSets);
141    for (i = 0; i < pAllocateInfo->descriptorSetCount; i++)
142       pDescriptorSets[i] = VK_NULL_HANDLE;
143 
144    return result;
145 }
146 
147 static void
panvk_set_image_desc(struct panvk_descriptor * desc,const VkDescriptorImageInfo * pImageInfo)148 panvk_set_image_desc(struct panvk_descriptor *desc,
149                      const VkDescriptorImageInfo *pImageInfo)
150 {
151    VK_FROM_HANDLE(panvk_sampler, sampler, pImageInfo->sampler);
152    VK_FROM_HANDLE(panvk_image_view, image_view, pImageInfo->imageView);
153    desc->image.sampler = sampler;
154    desc->image.view = image_view;
155    desc->image.layout = pImageInfo->imageLayout;
156 }
157 
158 static void
panvk_set_texel_buffer_view_desc(struct panvk_descriptor * desc,const VkBufferView * pTexelBufferView)159 panvk_set_texel_buffer_view_desc(struct panvk_descriptor *desc,
160                                  const VkBufferView *pTexelBufferView)
161 {
162    VK_FROM_HANDLE(panvk_buffer_view, buffer_view, *pTexelBufferView);
163    desc->buffer_view = buffer_view;
164 }
165 
166 static void
panvk_set_buffer_info_desc(struct panvk_descriptor * desc,const VkDescriptorBufferInfo * pBufferInfo)167 panvk_set_buffer_info_desc(struct panvk_descriptor *desc,
168                            const VkDescriptorBufferInfo *pBufferInfo)
169 {
170    VK_FROM_HANDLE(panvk_buffer, buffer, pBufferInfo->buffer);
171    desc->buffer_info.buffer = buffer;
172    desc->buffer_info.offset = pBufferInfo->offset;
173    desc->buffer_info.range = pBufferInfo->range;
174 }
175 
176 static void
panvk_per_arch(set_ubo_desc)177 panvk_per_arch(set_ubo_desc)(void *ubo,
178                              const VkDescriptorBufferInfo *pBufferInfo)
179 {
180    VK_FROM_HANDLE(panvk_buffer, buffer, pBufferInfo->buffer);
181    size_t size = pBufferInfo->range == VK_WHOLE_SIZE ?
182                  (buffer->bo->size - pBufferInfo->offset) :
183                  pBufferInfo->range;
184 
185    panvk_per_arch(emit_ubo)(buffer->bo->ptr.gpu + pBufferInfo->offset, size,  ubo);
186 }
187 
188 static void
panvk_set_sampler_desc(void * desc,const VkDescriptorImageInfo * pImageInfo)189 panvk_set_sampler_desc(void *desc,
190                        const VkDescriptorImageInfo *pImageInfo)
191 {
192    VK_FROM_HANDLE(panvk_sampler, sampler, pImageInfo->sampler);
193 
194    memcpy(desc, &sampler->desc, sizeof(sampler->desc));
195 }
196 
197 static void
panvk_per_arch(set_texture_desc)198 panvk_per_arch(set_texture_desc)(struct panvk_descriptor_set *set,
199                                  unsigned idx,
200                                  const VkDescriptorImageInfo *pImageInfo)
201 {
202    VK_FROM_HANDLE(panvk_image_view, view, pImageInfo->imageView);
203 
204 #if PAN_ARCH >= 6
205    memcpy(&((struct mali_texture_packed *)set->textures)[idx],
206           view->descs.tex, pan_size(TEXTURE));
207 #else
208    ((mali_ptr *)set->textures)[idx] = view->bo->ptr.gpu;
209 #endif
210 }
211 
212 static void
panvk_per_arch(write_descriptor_set)213 panvk_per_arch(write_descriptor_set)(struct panvk_device *dev,
214                                      const VkWriteDescriptorSet *pDescriptorWrite)
215 {
216    VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorWrite->dstSet);
217    const struct panvk_descriptor_set_layout *layout = set->layout;
218    unsigned dest_offset = pDescriptorWrite->dstArrayElement;
219    unsigned binding = pDescriptorWrite->dstBinding;
220    struct mali_uniform_buffer_packed *ubos = set->ubos;
221    struct mali_sampler_packed *samplers = set->samplers;
222    unsigned src_offset = 0;
223 
224    while (src_offset < pDescriptorWrite->descriptorCount &&
225           binding < layout->binding_count) {
226       const struct panvk_descriptor_set_binding_layout *binding_layout =
227          &layout->bindings[binding];
228 
229       if (!binding_layout->array_size) {
230          binding++;
231          dest_offset = 0;
232          continue;
233       }
234 
235       assert(pDescriptorWrite->descriptorType == binding_layout->type);
236       unsigned ndescs = MIN2(pDescriptorWrite->descriptorCount - src_offset,
237                              binding_layout->array_size - dest_offset);
238       struct panvk_descriptor *descs = &set->descs[binding_layout->desc_idx + dest_offset];
239       assert(binding_layout->desc_idx + dest_offset + ndescs <= set->layout->num_descs);
240 
241       switch (pDescriptorWrite->descriptorType) {
242       case VK_DESCRIPTOR_TYPE_SAMPLER:
243       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
244       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
245          for (unsigned i = 0; i < ndescs; i++) {
246             const VkDescriptorImageInfo *info = &pDescriptorWrite->pImageInfo[src_offset + i];
247 
248             if ((pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
249                  pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
250                 !binding_layout->immutable_samplers) {
251                unsigned sampler = binding_layout->sampler_idx + dest_offset + i;
252 
253                panvk_set_sampler_desc(&samplers[sampler], info);
254             }
255 
256             if (pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
257                 pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
258                unsigned tex = binding_layout->tex_idx + dest_offset + i;
259 
260                panvk_per_arch(set_texture_desc)(set, tex, info);
261             }
262          }
263          break;
264 
265       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
266       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
267          for (unsigned i = 0; i < ndescs; i++)
268             panvk_set_image_desc(&descs[i], &pDescriptorWrite->pImageInfo[src_offset + i]);
269          break;
270 
271       case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
272       case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
273          for (unsigned i = 0; i < ndescs; i++)
274             panvk_set_texel_buffer_view_desc(&descs[i], &pDescriptorWrite->pTexelBufferView[src_offset + i]);
275          break;
276 
277       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
278       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
279          for (unsigned i = 0; i < ndescs; i++) {
280             unsigned ubo = binding_layout->ubo_idx + dest_offset + i;
281             panvk_per_arch(set_ubo_desc)(&ubos[ubo],
282                                          &pDescriptorWrite->pBufferInfo[src_offset + i]);
283          }
284          break;
285 
286       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
287       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
288          for (unsigned i = 0; i < ndescs; i++)
289             panvk_set_buffer_info_desc(&descs[i], &pDescriptorWrite->pBufferInfo[src_offset + i]);
290          break;
291       default:
292          unreachable("Invalid type");
293       }
294 
295       src_offset += ndescs;
296       binding++;
297       dest_offset = 0;
298    }
299 }
300 
301 static void
panvk_copy_descriptor_set(struct panvk_device * dev,const VkCopyDescriptorSet * pDescriptorCopy)302 panvk_copy_descriptor_set(struct panvk_device *dev,
303                           const VkCopyDescriptorSet *pDescriptorCopy)
304 {
305    VK_FROM_HANDLE(panvk_descriptor_set, dest_set, pDescriptorCopy->dstSet);
306    VK_FROM_HANDLE(panvk_descriptor_set, src_set, pDescriptorCopy->srcSet);
307    const struct panvk_descriptor_set_layout *dest_layout = dest_set->layout;
308    const struct panvk_descriptor_set_layout *src_layout = dest_set->layout;
309    unsigned dest_offset = pDescriptorCopy->dstArrayElement;
310    unsigned src_offset = pDescriptorCopy->srcArrayElement;
311    unsigned dest_binding = pDescriptorCopy->dstBinding;
312    unsigned src_binding = pDescriptorCopy->srcBinding;
313    unsigned desc_count = pDescriptorCopy->descriptorCount;
314 
315    while (desc_count && src_binding < src_layout->binding_count &&
316           dest_binding < dest_layout->binding_count) {
317       const struct panvk_descriptor_set_binding_layout *dest_binding_layout =
318          &src_layout->bindings[dest_binding];
319 
320       if (!dest_binding_layout->array_size) {
321          dest_binding++;
322          dest_offset = 0;
323          continue;
324       }
325 
326       const struct panvk_descriptor_set_binding_layout *src_binding_layout =
327          &src_layout->bindings[src_binding];
328 
329       if (!src_binding_layout->array_size) {
330          src_binding++;
331          src_offset = 0;
332          continue;
333       }
334 
335       assert(dest_binding_layout->type == src_binding_layout->type);
336 
337       unsigned ndescs = MAX3(desc_count,
338                              dest_binding_layout->array_size - dest_offset,
339                              src_binding_layout->array_size - src_offset);
340 
341       struct panvk_descriptor *dest_descs = dest_set->descs + dest_binding_layout->desc_idx + dest_offset;
342       struct panvk_descriptor *src_descs = src_set->descs + src_binding_layout->desc_idx + src_offset;
343       memcpy(dest_descs, src_descs, ndescs * sizeof(*dest_descs));
344       desc_count -= ndescs;
345       dest_offset += ndescs;
346       if (dest_offset == dest_binding_layout->array_size) {
347          dest_binding++;
348          dest_offset = 0;
349          continue;
350       }
351       src_offset += ndescs;
352       if (src_offset == src_binding_layout->array_size) {
353          src_binding++;
354          src_offset = 0;
355          continue;
356       }
357    }
358 
359    assert(!desc_count);
360 }
361 
362 void
panvk_per_arch(UpdateDescriptorSets)363 panvk_per_arch(UpdateDescriptorSets)(VkDevice _device,
364                                      uint32_t descriptorWriteCount,
365                                      const VkWriteDescriptorSet *pDescriptorWrites,
366                                      uint32_t descriptorCopyCount,
367                                      const VkCopyDescriptorSet *pDescriptorCopies)
368 {
369    VK_FROM_HANDLE(panvk_device, dev, _device);
370 
371    for (unsigned i = 0; i < descriptorWriteCount; i++)
372       panvk_per_arch(write_descriptor_set)(dev, &pDescriptorWrites[i]);
373    for (unsigned i = 0; i < descriptorCopyCount; i++)
374       panvk_copy_descriptor_set(dev, &pDescriptorCopies[i]);
375 }
376