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
45static VkResult
46panvk_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
106err_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
115VkResult
116panvk_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
139err_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
147static void
148panvk_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
158static void
159panvk_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
166static void
167panvk_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
176static void
177panvk_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
188static void
189panvk_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
197static void
198panvk_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
212static void
213panvk_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
301static void
302panvk_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
362void
363panvk_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