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
47void
48panvk_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
122VkResult
123panvk_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
204VkResult
205panvk_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
267void
268panvk_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
279VkResult
280panvk_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
289static void
290panvk_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
306VkResult
307panvk_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
324VkResult
325panvk_CreateDescriptorUpdateTemplate(VkDevice _device,
326                                     const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
327                                     const VkAllocationCallbacks *pAllocator,
328                                     VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)
329{
330   panvk_stub();
331   return VK_SUCCESS;
332}
333
334void
335panvk_DestroyDescriptorUpdateTemplate(VkDevice _device,
336                                      VkDescriptorUpdateTemplate descriptorUpdateTemplate,
337                                      const VkAllocationCallbacks *pAllocator)
338{
339   panvk_stub();
340}
341
342void
343panvk_UpdateDescriptorSetWithTemplate(VkDevice _device,
344                                      VkDescriptorSet descriptorSet,
345                                      VkDescriptorUpdateTemplate descriptorUpdateTemplate,
346                                      const void *pData)
347{
348   panvk_stub();
349}
350
351VkResult
352panvk_CreateSamplerYcbcrConversion(VkDevice device,
353                                   const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
354                                   const VkAllocationCallbacks *pAllocator,
355                                   VkSamplerYcbcrConversion *pYcbcrConversion)
356{
357   panvk_stub();
358   return VK_SUCCESS;
359}
360
361void
362panvk_DestroySamplerYcbcrConversion(VkDevice device,
363                                    VkSamplerYcbcrConversion ycbcrConversion,
364                                    const VkAllocationCallbacks *pAllocator)
365{
366   panvk_stub();
367}
368