1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2019 Raspberry Pi Ltd
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "vk_descriptors.h"
25bf215546Sopenharmony_ci#include "vk_util.h"
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "v3dv_private.h"
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci/*
30bf215546Sopenharmony_ci * For a given descriptor defined by the descriptor_set it belongs, its
31bf215546Sopenharmony_ci * binding layout, and array_index, it returns the map region assigned to it
32bf215546Sopenharmony_ci * from the descriptor pool bo.
33bf215546Sopenharmony_ci */
34bf215546Sopenharmony_cistatic void *
35bf215546Sopenharmony_cidescriptor_bo_map(struct v3dv_device *device,
36bf215546Sopenharmony_ci                  struct v3dv_descriptor_set *set,
37bf215546Sopenharmony_ci                  const struct v3dv_descriptor_set_binding_layout *binding_layout,
38bf215546Sopenharmony_ci                  uint32_t array_index)
39bf215546Sopenharmony_ci{
40bf215546Sopenharmony_ci   /* Inline uniform blocks use BO memory to store UBO contents, not
41bf215546Sopenharmony_ci    * descriptor data, so their descriptor BO size is 0 even though they
42bf215546Sopenharmony_ci    * do use BO memory.
43bf215546Sopenharmony_ci    */
44bf215546Sopenharmony_ci   uint32_t bo_size = v3dv_X(device, descriptor_bo_size)(binding_layout->type);
45bf215546Sopenharmony_ci   assert(bo_size > 0 ||
46bf215546Sopenharmony_ci          binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK);
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci   return set->pool->bo->map +
49bf215546Sopenharmony_ci      set->base_offset + binding_layout->descriptor_offset +
50bf215546Sopenharmony_ci      array_index * bo_size;
51bf215546Sopenharmony_ci}
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_cistatic bool
54bf215546Sopenharmony_cidescriptor_type_is_dynamic(VkDescriptorType type)
55bf215546Sopenharmony_ci{
56bf215546Sopenharmony_ci   switch (type) {
57bf215546Sopenharmony_ci   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
58bf215546Sopenharmony_ci   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
59bf215546Sopenharmony_ci      return true;
60bf215546Sopenharmony_ci      break;
61bf215546Sopenharmony_ci   default:
62bf215546Sopenharmony_ci      return false;
63bf215546Sopenharmony_ci   }
64bf215546Sopenharmony_ci}
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci/*
67bf215546Sopenharmony_ci * Tries to get a real descriptor using a descriptor map index from the
68bf215546Sopenharmony_ci * descriptor_state + pipeline_layout.
69bf215546Sopenharmony_ci */
70bf215546Sopenharmony_cistruct v3dv_descriptor *
71bf215546Sopenharmony_civ3dv_descriptor_map_get_descriptor(struct v3dv_descriptor_state *descriptor_state,
72bf215546Sopenharmony_ci                                   struct v3dv_descriptor_map *map,
73bf215546Sopenharmony_ci                                   struct v3dv_pipeline_layout *pipeline_layout,
74bf215546Sopenharmony_ci                                   uint32_t index,
75bf215546Sopenharmony_ci                                   uint32_t *dynamic_offset)
76bf215546Sopenharmony_ci{
77bf215546Sopenharmony_ci   assert(index < map->num_desc);
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci   uint32_t set_number = map->set[index];
80bf215546Sopenharmony_ci   assert((descriptor_state->valid & 1 << set_number));
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   struct v3dv_descriptor_set *set =
83bf215546Sopenharmony_ci      descriptor_state->descriptor_sets[set_number];
84bf215546Sopenharmony_ci   assert(set);
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci   uint32_t binding_number = map->binding[index];
87bf215546Sopenharmony_ci   assert(binding_number < set->layout->binding_count);
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   const struct v3dv_descriptor_set_binding_layout *binding_layout =
90bf215546Sopenharmony_ci      &set->layout->binding[binding_number];
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci   uint32_t array_index = map->array_index[index];
93bf215546Sopenharmony_ci   assert(array_index < binding_layout->array_size);
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   if (descriptor_type_is_dynamic(binding_layout->type)) {
96bf215546Sopenharmony_ci      uint32_t dynamic_offset_index =
97bf215546Sopenharmony_ci         pipeline_layout->set[set_number].dynamic_offset_start +
98bf215546Sopenharmony_ci         binding_layout->dynamic_offset_index + array_index;
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci      *dynamic_offset = descriptor_state->dynamic_offsets[dynamic_offset_index];
101bf215546Sopenharmony_ci   }
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   return &set->descriptors[binding_layout->descriptor_index + array_index];
104bf215546Sopenharmony_ci}
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci/* Equivalent to map_get_descriptor but it returns a reloc with the bo
107bf215546Sopenharmony_ci * associated with that descriptor (suballocation of the descriptor pool bo)
108bf215546Sopenharmony_ci *
109bf215546Sopenharmony_ci * It also returns the descriptor type, so the caller could do extra
110bf215546Sopenharmony_ci * validation or adding extra offsets if the bo contains more that one field.
111bf215546Sopenharmony_ci */
112bf215546Sopenharmony_cistruct v3dv_cl_reloc
113bf215546Sopenharmony_civ3dv_descriptor_map_get_descriptor_bo(struct v3dv_device *device,
114bf215546Sopenharmony_ci                                      struct v3dv_descriptor_state *descriptor_state,
115bf215546Sopenharmony_ci                                      struct v3dv_descriptor_map *map,
116bf215546Sopenharmony_ci                                      struct v3dv_pipeline_layout *pipeline_layout,
117bf215546Sopenharmony_ci                                      uint32_t index,
118bf215546Sopenharmony_ci                                      VkDescriptorType *out_type)
119bf215546Sopenharmony_ci{
120bf215546Sopenharmony_ci   assert(index < map->num_desc);
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   uint32_t set_number = map->set[index];
123bf215546Sopenharmony_ci   assert(descriptor_state->valid & 1 << set_number);
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci   struct v3dv_descriptor_set *set =
126bf215546Sopenharmony_ci      descriptor_state->descriptor_sets[set_number];
127bf215546Sopenharmony_ci   assert(set);
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci   uint32_t binding_number = map->binding[index];
130bf215546Sopenharmony_ci   assert(binding_number < set->layout->binding_count);
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   const struct v3dv_descriptor_set_binding_layout *binding_layout =
133bf215546Sopenharmony_ci      &set->layout->binding[binding_number];
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   assert(binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK ||
136bf215546Sopenharmony_ci          v3dv_X(device, descriptor_bo_size)(binding_layout->type) > 0);
137bf215546Sopenharmony_ci   if (out_type)
138bf215546Sopenharmony_ci      *out_type = binding_layout->type;
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci   uint32_t array_index = map->array_index[index];
141bf215546Sopenharmony_ci   assert(array_index < binding_layout->array_size);
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci   struct v3dv_cl_reloc reloc = {
144bf215546Sopenharmony_ci      .bo = set->pool->bo,
145bf215546Sopenharmony_ci      .offset = set->base_offset + binding_layout->descriptor_offset +
146bf215546Sopenharmony_ci      array_index * v3dv_X(device, descriptor_bo_size)(binding_layout->type),
147bf215546Sopenharmony_ci   };
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   return reloc;
150bf215546Sopenharmony_ci}
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci/*
153bf215546Sopenharmony_ci * The difference between this method and v3dv_descriptor_map_get_descriptor,
154bf215546Sopenharmony_ci * is that if the sampler are added as immutable when creating the set layout,
155bf215546Sopenharmony_ci * they are bound to the set layout, so not part of the descriptor per
156bf215546Sopenharmony_ci * se. This method return early in that case.
157bf215546Sopenharmony_ci */
158bf215546Sopenharmony_ciconst struct v3dv_sampler *
159bf215546Sopenharmony_civ3dv_descriptor_map_get_sampler(struct v3dv_descriptor_state *descriptor_state,
160bf215546Sopenharmony_ci                                struct v3dv_descriptor_map *map,
161bf215546Sopenharmony_ci                                struct v3dv_pipeline_layout *pipeline_layout,
162bf215546Sopenharmony_ci                                uint32_t index)
163bf215546Sopenharmony_ci{
164bf215546Sopenharmony_ci   assert(index < map->num_desc);
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   uint32_t set_number = map->set[index];
167bf215546Sopenharmony_ci   assert(descriptor_state->valid & 1 << set_number);
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   struct v3dv_descriptor_set *set =
170bf215546Sopenharmony_ci      descriptor_state->descriptor_sets[set_number];
171bf215546Sopenharmony_ci   assert(set);
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci   uint32_t binding_number = map->binding[index];
174bf215546Sopenharmony_ci   assert(binding_number < set->layout->binding_count);
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   const struct v3dv_descriptor_set_binding_layout *binding_layout =
177bf215546Sopenharmony_ci      &set->layout->binding[binding_number];
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   uint32_t array_index = map->array_index[index];
180bf215546Sopenharmony_ci   assert(array_index < binding_layout->array_size);
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   if (binding_layout->immutable_samplers_offset != 0) {
183bf215546Sopenharmony_ci      assert(binding_layout->type == VK_DESCRIPTOR_TYPE_SAMPLER ||
184bf215546Sopenharmony_ci             binding_layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci      const struct v3dv_sampler *immutable_samplers =
187bf215546Sopenharmony_ci         v3dv_immutable_samplers(set->layout, binding_layout);
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci      assert(immutable_samplers);
190bf215546Sopenharmony_ci      const struct v3dv_sampler *sampler = &immutable_samplers[array_index];
191bf215546Sopenharmony_ci      assert(sampler);
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci      return sampler;
194bf215546Sopenharmony_ci   }
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci   struct v3dv_descriptor *descriptor =
197bf215546Sopenharmony_ci      &set->descriptors[binding_layout->descriptor_index + array_index];
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   assert(descriptor->type == VK_DESCRIPTOR_TYPE_SAMPLER ||
200bf215546Sopenharmony_ci          descriptor->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   assert(descriptor->sampler);
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci   return descriptor->sampler;
205bf215546Sopenharmony_ci}
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_cistruct v3dv_cl_reloc
209bf215546Sopenharmony_civ3dv_descriptor_map_get_sampler_state(struct v3dv_device *device,
210bf215546Sopenharmony_ci                                      struct v3dv_descriptor_state *descriptor_state,
211bf215546Sopenharmony_ci                                      struct v3dv_descriptor_map *map,
212bf215546Sopenharmony_ci                                      struct v3dv_pipeline_layout *pipeline_layout,
213bf215546Sopenharmony_ci                                      uint32_t index)
214bf215546Sopenharmony_ci{
215bf215546Sopenharmony_ci   VkDescriptorType type;
216bf215546Sopenharmony_ci   struct v3dv_cl_reloc reloc =
217bf215546Sopenharmony_ci      v3dv_descriptor_map_get_descriptor_bo(device, descriptor_state, map,
218bf215546Sopenharmony_ci                                            pipeline_layout,
219bf215546Sopenharmony_ci                                            index, &type);
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci   assert(type == VK_DESCRIPTOR_TYPE_SAMPLER ||
222bf215546Sopenharmony_ci          type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci   if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
225bf215546Sopenharmony_ci      reloc.offset += v3dv_X(device, combined_image_sampler_sampler_state_offset)();
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci   return reloc;
228bf215546Sopenharmony_ci}
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_cistruct v3dv_bo*
231bf215546Sopenharmony_civ3dv_descriptor_map_get_texture_bo(struct v3dv_descriptor_state *descriptor_state,
232bf215546Sopenharmony_ci                                   struct v3dv_descriptor_map *map,
233bf215546Sopenharmony_ci                                   struct v3dv_pipeline_layout *pipeline_layout,
234bf215546Sopenharmony_ci                                   uint32_t index)
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci{
237bf215546Sopenharmony_ci   struct v3dv_descriptor *descriptor =
238bf215546Sopenharmony_ci      v3dv_descriptor_map_get_descriptor(descriptor_state, map,
239bf215546Sopenharmony_ci                                         pipeline_layout, index, NULL);
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci   switch (descriptor->type) {
242bf215546Sopenharmony_ci   case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
243bf215546Sopenharmony_ci   case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
244bf215546Sopenharmony_ci      assert(descriptor->buffer_view);
245bf215546Sopenharmony_ci      return descriptor->buffer_view->buffer->mem->bo;
246bf215546Sopenharmony_ci   case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
247bf215546Sopenharmony_ci   case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
248bf215546Sopenharmony_ci   case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
249bf215546Sopenharmony_ci   case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
250bf215546Sopenharmony_ci      assert(descriptor->image_view);
251bf215546Sopenharmony_ci      struct v3dv_image *image =
252bf215546Sopenharmony_ci         (struct v3dv_image *) descriptor->image_view->vk.image;
253bf215546Sopenharmony_ci      return image->mem->bo;
254bf215546Sopenharmony_ci   }
255bf215546Sopenharmony_ci   default:
256bf215546Sopenharmony_ci      unreachable("descriptor type doesn't has a texture bo");
257bf215546Sopenharmony_ci   }
258bf215546Sopenharmony_ci}
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_cistruct v3dv_cl_reloc
261bf215546Sopenharmony_civ3dv_descriptor_map_get_texture_shader_state(struct v3dv_device *device,
262bf215546Sopenharmony_ci                                             struct v3dv_descriptor_state *descriptor_state,
263bf215546Sopenharmony_ci                                             struct v3dv_descriptor_map *map,
264bf215546Sopenharmony_ci                                             struct v3dv_pipeline_layout *pipeline_layout,
265bf215546Sopenharmony_ci                                             uint32_t index)
266bf215546Sopenharmony_ci{
267bf215546Sopenharmony_ci   VkDescriptorType type;
268bf215546Sopenharmony_ci   struct v3dv_cl_reloc reloc =
269bf215546Sopenharmony_ci      v3dv_descriptor_map_get_descriptor_bo(device,
270bf215546Sopenharmony_ci                                            descriptor_state, map,
271bf215546Sopenharmony_ci                                            pipeline_layout,
272bf215546Sopenharmony_ci                                            index, &type);
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci   assert(type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
275bf215546Sopenharmony_ci          type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
276bf215546Sopenharmony_ci          type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ||
277bf215546Sopenharmony_ci          type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
278bf215546Sopenharmony_ci          type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
279bf215546Sopenharmony_ci          type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci   if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
282bf215546Sopenharmony_ci      reloc.offset += v3dv_X(device, combined_image_sampler_texture_state_offset)();
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci   return reloc;
285bf215546Sopenharmony_ci}
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_ci#define SHA1_UPDATE_VALUE(ctx, x) _mesa_sha1_update(ctx, &(x), sizeof(x));
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_cistatic void
290bf215546Sopenharmony_cisha1_update_descriptor_set_binding_layout(struct mesa_sha1 *ctx,
291bf215546Sopenharmony_ci                                          const struct v3dv_descriptor_set_binding_layout *layout)
292bf215546Sopenharmony_ci{
293bf215546Sopenharmony_ci   SHA1_UPDATE_VALUE(ctx, layout->type);
294bf215546Sopenharmony_ci   SHA1_UPDATE_VALUE(ctx, layout->array_size);
295bf215546Sopenharmony_ci   SHA1_UPDATE_VALUE(ctx, layout->descriptor_index);
296bf215546Sopenharmony_ci   SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_count);
297bf215546Sopenharmony_ci   SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_index);
298bf215546Sopenharmony_ci   SHA1_UPDATE_VALUE(ctx, layout->descriptor_offset);
299bf215546Sopenharmony_ci   SHA1_UPDATE_VALUE(ctx, layout->immutable_samplers_offset);
300bf215546Sopenharmony_ci}
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_cistatic void
303bf215546Sopenharmony_cisha1_update_descriptor_set_layout(struct mesa_sha1 *ctx,
304bf215546Sopenharmony_ci                                  const struct v3dv_descriptor_set_layout *layout)
305bf215546Sopenharmony_ci{
306bf215546Sopenharmony_ci   SHA1_UPDATE_VALUE(ctx, layout->flags);
307bf215546Sopenharmony_ci   SHA1_UPDATE_VALUE(ctx, layout->binding_count);
308bf215546Sopenharmony_ci   SHA1_UPDATE_VALUE(ctx, layout->shader_stages);
309bf215546Sopenharmony_ci   SHA1_UPDATE_VALUE(ctx, layout->descriptor_count);
310bf215546Sopenharmony_ci   SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_count);
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_ci   for (uint16_t i = 0; i < layout->binding_count; i++)
313bf215546Sopenharmony_ci      sha1_update_descriptor_set_binding_layout(ctx, &layout->binding[i]);
314bf215546Sopenharmony_ci}
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci/*
318bf215546Sopenharmony_ci * As anv and tu already points:
319bf215546Sopenharmony_ci *
320bf215546Sopenharmony_ci * "Pipeline layouts.  These have nothing to do with the pipeline.  They are
321bf215546Sopenharmony_ci * just multiple descriptor set layouts pasted together."
322bf215546Sopenharmony_ci */
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
325bf215546Sopenharmony_civ3dv_CreatePipelineLayout(VkDevice _device,
326bf215546Sopenharmony_ci                         const VkPipelineLayoutCreateInfo *pCreateInfo,
327bf215546Sopenharmony_ci                         const VkAllocationCallbacks *pAllocator,
328bf215546Sopenharmony_ci                         VkPipelineLayout *pPipelineLayout)
329bf215546Sopenharmony_ci{
330bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
331bf215546Sopenharmony_ci   struct v3dv_pipeline_layout *layout;
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci   assert(pCreateInfo->sType ==
334bf215546Sopenharmony_ci          VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci   layout = vk_object_zalloc(&device->vk, pAllocator, sizeof(*layout),
337bf215546Sopenharmony_ci                             VK_OBJECT_TYPE_PIPELINE_LAYOUT);
338bf215546Sopenharmony_ci   if (layout == NULL)
339bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci   layout->num_sets = pCreateInfo->setLayoutCount;
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   uint32_t dynamic_offset_count = 0;
344bf215546Sopenharmony_ci   for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) {
345bf215546Sopenharmony_ci      V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, set_layout,
346bf215546Sopenharmony_ci                     pCreateInfo->pSetLayouts[set]);
347bf215546Sopenharmony_ci      v3dv_descriptor_set_layout_ref(set_layout);
348bf215546Sopenharmony_ci      layout->set[set].layout = set_layout;
349bf215546Sopenharmony_ci      layout->set[set].dynamic_offset_start = dynamic_offset_count;
350bf215546Sopenharmony_ci      for (uint32_t b = 0; b < set_layout->binding_count; b++) {
351bf215546Sopenharmony_ci         dynamic_offset_count += set_layout->binding[b].array_size *
352bf215546Sopenharmony_ci            set_layout->binding[b].dynamic_offset_count;
353bf215546Sopenharmony_ci      }
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci      layout->shader_stages |= set_layout->shader_stages;
356bf215546Sopenharmony_ci   }
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci   layout->push_constant_size = 0;
359bf215546Sopenharmony_ci   for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
360bf215546Sopenharmony_ci      const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i;
361bf215546Sopenharmony_ci      layout->push_constant_size =
362bf215546Sopenharmony_ci         MAX2(layout->push_constant_size, range->offset + range->size);
363bf215546Sopenharmony_ci   }
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci   layout->push_constant_size = align(layout->push_constant_size, 4096);
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   layout->dynamic_offset_count = dynamic_offset_count;
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_ci   struct mesa_sha1 ctx;
370bf215546Sopenharmony_ci   _mesa_sha1_init(&ctx);
371bf215546Sopenharmony_ci   for (unsigned s = 0; s < layout->num_sets; s++) {
372bf215546Sopenharmony_ci      sha1_update_descriptor_set_layout(&ctx, layout->set[s].layout);
373bf215546Sopenharmony_ci      _mesa_sha1_update(&ctx, &layout->set[s].dynamic_offset_start,
374bf215546Sopenharmony_ci                        sizeof(layout->set[s].dynamic_offset_start));
375bf215546Sopenharmony_ci   }
376bf215546Sopenharmony_ci   _mesa_sha1_update(&ctx, &layout->num_sets, sizeof(layout->num_sets));
377bf215546Sopenharmony_ci   _mesa_sha1_final(&ctx, layout->sha1);
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci   *pPipelineLayout = v3dv_pipeline_layout_to_handle(layout);
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci   return VK_SUCCESS;
382bf215546Sopenharmony_ci}
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
385bf215546Sopenharmony_civ3dv_DestroyPipelineLayout(VkDevice _device,
386bf215546Sopenharmony_ci                          VkPipelineLayout _pipelineLayout,
387bf215546Sopenharmony_ci                          const VkAllocationCallbacks *pAllocator)
388bf215546Sopenharmony_ci{
389bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
390bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_pipeline_layout, pipeline_layout, _pipelineLayout);
391bf215546Sopenharmony_ci
392bf215546Sopenharmony_ci   if (!pipeline_layout)
393bf215546Sopenharmony_ci      return;
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pipeline_layout->num_sets; i++)
396bf215546Sopenharmony_ci      v3dv_descriptor_set_layout_unref(device, pipeline_layout->set[i].layout);
397bf215546Sopenharmony_ci
398bf215546Sopenharmony_ci   vk_object_free(&device->vk, pAllocator, pipeline_layout);
399bf215546Sopenharmony_ci}
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
402bf215546Sopenharmony_civ3dv_CreateDescriptorPool(VkDevice _device,
403bf215546Sopenharmony_ci                          const VkDescriptorPoolCreateInfo *pCreateInfo,
404bf215546Sopenharmony_ci                          const VkAllocationCallbacks *pAllocator,
405bf215546Sopenharmony_ci                          VkDescriptorPool *pDescriptorPool)
406bf215546Sopenharmony_ci{
407bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
408bf215546Sopenharmony_ci   struct v3dv_descriptor_pool *pool;
409bf215546Sopenharmony_ci   /* size is for the vulkan object descriptor pool. The final size would
410bf215546Sopenharmony_ci    * depend on some of FREE_DESCRIPTOR flags used
411bf215546Sopenharmony_ci    */
412bf215546Sopenharmony_ci   uint64_t size = sizeof(struct v3dv_descriptor_pool);
413bf215546Sopenharmony_ci   /* bo_size is for the descriptor related info that we need to have on a GPU
414bf215546Sopenharmony_ci    * address (so on v3dv_bo_alloc allocated memory), like for example the
415bf215546Sopenharmony_ci    * texture sampler state. Note that not all the descriptors use it
416bf215546Sopenharmony_ci    */
417bf215546Sopenharmony_ci   uint32_t bo_size = 0;
418bf215546Sopenharmony_ci   uint32_t descriptor_count = 0;
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci   const VkDescriptorPoolInlineUniformBlockCreateInfo *inline_info =
421bf215546Sopenharmony_ci      vk_find_struct_const(pCreateInfo->pNext,
422bf215546Sopenharmony_ci                           DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO);
423bf215546Sopenharmony_ci
424bf215546Sopenharmony_ci   for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
425bf215546Sopenharmony_ci      /* Verify supported descriptor type */
426bf215546Sopenharmony_ci      switch(pCreateInfo->pPoolSizes[i].type) {
427bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
428bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
429bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
430bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
431bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLER:
432bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
433bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
434bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
435bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
436bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
437bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
438bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
439bf215546Sopenharmony_ci         break;
440bf215546Sopenharmony_ci      default:
441bf215546Sopenharmony_ci         unreachable("Unimplemented descriptor type");
442bf215546Sopenharmony_ci         break;
443bf215546Sopenharmony_ci      }
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ci      assert(pCreateInfo->pPoolSizes[i].descriptorCount > 0);
446bf215546Sopenharmony_ci      if (pCreateInfo->pPoolSizes[i].type ==
447bf215546Sopenharmony_ci          VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
448bf215546Sopenharmony_ci         /* Inline uniform blocks are specified to use the descriptor array
449bf215546Sopenharmony_ci          * size as the size in bytes of the block.
450bf215546Sopenharmony_ci          */
451bf215546Sopenharmony_ci         assert(inline_info);
452bf215546Sopenharmony_ci         descriptor_count += inline_info->maxInlineUniformBlockBindings;
453bf215546Sopenharmony_ci         bo_size += pCreateInfo->pPoolSizes[i].descriptorCount;
454bf215546Sopenharmony_ci      } else {
455bf215546Sopenharmony_ci         descriptor_count += pCreateInfo->pPoolSizes[i].descriptorCount;
456bf215546Sopenharmony_ci         bo_size += v3dv_X(device, descriptor_bo_size)(pCreateInfo->pPoolSizes[i].type) *
457bf215546Sopenharmony_ci            pCreateInfo->pPoolSizes[i].descriptorCount;
458bf215546Sopenharmony_ci      }
459bf215546Sopenharmony_ci   }
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci   /* We align all our buffers to V3D_NON_COHERENT_ATOM_SIZE, make sure we
462bf215546Sopenharmony_ci    * allocate enough memory to honor that requirement for all our inline
463bf215546Sopenharmony_ci    * buffers too.
464bf215546Sopenharmony_ci    */
465bf215546Sopenharmony_ci   if (inline_info) {
466bf215546Sopenharmony_ci      bo_size += V3D_NON_COHERENT_ATOM_SIZE *
467bf215546Sopenharmony_ci                 inline_info->maxInlineUniformBlockBindings;
468bf215546Sopenharmony_ci   }
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_ci   if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) {
471bf215546Sopenharmony_ci      uint64_t host_size =
472bf215546Sopenharmony_ci         pCreateInfo->maxSets * sizeof(struct v3dv_descriptor_set);
473bf215546Sopenharmony_ci      host_size += sizeof(struct v3dv_descriptor) * descriptor_count;
474bf215546Sopenharmony_ci      size += host_size;
475bf215546Sopenharmony_ci   } else {
476bf215546Sopenharmony_ci      size += sizeof(struct v3dv_descriptor_pool_entry) * pCreateInfo->maxSets;
477bf215546Sopenharmony_ci   }
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci   pool = vk_object_zalloc(&device->vk, pAllocator, size,
480bf215546Sopenharmony_ci                           VK_OBJECT_TYPE_DESCRIPTOR_POOL);
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci   if (!pool)
483bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci   if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) {
486bf215546Sopenharmony_ci      pool->host_memory_base = (uint8_t*)pool + sizeof(struct v3dv_descriptor_pool);
487bf215546Sopenharmony_ci      pool->host_memory_ptr = pool->host_memory_base;
488bf215546Sopenharmony_ci      pool->host_memory_end = (uint8_t*)pool + size;
489bf215546Sopenharmony_ci   }
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci   pool->max_entry_count = pCreateInfo->maxSets;
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_ci   if (bo_size > 0) {
494bf215546Sopenharmony_ci      pool->bo = v3dv_bo_alloc(device, bo_size, "descriptor pool bo", true);
495bf215546Sopenharmony_ci      if (!pool->bo)
496bf215546Sopenharmony_ci         goto out_of_device_memory;
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci      bool ok = v3dv_bo_map(device, pool->bo, pool->bo->size);
499bf215546Sopenharmony_ci      if (!ok)
500bf215546Sopenharmony_ci         goto out_of_device_memory;
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci      pool->current_offset = 0;
503bf215546Sopenharmony_ci   } else {
504bf215546Sopenharmony_ci      pool->bo = NULL;
505bf215546Sopenharmony_ci   }
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci   list_inithead(&pool->set_list);
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci   *pDescriptorPool = v3dv_descriptor_pool_to_handle(pool);
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci   return VK_SUCCESS;
512bf215546Sopenharmony_ci
513bf215546Sopenharmony_ci out_of_device_memory:
514bf215546Sopenharmony_ci   vk_object_free(&device->vk, pAllocator, pool);
515bf215546Sopenharmony_ci   return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
516bf215546Sopenharmony_ci}
517bf215546Sopenharmony_ci
518bf215546Sopenharmony_cistatic void
519bf215546Sopenharmony_cidescriptor_set_destroy(struct v3dv_device *device,
520bf215546Sopenharmony_ci                       struct v3dv_descriptor_pool *pool,
521bf215546Sopenharmony_ci                       struct v3dv_descriptor_set *set,
522bf215546Sopenharmony_ci                       bool free_bo)
523bf215546Sopenharmony_ci{
524bf215546Sopenharmony_ci   assert(!pool->host_memory_base);
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci   if (free_bo && !pool->host_memory_base) {
527bf215546Sopenharmony_ci      for (uint32_t i = 0; i < pool->entry_count; i++) {
528bf215546Sopenharmony_ci         if (pool->entries[i].set == set) {
529bf215546Sopenharmony_ci            memmove(&pool->entries[i], &pool->entries[i+1],
530bf215546Sopenharmony_ci                    sizeof(pool->entries[i]) * (pool->entry_count - i - 1));
531bf215546Sopenharmony_ci            --pool->entry_count;
532bf215546Sopenharmony_ci            break;
533bf215546Sopenharmony_ci         }
534bf215546Sopenharmony_ci      }
535bf215546Sopenharmony_ci   }
536bf215546Sopenharmony_ci   vk_object_free(&device->vk, NULL, set);
537bf215546Sopenharmony_ci}
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
540bf215546Sopenharmony_civ3dv_DestroyDescriptorPool(VkDevice _device,
541bf215546Sopenharmony_ci                           VkDescriptorPool _pool,
542bf215546Sopenharmony_ci                           const VkAllocationCallbacks *pAllocator)
543bf215546Sopenharmony_ci{
544bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
545bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, _pool);
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_ci   if (!pool)
548bf215546Sopenharmony_ci      return;
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci   list_for_each_entry_safe(struct v3dv_descriptor_set, set,
551bf215546Sopenharmony_ci                            &pool->set_list, pool_link) {
552bf215546Sopenharmony_ci      v3dv_descriptor_set_layout_unref(device, set->layout);
553bf215546Sopenharmony_ci   }
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_ci   if (!pool->host_memory_base) {
556bf215546Sopenharmony_ci      for(int i = 0; i < pool->entry_count; ++i) {
557bf215546Sopenharmony_ci         descriptor_set_destroy(device, pool, pool->entries[i].set, false);
558bf215546Sopenharmony_ci      }
559bf215546Sopenharmony_ci   }
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_ci   if (pool->bo) {
562bf215546Sopenharmony_ci      v3dv_bo_free(device, pool->bo);
563bf215546Sopenharmony_ci      pool->bo = NULL;
564bf215546Sopenharmony_ci   }
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_ci   vk_object_free(&device->vk, pAllocator, pool);
567bf215546Sopenharmony_ci}
568bf215546Sopenharmony_ci
569bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
570bf215546Sopenharmony_civ3dv_ResetDescriptorPool(VkDevice _device,
571bf215546Sopenharmony_ci                         VkDescriptorPool descriptorPool,
572bf215546Sopenharmony_ci                         VkDescriptorPoolResetFlags flags)
573bf215546Sopenharmony_ci{
574bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
575bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, descriptorPool);
576bf215546Sopenharmony_ci
577bf215546Sopenharmony_ci   list_for_each_entry_safe(struct v3dv_descriptor_set, set,
578bf215546Sopenharmony_ci                            &pool->set_list, pool_link) {
579bf215546Sopenharmony_ci      v3dv_descriptor_set_layout_unref(device, set->layout);
580bf215546Sopenharmony_ci   }
581bf215546Sopenharmony_ci   list_inithead(&pool->set_list);
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_ci   if (!pool->host_memory_base) {
584bf215546Sopenharmony_ci      for(int i = 0; i < pool->entry_count; ++i) {
585bf215546Sopenharmony_ci         descriptor_set_destroy(device, pool, pool->entries[i].set, false);
586bf215546Sopenharmony_ci      }
587bf215546Sopenharmony_ci   } else {
588bf215546Sopenharmony_ci      /* We clean-up the host memory, so when allocating a new set from the
589bf215546Sopenharmony_ci       * pool, it is already 0
590bf215546Sopenharmony_ci       */
591bf215546Sopenharmony_ci      uint32_t host_size = pool->host_memory_end - pool->host_memory_base;
592bf215546Sopenharmony_ci      memset(pool->host_memory_base, 0, host_size);
593bf215546Sopenharmony_ci   }
594bf215546Sopenharmony_ci
595bf215546Sopenharmony_ci   pool->entry_count = 0;
596bf215546Sopenharmony_ci   pool->host_memory_ptr = pool->host_memory_base;
597bf215546Sopenharmony_ci   pool->current_offset = 0;
598bf215546Sopenharmony_ci
599bf215546Sopenharmony_ci   return VK_SUCCESS;
600bf215546Sopenharmony_ci}
601bf215546Sopenharmony_ci
602bf215546Sopenharmony_civoid
603bf215546Sopenharmony_civ3dv_descriptor_set_layout_destroy(struct v3dv_device *device,
604bf215546Sopenharmony_ci                                   struct v3dv_descriptor_set_layout *set_layout)
605bf215546Sopenharmony_ci{
606bf215546Sopenharmony_ci   assert(set_layout->ref_cnt == 0);
607bf215546Sopenharmony_ci   vk_object_base_finish(&set_layout->base);
608bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, NULL, set_layout);
609bf215546Sopenharmony_ci}
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
612bf215546Sopenharmony_civ3dv_CreateDescriptorSetLayout(VkDevice _device,
613bf215546Sopenharmony_ci                               const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
614bf215546Sopenharmony_ci                               const VkAllocationCallbacks *pAllocator,
615bf215546Sopenharmony_ci                               VkDescriptorSetLayout *pSetLayout)
616bf215546Sopenharmony_ci{
617bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
618bf215546Sopenharmony_ci   struct v3dv_descriptor_set_layout *set_layout;
619bf215546Sopenharmony_ci
620bf215546Sopenharmony_ci   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_ci   uint32_t num_bindings = 0;
623bf215546Sopenharmony_ci   uint32_t immutable_sampler_count = 0;
624bf215546Sopenharmony_ci   for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
625bf215546Sopenharmony_ci      num_bindings = MAX2(num_bindings, pCreateInfo->pBindings[j].binding + 1);
626bf215546Sopenharmony_ci
627bf215546Sopenharmony_ci      /* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding:
628bf215546Sopenharmony_ci       *
629bf215546Sopenharmony_ci       *    "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or
630bf215546Sopenharmony_ci       *    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then
631bf215546Sopenharmony_ci       *    pImmutableSamplers can be used to initialize a set of immutable
632bf215546Sopenharmony_ci       *    samplers. [...]  If descriptorType is not one of these descriptor
633bf215546Sopenharmony_ci       *    types, then pImmutableSamplers is ignored.
634bf215546Sopenharmony_ci       *
635bf215546Sopenharmony_ci       * We need to be careful here and only parse pImmutableSamplers if we
636bf215546Sopenharmony_ci       * have one of the right descriptor types.
637bf215546Sopenharmony_ci       */
638bf215546Sopenharmony_ci      VkDescriptorType desc_type = pCreateInfo->pBindings[j].descriptorType;
639bf215546Sopenharmony_ci      if ((desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
640bf215546Sopenharmony_ci           desc_type == VK_DESCRIPTOR_TYPE_SAMPLER) &&
641bf215546Sopenharmony_ci           pCreateInfo->pBindings[j].pImmutableSamplers) {
642bf215546Sopenharmony_ci         immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount;
643bf215546Sopenharmony_ci      }
644bf215546Sopenharmony_ci   }
645bf215546Sopenharmony_ci
646bf215546Sopenharmony_ci   /* We place immutable samplers after the binding data. We want to use
647bf215546Sopenharmony_ci    * offsetof instead of any sizeof(struct v3dv_descriptor_set_layout)
648bf215546Sopenharmony_ci    * because the latter may include padding at the end of the struct.
649bf215546Sopenharmony_ci    */
650bf215546Sopenharmony_ci   uint32_t samplers_offset =
651bf215546Sopenharmony_ci      offsetof(struct v3dv_descriptor_set_layout, binding[num_bindings]);
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci   uint32_t size = samplers_offset +
654bf215546Sopenharmony_ci      immutable_sampler_count * sizeof(struct v3dv_sampler);
655bf215546Sopenharmony_ci
656bf215546Sopenharmony_ci   /* Descriptor set layouts are reference counted and therefore can survive
657bf215546Sopenharmony_ci    * vkDestroyPipelineSetLayout, so they need to be allocated with a device
658bf215546Sopenharmony_ci    * scope.
659bf215546Sopenharmony_ci    */
660bf215546Sopenharmony_ci   set_layout =
661bf215546Sopenharmony_ci      vk_zalloc(&device->vk.alloc, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
662bf215546Sopenharmony_ci   if (!set_layout)
663bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci   vk_object_base_init(&device->vk, &set_layout->base,
666bf215546Sopenharmony_ci                       VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT);
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_ci   struct v3dv_sampler *samplers = (void*) &set_layout->binding[num_bindings];
669bf215546Sopenharmony_ci
670bf215546Sopenharmony_ci   assert(pCreateInfo->bindingCount == 0 || num_bindings > 0);
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ci   VkDescriptorSetLayoutBinding *bindings = NULL;
673bf215546Sopenharmony_ci   VkResult result = vk_create_sorted_bindings(pCreateInfo->pBindings,
674bf215546Sopenharmony_ci                                               pCreateInfo->bindingCount, &bindings);
675bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
676bf215546Sopenharmony_ci      v3dv_descriptor_set_layout_destroy(device, set_layout);
677bf215546Sopenharmony_ci      return vk_error(device, result);
678bf215546Sopenharmony_ci   }
679bf215546Sopenharmony_ci
680bf215546Sopenharmony_ci   set_layout->binding_count = num_bindings;
681bf215546Sopenharmony_ci   set_layout->flags = pCreateInfo->flags;
682bf215546Sopenharmony_ci   set_layout->shader_stages = 0;
683bf215546Sopenharmony_ci   set_layout->bo_size = 0;
684bf215546Sopenharmony_ci   set_layout->ref_cnt = 1;
685bf215546Sopenharmony_ci
686bf215546Sopenharmony_ci   uint32_t descriptor_count = 0;
687bf215546Sopenharmony_ci   uint32_t dynamic_offset_count = 0;
688bf215546Sopenharmony_ci
689bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
690bf215546Sopenharmony_ci      const VkDescriptorSetLayoutBinding *binding = bindings + i;
691bf215546Sopenharmony_ci      uint32_t binding_number = binding->binding;
692bf215546Sopenharmony_ci
693bf215546Sopenharmony_ci      switch (binding->descriptorType) {
694bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
695bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
696bf215546Sopenharmony_ci         break;
697bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
698bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
699bf215546Sopenharmony_ci         set_layout->binding[binding_number].dynamic_offset_count = 1;
700bf215546Sopenharmony_ci         break;
701bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLER:
702bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
703bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
704bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
705bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
706bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
707bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
708bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
709bf215546Sopenharmony_ci         /* Nothing here, just to keep the descriptor type filtering below */
710bf215546Sopenharmony_ci         break;
711bf215546Sopenharmony_ci      default:
712bf215546Sopenharmony_ci         unreachable("Unknown descriptor type\n");
713bf215546Sopenharmony_ci         break;
714bf215546Sopenharmony_ci      }
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_ci      set_layout->binding[binding_number].type = binding->descriptorType;
717bf215546Sopenharmony_ci      set_layout->binding[binding_number].array_size = binding->descriptorCount;
718bf215546Sopenharmony_ci      set_layout->binding[binding_number].descriptor_index = descriptor_count;
719bf215546Sopenharmony_ci      set_layout->binding[binding_number].dynamic_offset_index = dynamic_offset_count;
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_ci      if ((binding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
722bf215546Sopenharmony_ci           binding->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) &&
723bf215546Sopenharmony_ci          binding->pImmutableSamplers) {
724bf215546Sopenharmony_ci
725bf215546Sopenharmony_ci         set_layout->binding[binding_number].immutable_samplers_offset = samplers_offset;
726bf215546Sopenharmony_ci
727bf215546Sopenharmony_ci         for (uint32_t i = 0; i < binding->descriptorCount; i++)
728bf215546Sopenharmony_ci            samplers[i] = *v3dv_sampler_from_handle(binding->pImmutableSamplers[i]);
729bf215546Sopenharmony_ci
730bf215546Sopenharmony_ci         samplers += binding->descriptorCount;
731bf215546Sopenharmony_ci         samplers_offset += sizeof(struct v3dv_sampler) * binding->descriptorCount;
732bf215546Sopenharmony_ci      }
733bf215546Sopenharmony_ci
734bf215546Sopenharmony_ci      set_layout->shader_stages |= binding->stageFlags;
735bf215546Sopenharmony_ci
736bf215546Sopenharmony_ci      if (binding->descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
737bf215546Sopenharmony_ci         dynamic_offset_count += binding->descriptorCount *
738bf215546Sopenharmony_ci            set_layout->binding[binding_number].dynamic_offset_count;
739bf215546Sopenharmony_ci
740bf215546Sopenharmony_ci         descriptor_count += binding->descriptorCount;
741bf215546Sopenharmony_ci
742bf215546Sopenharmony_ci         set_layout->binding[binding_number].descriptor_offset =
743bf215546Sopenharmony_ci            set_layout->bo_size;
744bf215546Sopenharmony_ci         set_layout->bo_size +=
745bf215546Sopenharmony_ci            v3dv_X(device, descriptor_bo_size)(set_layout->binding[binding_number].type) *
746bf215546Sopenharmony_ci            binding->descriptorCount;
747bf215546Sopenharmony_ci      } else {
748bf215546Sopenharmony_ci         /* We align all our buffers, inline buffers too. We made sure to take
749bf215546Sopenharmony_ci          * this account when calculating total BO size requirements at pool
750bf215546Sopenharmony_ci          * creation time.
751bf215546Sopenharmony_ci          */
752bf215546Sopenharmony_ci         set_layout->bo_size = align(set_layout->bo_size,
753bf215546Sopenharmony_ci                                     V3D_NON_COHERENT_ATOM_SIZE);
754bf215546Sopenharmony_ci
755bf215546Sopenharmony_ci         set_layout->binding[binding_number].descriptor_offset =
756bf215546Sopenharmony_ci            set_layout->bo_size;
757bf215546Sopenharmony_ci
758bf215546Sopenharmony_ci         /* Inline uniform blocks are not arrayed, instead descriptorCount
759bf215546Sopenharmony_ci          * specifies the size of the buffer in bytes.
760bf215546Sopenharmony_ci          */
761bf215546Sopenharmony_ci         set_layout->bo_size += binding->descriptorCount;
762bf215546Sopenharmony_ci         descriptor_count++;
763bf215546Sopenharmony_ci      }
764bf215546Sopenharmony_ci   }
765bf215546Sopenharmony_ci
766bf215546Sopenharmony_ci   free(bindings);
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_ci   set_layout->descriptor_count = descriptor_count;
769bf215546Sopenharmony_ci   set_layout->dynamic_offset_count = dynamic_offset_count;
770bf215546Sopenharmony_ci
771bf215546Sopenharmony_ci   *pSetLayout = v3dv_descriptor_set_layout_to_handle(set_layout);
772bf215546Sopenharmony_ci
773bf215546Sopenharmony_ci   return VK_SUCCESS;
774bf215546Sopenharmony_ci}
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
777bf215546Sopenharmony_civ3dv_DestroyDescriptorSetLayout(VkDevice _device,
778bf215546Sopenharmony_ci                                VkDescriptorSetLayout _set_layout,
779bf215546Sopenharmony_ci                                const VkAllocationCallbacks *pAllocator)
780bf215546Sopenharmony_ci{
781bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
782bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, set_layout, _set_layout);
783bf215546Sopenharmony_ci
784bf215546Sopenharmony_ci   if (!set_layout)
785bf215546Sopenharmony_ci      return;
786bf215546Sopenharmony_ci
787bf215546Sopenharmony_ci   v3dv_descriptor_set_layout_unref(device, set_layout);
788bf215546Sopenharmony_ci}
789bf215546Sopenharmony_ci
790bf215546Sopenharmony_cistatic inline VkResult
791bf215546Sopenharmony_ciout_of_pool_memory(const struct v3dv_device *device,
792bf215546Sopenharmony_ci                   const struct v3dv_descriptor_pool *pool)
793bf215546Sopenharmony_ci{
794bf215546Sopenharmony_ci   /* Don't log OOPM errors for internal driver pools, we handle these properly
795bf215546Sopenharmony_ci    * by allocating a new pool, so they don't point to real issues.
796bf215546Sopenharmony_ci    */
797bf215546Sopenharmony_ci   if (!pool->is_driver_internal)
798bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY);
799bf215546Sopenharmony_ci   else
800bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_POOL_MEMORY;
801bf215546Sopenharmony_ci}
802bf215546Sopenharmony_ci
803bf215546Sopenharmony_cistatic VkResult
804bf215546Sopenharmony_cidescriptor_set_create(struct v3dv_device *device,
805bf215546Sopenharmony_ci                      struct v3dv_descriptor_pool *pool,
806bf215546Sopenharmony_ci                      struct v3dv_descriptor_set_layout *layout,
807bf215546Sopenharmony_ci                      struct v3dv_descriptor_set **out_set)
808bf215546Sopenharmony_ci{
809bf215546Sopenharmony_ci   struct v3dv_descriptor_set *set;
810bf215546Sopenharmony_ci   uint32_t descriptor_count = layout->descriptor_count;
811bf215546Sopenharmony_ci   unsigned mem_size = sizeof(struct v3dv_descriptor_set) +
812bf215546Sopenharmony_ci      sizeof(struct v3dv_descriptor) * descriptor_count;
813bf215546Sopenharmony_ci
814bf215546Sopenharmony_ci   if (pool->host_memory_base) {
815bf215546Sopenharmony_ci      if (pool->host_memory_end - pool->host_memory_ptr < mem_size)
816bf215546Sopenharmony_ci         return out_of_pool_memory(device, pool);
817bf215546Sopenharmony_ci
818bf215546Sopenharmony_ci      set = (struct v3dv_descriptor_set*)pool->host_memory_ptr;
819bf215546Sopenharmony_ci      pool->host_memory_ptr += mem_size;
820bf215546Sopenharmony_ci
821bf215546Sopenharmony_ci      vk_object_base_init(&device->vk, &set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET);
822bf215546Sopenharmony_ci   } else {
823bf215546Sopenharmony_ci      set = vk_object_zalloc(&device->vk, NULL, mem_size,
824bf215546Sopenharmony_ci                             VK_OBJECT_TYPE_DESCRIPTOR_SET);
825bf215546Sopenharmony_ci
826bf215546Sopenharmony_ci      if (!set)
827bf215546Sopenharmony_ci         return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
828bf215546Sopenharmony_ci   }
829bf215546Sopenharmony_ci
830bf215546Sopenharmony_ci   set->pool = pool;
831bf215546Sopenharmony_ci
832bf215546Sopenharmony_ci   set->layout = layout;
833bf215546Sopenharmony_ci
834bf215546Sopenharmony_ci   /* FIXME: VK_EXT_descriptor_indexing introduces
835bf215546Sopenharmony_ci    * VARIABLE_DESCRIPTOR_LAYOUT_COUNT. That would affect the layout_size used
836bf215546Sopenharmony_ci    * below for bo allocation
837bf215546Sopenharmony_ci    */
838bf215546Sopenharmony_ci
839bf215546Sopenharmony_ci   uint32_t offset = 0;
840bf215546Sopenharmony_ci   uint32_t index = pool->entry_count;
841bf215546Sopenharmony_ci
842bf215546Sopenharmony_ci   if (layout->bo_size) {
843bf215546Sopenharmony_ci      if (!pool->host_memory_base && pool->entry_count == pool->max_entry_count) {
844bf215546Sopenharmony_ci         vk_object_free(&device->vk, NULL, set);
845bf215546Sopenharmony_ci         return out_of_pool_memory(device, pool);
846bf215546Sopenharmony_ci      }
847bf215546Sopenharmony_ci
848bf215546Sopenharmony_ci      /* We first try to allocate linearly fist, so that we don't spend time
849bf215546Sopenharmony_ci       * looking for gaps if the app only allocates & resets via the pool.
850bf215546Sopenharmony_ci       *
851bf215546Sopenharmony_ci       * If that fails, we try to find a gap from previously freed subregions
852bf215546Sopenharmony_ci       * iterating through the descriptor pool entries. Note that we are not
853bf215546Sopenharmony_ci       * doing that if we have a pool->host_memory_base. We only have that if
854bf215546Sopenharmony_ci       * VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT is not set, so in
855bf215546Sopenharmony_ci       * that case the user can't free subregions, so it doesn't make sense to
856bf215546Sopenharmony_ci       * even try (or track those subregions).
857bf215546Sopenharmony_ci       */
858bf215546Sopenharmony_ci      if (pool->current_offset + layout->bo_size <= pool->bo->size) {
859bf215546Sopenharmony_ci         offset = pool->current_offset;
860bf215546Sopenharmony_ci         pool->current_offset += layout->bo_size;
861bf215546Sopenharmony_ci      } else if (!pool->host_memory_base) {
862bf215546Sopenharmony_ci         for (index = 0; index < pool->entry_count; index++) {
863bf215546Sopenharmony_ci            if (pool->entries[index].offset - offset >= layout->bo_size)
864bf215546Sopenharmony_ci               break;
865bf215546Sopenharmony_ci            offset = pool->entries[index].offset + pool->entries[index].size;
866bf215546Sopenharmony_ci         }
867bf215546Sopenharmony_ci         if (pool->bo->size - offset < layout->bo_size) {
868bf215546Sopenharmony_ci            vk_object_free(&device->vk, NULL, set);
869bf215546Sopenharmony_ci            return out_of_pool_memory(device, pool);
870bf215546Sopenharmony_ci         }
871bf215546Sopenharmony_ci         memmove(&pool->entries[index + 1], &pool->entries[index],
872bf215546Sopenharmony_ci                 sizeof(pool->entries[0]) * (pool->entry_count - index));
873bf215546Sopenharmony_ci      } else {
874bf215546Sopenharmony_ci         assert(pool->host_memory_base);
875bf215546Sopenharmony_ci         return out_of_pool_memory(device, pool);
876bf215546Sopenharmony_ci      }
877bf215546Sopenharmony_ci
878bf215546Sopenharmony_ci      set->base_offset = offset;
879bf215546Sopenharmony_ci   }
880bf215546Sopenharmony_ci
881bf215546Sopenharmony_ci   if (!pool->host_memory_base) {
882bf215546Sopenharmony_ci      pool->entries[index].set = set;
883bf215546Sopenharmony_ci      pool->entries[index].offset = offset;
884bf215546Sopenharmony_ci      pool->entries[index].size = layout->bo_size;
885bf215546Sopenharmony_ci      pool->entry_count++;
886bf215546Sopenharmony_ci   }
887bf215546Sopenharmony_ci
888bf215546Sopenharmony_ci   /* Go through and fill out immutable samplers if we have any */
889bf215546Sopenharmony_ci   for (uint32_t b = 0; b < layout->binding_count; b++) {
890bf215546Sopenharmony_ci      if (layout->binding[b].immutable_samplers_offset == 0)
891bf215546Sopenharmony_ci         continue;
892bf215546Sopenharmony_ci
893bf215546Sopenharmony_ci      const struct v3dv_sampler *samplers =
894bf215546Sopenharmony_ci         (const struct v3dv_sampler *)((const char *)layout +
895bf215546Sopenharmony_ci                                       layout->binding[b].immutable_samplers_offset);
896bf215546Sopenharmony_ci
897bf215546Sopenharmony_ci      for (uint32_t i = 0; i < layout->binding[b].array_size; i++) {
898bf215546Sopenharmony_ci         uint32_t combined_offset =
899bf215546Sopenharmony_ci            layout->binding[b].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ?
900bf215546Sopenharmony_ci            v3dv_X(device, combined_image_sampler_sampler_state_offset)() : 0;
901bf215546Sopenharmony_ci
902bf215546Sopenharmony_ci         void *desc_map = descriptor_bo_map(device, set, &layout->binding[b], i);
903bf215546Sopenharmony_ci         desc_map += combined_offset;
904bf215546Sopenharmony_ci
905bf215546Sopenharmony_ci         memcpy(desc_map,
906bf215546Sopenharmony_ci                samplers[i].sampler_state,
907bf215546Sopenharmony_ci                sizeof(samplers[i].sampler_state));
908bf215546Sopenharmony_ci      }
909bf215546Sopenharmony_ci   }
910bf215546Sopenharmony_ci
911bf215546Sopenharmony_ci   v3dv_descriptor_set_layout_ref(layout);
912bf215546Sopenharmony_ci   list_addtail(&set->pool_link, &pool->set_list);
913bf215546Sopenharmony_ci
914bf215546Sopenharmony_ci   *out_set = set;
915bf215546Sopenharmony_ci
916bf215546Sopenharmony_ci   return VK_SUCCESS;
917bf215546Sopenharmony_ci}
918bf215546Sopenharmony_ci
919bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
920bf215546Sopenharmony_civ3dv_AllocateDescriptorSets(VkDevice _device,
921bf215546Sopenharmony_ci                            const VkDescriptorSetAllocateInfo *pAllocateInfo,
922bf215546Sopenharmony_ci                            VkDescriptorSet *pDescriptorSets)
923bf215546Sopenharmony_ci{
924bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
925bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, pAllocateInfo->descriptorPool);
926bf215546Sopenharmony_ci
927bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
928bf215546Sopenharmony_ci   struct v3dv_descriptor_set *set = NULL;
929bf215546Sopenharmony_ci   uint32_t i = 0;
930bf215546Sopenharmony_ci
931bf215546Sopenharmony_ci   for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
932bf215546Sopenharmony_ci      V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, layout,
933bf215546Sopenharmony_ci                       pAllocateInfo->pSetLayouts[i]);
934bf215546Sopenharmony_ci
935bf215546Sopenharmony_ci      result = descriptor_set_create(device, pool, layout, &set);
936bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
937bf215546Sopenharmony_ci         break;
938bf215546Sopenharmony_ci
939bf215546Sopenharmony_ci      pDescriptorSets[i] = v3dv_descriptor_set_to_handle(set);
940bf215546Sopenharmony_ci   }
941bf215546Sopenharmony_ci
942bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
943bf215546Sopenharmony_ci      v3dv_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool,
944bf215546Sopenharmony_ci                              i, pDescriptorSets);
945bf215546Sopenharmony_ci      for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
946bf215546Sopenharmony_ci         pDescriptorSets[i] = VK_NULL_HANDLE;
947bf215546Sopenharmony_ci      }
948bf215546Sopenharmony_ci   }
949bf215546Sopenharmony_ci
950bf215546Sopenharmony_ci   return result;
951bf215546Sopenharmony_ci}
952bf215546Sopenharmony_ci
953bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
954bf215546Sopenharmony_civ3dv_FreeDescriptorSets(VkDevice _device,
955bf215546Sopenharmony_ci                        VkDescriptorPool descriptorPool,
956bf215546Sopenharmony_ci                        uint32_t count,
957bf215546Sopenharmony_ci                        const VkDescriptorSet *pDescriptorSets)
958bf215546Sopenharmony_ci{
959bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
960bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, descriptorPool);
961bf215546Sopenharmony_ci
962bf215546Sopenharmony_ci   for (uint32_t i = 0; i < count; i++) {
963bf215546Sopenharmony_ci      V3DV_FROM_HANDLE(v3dv_descriptor_set, set, pDescriptorSets[i]);
964bf215546Sopenharmony_ci
965bf215546Sopenharmony_ci      if (set) {
966bf215546Sopenharmony_ci         v3dv_descriptor_set_layout_unref(device, set->layout);
967bf215546Sopenharmony_ci         list_del(&set->pool_link);
968bf215546Sopenharmony_ci         if (!pool->host_memory_base)
969bf215546Sopenharmony_ci            descriptor_set_destroy(device, pool, set, true);
970bf215546Sopenharmony_ci      }
971bf215546Sopenharmony_ci   }
972bf215546Sopenharmony_ci
973bf215546Sopenharmony_ci   return VK_SUCCESS;
974bf215546Sopenharmony_ci}
975bf215546Sopenharmony_ci
976bf215546Sopenharmony_cistatic void
977bf215546Sopenharmony_cidescriptor_bo_copy(struct v3dv_device *device,
978bf215546Sopenharmony_ci                   struct v3dv_descriptor_set *dst_set,
979bf215546Sopenharmony_ci                   const struct v3dv_descriptor_set_binding_layout *dst_binding_layout,
980bf215546Sopenharmony_ci                   uint32_t dst_array_index,
981bf215546Sopenharmony_ci                   struct v3dv_descriptor_set *src_set,
982bf215546Sopenharmony_ci                   const struct v3dv_descriptor_set_binding_layout *src_binding_layout,
983bf215546Sopenharmony_ci                   uint32_t src_array_index)
984bf215546Sopenharmony_ci{
985bf215546Sopenharmony_ci   assert(dst_binding_layout->type == src_binding_layout->type);
986bf215546Sopenharmony_ci
987bf215546Sopenharmony_ci   void *dst_map = descriptor_bo_map(device, dst_set, dst_binding_layout, dst_array_index);
988bf215546Sopenharmony_ci   void *src_map = descriptor_bo_map(device, src_set, src_binding_layout, src_array_index);
989bf215546Sopenharmony_ci
990bf215546Sopenharmony_ci   memcpy(dst_map, src_map, v3dv_X(device, descriptor_bo_size)(src_binding_layout->type));
991bf215546Sopenharmony_ci}
992bf215546Sopenharmony_ci
993bf215546Sopenharmony_cistatic void
994bf215546Sopenharmony_ciwrite_buffer_descriptor(struct v3dv_descriptor *descriptor,
995bf215546Sopenharmony_ci                        VkDescriptorType desc_type,
996bf215546Sopenharmony_ci                        const VkDescriptorBufferInfo *buffer_info)
997bf215546Sopenharmony_ci{
998bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_buffer, buffer, buffer_info->buffer);
999bf215546Sopenharmony_ci
1000bf215546Sopenharmony_ci   descriptor->type = desc_type;
1001bf215546Sopenharmony_ci   descriptor->buffer = buffer;
1002bf215546Sopenharmony_ci   descriptor->offset = buffer_info->offset;
1003bf215546Sopenharmony_ci   if (buffer_info->range == VK_WHOLE_SIZE) {
1004bf215546Sopenharmony_ci      descriptor->range = buffer->size - buffer_info->offset;
1005bf215546Sopenharmony_ci   } else {
1006bf215546Sopenharmony_ci      assert(descriptor->range <= UINT32_MAX);
1007bf215546Sopenharmony_ci      descriptor->range = buffer_info->range;
1008bf215546Sopenharmony_ci   }
1009bf215546Sopenharmony_ci}
1010bf215546Sopenharmony_ci
1011bf215546Sopenharmony_cistatic void
1012bf215546Sopenharmony_ciwrite_image_descriptor(struct v3dv_device *device,
1013bf215546Sopenharmony_ci                       struct v3dv_descriptor *descriptor,
1014bf215546Sopenharmony_ci                       VkDescriptorType desc_type,
1015bf215546Sopenharmony_ci                       struct v3dv_descriptor_set *set,
1016bf215546Sopenharmony_ci                       const struct v3dv_descriptor_set_binding_layout *binding_layout,
1017bf215546Sopenharmony_ci                       struct v3dv_image_view *iview,
1018bf215546Sopenharmony_ci                       struct v3dv_sampler *sampler,
1019bf215546Sopenharmony_ci                       uint32_t array_index)
1020bf215546Sopenharmony_ci{
1021bf215546Sopenharmony_ci   descriptor->type = desc_type;
1022bf215546Sopenharmony_ci   descriptor->sampler = sampler;
1023bf215546Sopenharmony_ci   descriptor->image_view = iview;
1024bf215546Sopenharmony_ci
1025bf215546Sopenharmony_ci   void *desc_map = descriptor_bo_map(device, set,
1026bf215546Sopenharmony_ci                                      binding_layout, array_index);
1027bf215546Sopenharmony_ci
1028bf215546Sopenharmony_ci   if (iview) {
1029bf215546Sopenharmony_ci      const uint32_t tex_state_index =
1030bf215546Sopenharmony_ci         iview->vk.view_type != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY ||
1031bf215546Sopenharmony_ci         desc_type != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? 0 : 1;
1032bf215546Sopenharmony_ci      memcpy(desc_map,
1033bf215546Sopenharmony_ci             iview->texture_shader_state[tex_state_index],
1034bf215546Sopenharmony_ci             sizeof(iview->texture_shader_state[0]));
1035bf215546Sopenharmony_ci      desc_map += v3dv_X(device, combined_image_sampler_sampler_state_offset)();
1036bf215546Sopenharmony_ci   }
1037bf215546Sopenharmony_ci
1038bf215546Sopenharmony_ci   if (sampler && !binding_layout->immutable_samplers_offset) {
1039bf215546Sopenharmony_ci      /* For immutable samplers this was already done as part of the
1040bf215546Sopenharmony_ci       * descriptor set create, as that info can't change later
1041bf215546Sopenharmony_ci       */
1042bf215546Sopenharmony_ci      memcpy(desc_map,
1043bf215546Sopenharmony_ci             sampler->sampler_state,
1044bf215546Sopenharmony_ci             sizeof(sampler->sampler_state));
1045bf215546Sopenharmony_ci   }
1046bf215546Sopenharmony_ci}
1047bf215546Sopenharmony_ci
1048bf215546Sopenharmony_ci
1049bf215546Sopenharmony_cistatic void
1050bf215546Sopenharmony_ciwrite_buffer_view_descriptor(struct v3dv_device *device,
1051bf215546Sopenharmony_ci                             struct v3dv_descriptor *descriptor,
1052bf215546Sopenharmony_ci                             VkDescriptorType desc_type,
1053bf215546Sopenharmony_ci                             struct v3dv_descriptor_set *set,
1054bf215546Sopenharmony_ci                             const struct v3dv_descriptor_set_binding_layout *binding_layout,
1055bf215546Sopenharmony_ci                             struct v3dv_buffer_view *bview,
1056bf215546Sopenharmony_ci                             uint32_t array_index)
1057bf215546Sopenharmony_ci{
1058bf215546Sopenharmony_ci   assert(bview);
1059bf215546Sopenharmony_ci   descriptor->type = desc_type;
1060bf215546Sopenharmony_ci   descriptor->buffer_view = bview;
1061bf215546Sopenharmony_ci
1062bf215546Sopenharmony_ci   void *desc_map = descriptor_bo_map(device, set, binding_layout, array_index);
1063bf215546Sopenharmony_ci
1064bf215546Sopenharmony_ci   memcpy(desc_map,
1065bf215546Sopenharmony_ci          bview->texture_shader_state,
1066bf215546Sopenharmony_ci          sizeof(bview->texture_shader_state));
1067bf215546Sopenharmony_ci}
1068bf215546Sopenharmony_ci
1069bf215546Sopenharmony_cistatic void
1070bf215546Sopenharmony_ciwrite_inline_uniform_descriptor(struct v3dv_device *device,
1071bf215546Sopenharmony_ci                                struct v3dv_descriptor *descriptor,
1072bf215546Sopenharmony_ci                                struct v3dv_descriptor_set *set,
1073bf215546Sopenharmony_ci                                const struct v3dv_descriptor_set_binding_layout *binding_layout,
1074bf215546Sopenharmony_ci                                const void *data,
1075bf215546Sopenharmony_ci                                size_t offset,
1076bf215546Sopenharmony_ci                                size_t size)
1077bf215546Sopenharmony_ci{
1078bf215546Sopenharmony_ci   assert(binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK);
1079bf215546Sopenharmony_ci   descriptor->type = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK;
1080bf215546Sopenharmony_ci   descriptor->buffer = NULL;
1081bf215546Sopenharmony_ci
1082bf215546Sopenharmony_ci   void *desc_map = descriptor_bo_map(device, set, binding_layout, 0);
1083bf215546Sopenharmony_ci   memcpy(desc_map + offset, data, size);
1084bf215546Sopenharmony_ci
1085bf215546Sopenharmony_ci   /* Inline uniform buffers allocate BO space in the pool for all inline
1086bf215546Sopenharmony_ci    * buffers it may allocate and then this space is assigned to individual
1087bf215546Sopenharmony_ci    * descriptors when they are written, so we define the range of an inline
1088bf215546Sopenharmony_ci    * buffer as the largest range of data that the client has written to it.
1089bf215546Sopenharmony_ci    */
1090bf215546Sopenharmony_ci   descriptor->offset = 0;
1091bf215546Sopenharmony_ci   descriptor->range = MAX2(descriptor->range, offset + size);
1092bf215546Sopenharmony_ci}
1093bf215546Sopenharmony_ci
1094bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1095bf215546Sopenharmony_civ3dv_UpdateDescriptorSets(VkDevice  _device,
1096bf215546Sopenharmony_ci                          uint32_t descriptorWriteCount,
1097bf215546Sopenharmony_ci                          const VkWriteDescriptorSet *pDescriptorWrites,
1098bf215546Sopenharmony_ci                          uint32_t descriptorCopyCount,
1099bf215546Sopenharmony_ci                          const VkCopyDescriptorSet *pDescriptorCopies)
1100bf215546Sopenharmony_ci{
1101bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
1102bf215546Sopenharmony_ci   for (uint32_t i = 0; i < descriptorWriteCount; i++) {
1103bf215546Sopenharmony_ci      const VkWriteDescriptorSet *writeset = &pDescriptorWrites[i];
1104bf215546Sopenharmony_ci      V3DV_FROM_HANDLE(v3dv_descriptor_set, set, writeset->dstSet);
1105bf215546Sopenharmony_ci
1106bf215546Sopenharmony_ci      const struct v3dv_descriptor_set_binding_layout *binding_layout =
1107bf215546Sopenharmony_ci         set->layout->binding + writeset->dstBinding;
1108bf215546Sopenharmony_ci
1109bf215546Sopenharmony_ci      struct v3dv_descriptor *descriptor = set->descriptors;
1110bf215546Sopenharmony_ci
1111bf215546Sopenharmony_ci      descriptor += binding_layout->descriptor_index;
1112bf215546Sopenharmony_ci
1113bf215546Sopenharmony_ci      /* Inline uniform blocks are not arrayed, instead they use dstArrayElement
1114bf215546Sopenharmony_ci       * to specify the byte offset of the uniform update and descriptorCount
1115bf215546Sopenharmony_ci       * to specify the size (in bytes) of the update.
1116bf215546Sopenharmony_ci       */
1117bf215546Sopenharmony_ci      uint32_t descriptor_count;
1118bf215546Sopenharmony_ci      if (writeset->descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
1119bf215546Sopenharmony_ci         descriptor += writeset->dstArrayElement;
1120bf215546Sopenharmony_ci         descriptor_count = writeset->descriptorCount;
1121bf215546Sopenharmony_ci      } else {
1122bf215546Sopenharmony_ci         descriptor_count = 1;
1123bf215546Sopenharmony_ci      }
1124bf215546Sopenharmony_ci
1125bf215546Sopenharmony_ci      for (uint32_t j = 0; j < descriptor_count; ++j) {
1126bf215546Sopenharmony_ci         switch(writeset->descriptorType) {
1127bf215546Sopenharmony_ci
1128bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1129bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1130bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1131bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {
1132bf215546Sopenharmony_ci            const VkDescriptorBufferInfo *buffer_info = writeset->pBufferInfo + j;
1133bf215546Sopenharmony_ci            write_buffer_descriptor(descriptor, writeset->descriptorType,
1134bf215546Sopenharmony_ci                                    buffer_info);
1135bf215546Sopenharmony_ci            break;
1136bf215546Sopenharmony_ci         }
1137bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_SAMPLER: {
1138bf215546Sopenharmony_ci            /* If we are here we shouldn't be modifying a immutable sampler,
1139bf215546Sopenharmony_ci             * so we don't ensure that would work or not crash. But let the
1140bf215546Sopenharmony_ci             * validation layers check that
1141bf215546Sopenharmony_ci             */
1142bf215546Sopenharmony_ci            const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j;
1143bf215546Sopenharmony_ci            V3DV_FROM_HANDLE(v3dv_sampler, sampler, image_info->sampler);
1144bf215546Sopenharmony_ci            write_image_descriptor(device, descriptor, writeset->descriptorType,
1145bf215546Sopenharmony_ci                                   set, binding_layout, NULL, sampler,
1146bf215546Sopenharmony_ci                                   writeset->dstArrayElement + j);
1147bf215546Sopenharmony_ci
1148bf215546Sopenharmony_ci            break;
1149bf215546Sopenharmony_ci         }
1150bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1151bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1152bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
1153bf215546Sopenharmony_ci            const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j;
1154bf215546Sopenharmony_ci            V3DV_FROM_HANDLE(v3dv_image_view, iview, image_info->imageView);
1155bf215546Sopenharmony_ci            write_image_descriptor(device, descriptor, writeset->descriptorType,
1156bf215546Sopenharmony_ci                                   set, binding_layout, iview, NULL,
1157bf215546Sopenharmony_ci                                   writeset->dstArrayElement + j);
1158bf215546Sopenharmony_ci
1159bf215546Sopenharmony_ci            break;
1160bf215546Sopenharmony_ci         }
1161bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
1162bf215546Sopenharmony_ci            const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j;
1163bf215546Sopenharmony_ci            V3DV_FROM_HANDLE(v3dv_image_view, iview, image_info->imageView);
1164bf215546Sopenharmony_ci            V3DV_FROM_HANDLE(v3dv_sampler, sampler, image_info->sampler);
1165bf215546Sopenharmony_ci            write_image_descriptor(device, descriptor, writeset->descriptorType,
1166bf215546Sopenharmony_ci                                   set, binding_layout, iview, sampler,
1167bf215546Sopenharmony_ci                                   writeset->dstArrayElement + j);
1168bf215546Sopenharmony_ci
1169bf215546Sopenharmony_ci            break;
1170bf215546Sopenharmony_ci         }
1171bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1172bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: {
1173bf215546Sopenharmony_ci            V3DV_FROM_HANDLE(v3dv_buffer_view, buffer_view,
1174bf215546Sopenharmony_ci                             writeset->pTexelBufferView[j]);
1175bf215546Sopenharmony_ci            write_buffer_view_descriptor(device, descriptor, writeset->descriptorType,
1176bf215546Sopenharmony_ci                                         set, binding_layout, buffer_view,
1177bf215546Sopenharmony_ci                                         writeset->dstArrayElement + j);
1178bf215546Sopenharmony_ci            break;
1179bf215546Sopenharmony_ci         }
1180bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: {
1181bf215546Sopenharmony_ci            const VkWriteDescriptorSetInlineUniformBlock *inline_write =
1182bf215546Sopenharmony_ci               vk_find_struct_const(writeset->pNext,
1183bf215546Sopenharmony_ci                                    WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK);
1184bf215546Sopenharmony_ci            assert(inline_write->dataSize == writeset->descriptorCount);
1185bf215546Sopenharmony_ci            write_inline_uniform_descriptor(device, descriptor, set,
1186bf215546Sopenharmony_ci                                            binding_layout,
1187bf215546Sopenharmony_ci                                            inline_write->pData,
1188bf215546Sopenharmony_ci                                            writeset->dstArrayElement, /* offset */
1189bf215546Sopenharmony_ci                                            inline_write->dataSize);
1190bf215546Sopenharmony_ci            break;
1191bf215546Sopenharmony_ci         }
1192bf215546Sopenharmony_ci         default:
1193bf215546Sopenharmony_ci            unreachable("unimplemented descriptor type");
1194bf215546Sopenharmony_ci            break;
1195bf215546Sopenharmony_ci         }
1196bf215546Sopenharmony_ci         descriptor++;
1197bf215546Sopenharmony_ci      }
1198bf215546Sopenharmony_ci   }
1199bf215546Sopenharmony_ci
1200bf215546Sopenharmony_ci   for (uint32_t i = 0; i < descriptorCopyCount; i++) {
1201bf215546Sopenharmony_ci      const VkCopyDescriptorSet *copyset = &pDescriptorCopies[i];
1202bf215546Sopenharmony_ci      V3DV_FROM_HANDLE(v3dv_descriptor_set, src_set,
1203bf215546Sopenharmony_ci                       copyset->srcSet);
1204bf215546Sopenharmony_ci      V3DV_FROM_HANDLE(v3dv_descriptor_set, dst_set,
1205bf215546Sopenharmony_ci                       copyset->dstSet);
1206bf215546Sopenharmony_ci
1207bf215546Sopenharmony_ci      const struct v3dv_descriptor_set_binding_layout *src_binding_layout =
1208bf215546Sopenharmony_ci         src_set->layout->binding + copyset->srcBinding;
1209bf215546Sopenharmony_ci      const struct v3dv_descriptor_set_binding_layout *dst_binding_layout =
1210bf215546Sopenharmony_ci         dst_set->layout->binding + copyset->dstBinding;
1211bf215546Sopenharmony_ci
1212bf215546Sopenharmony_ci      assert(src_binding_layout->type == dst_binding_layout->type);
1213bf215546Sopenharmony_ci
1214bf215546Sopenharmony_ci      struct v3dv_descriptor *src_descriptor = src_set->descriptors;
1215bf215546Sopenharmony_ci      struct v3dv_descriptor *dst_descriptor = dst_set->descriptors;
1216bf215546Sopenharmony_ci
1217bf215546Sopenharmony_ci      src_descriptor += src_binding_layout->descriptor_index;
1218bf215546Sopenharmony_ci      dst_descriptor += dst_binding_layout->descriptor_index;
1219bf215546Sopenharmony_ci
1220bf215546Sopenharmony_ci      if (src_binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
1221bf215546Sopenharmony_ci         /* {src,dst}ArrayElement specifies src/dst start offset and
1222bf215546Sopenharmony_ci          * descriptorCount specifies size (in bytes) to copy.
1223bf215546Sopenharmony_ci          */
1224bf215546Sopenharmony_ci         const void *src_data = src_set->pool->bo->map +
1225bf215546Sopenharmony_ci                                src_set->base_offset +
1226bf215546Sopenharmony_ci                                src_binding_layout->descriptor_offset +
1227bf215546Sopenharmony_ci                                copyset->srcArrayElement;
1228bf215546Sopenharmony_ci         write_inline_uniform_descriptor(device, dst_descriptor, dst_set,
1229bf215546Sopenharmony_ci                                         dst_binding_layout,
1230bf215546Sopenharmony_ci                                         src_data,
1231bf215546Sopenharmony_ci                                         copyset->dstArrayElement,
1232bf215546Sopenharmony_ci                                         copyset->descriptorCount);
1233bf215546Sopenharmony_ci         continue;
1234bf215546Sopenharmony_ci      }
1235bf215546Sopenharmony_ci
1236bf215546Sopenharmony_ci      src_descriptor += copyset->srcArrayElement;
1237bf215546Sopenharmony_ci      dst_descriptor += copyset->dstArrayElement;
1238bf215546Sopenharmony_ci
1239bf215546Sopenharmony_ci      for (uint32_t j = 0; j < copyset->descriptorCount; j++) {
1240bf215546Sopenharmony_ci         *dst_descriptor = *src_descriptor;
1241bf215546Sopenharmony_ci         dst_descriptor++;
1242bf215546Sopenharmony_ci         src_descriptor++;
1243bf215546Sopenharmony_ci
1244bf215546Sopenharmony_ci         if (v3dv_X(device, descriptor_bo_size)(src_binding_layout->type) > 0) {
1245bf215546Sopenharmony_ci            descriptor_bo_copy(device,
1246bf215546Sopenharmony_ci                               dst_set, dst_binding_layout,
1247bf215546Sopenharmony_ci                               j + copyset->dstArrayElement,
1248bf215546Sopenharmony_ci                               src_set, src_binding_layout,
1249bf215546Sopenharmony_ci                               j + copyset->srcArrayElement);
1250bf215546Sopenharmony_ci         }
1251bf215546Sopenharmony_ci
1252bf215546Sopenharmony_ci      }
1253bf215546Sopenharmony_ci   }
1254bf215546Sopenharmony_ci}
1255bf215546Sopenharmony_ci
1256bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1257bf215546Sopenharmony_civ3dv_GetDescriptorSetLayoutSupport(
1258bf215546Sopenharmony_ci   VkDevice _device,
1259bf215546Sopenharmony_ci   const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
1260bf215546Sopenharmony_ci   VkDescriptorSetLayoutSupport *pSupport)
1261bf215546Sopenharmony_ci{
1262bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
1263bf215546Sopenharmony_ci   VkDescriptorSetLayoutBinding *bindings = NULL;
1264bf215546Sopenharmony_ci   VkResult result = vk_create_sorted_bindings(
1265bf215546Sopenharmony_ci      pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings);
1266bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
1267bf215546Sopenharmony_ci      pSupport->supported = false;
1268bf215546Sopenharmony_ci      return;
1269bf215546Sopenharmony_ci   }
1270bf215546Sopenharmony_ci
1271bf215546Sopenharmony_ci   bool supported = true;
1272bf215546Sopenharmony_ci
1273bf215546Sopenharmony_ci   uint32_t desc_host_size = sizeof(struct v3dv_descriptor);
1274bf215546Sopenharmony_ci   uint32_t host_size = sizeof(struct v3dv_descriptor_set);
1275bf215546Sopenharmony_ci   uint32_t bo_size = 0;
1276bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
1277bf215546Sopenharmony_ci      const VkDescriptorSetLayoutBinding *binding = bindings + i;
1278bf215546Sopenharmony_ci
1279bf215546Sopenharmony_ci      if ((UINT32_MAX - host_size) / desc_host_size < binding->descriptorCount) {
1280bf215546Sopenharmony_ci         supported = false;
1281bf215546Sopenharmony_ci         break;
1282bf215546Sopenharmony_ci      }
1283bf215546Sopenharmony_ci
1284bf215546Sopenharmony_ci      uint32_t desc_bo_size = v3dv_X(device, descriptor_bo_size)(binding->descriptorType);
1285bf215546Sopenharmony_ci      if (desc_bo_size > 0 &&
1286bf215546Sopenharmony_ci          (UINT32_MAX - bo_size) / desc_bo_size < binding->descriptorCount) {
1287bf215546Sopenharmony_ci         supported = false;
1288bf215546Sopenharmony_ci         break;
1289bf215546Sopenharmony_ci      }
1290bf215546Sopenharmony_ci
1291bf215546Sopenharmony_ci      host_size += binding->descriptorCount * desc_host_size;
1292bf215546Sopenharmony_ci      bo_size += binding->descriptorCount * desc_bo_size;
1293bf215546Sopenharmony_ci   }
1294bf215546Sopenharmony_ci
1295bf215546Sopenharmony_ci   free(bindings);
1296bf215546Sopenharmony_ci
1297bf215546Sopenharmony_ci   pSupport->supported = supported;
1298bf215546Sopenharmony_ci}
1299bf215546Sopenharmony_ci
1300bf215546Sopenharmony_ciVkResult
1301bf215546Sopenharmony_civ3dv_CreateDescriptorUpdateTemplate(
1302bf215546Sopenharmony_ci   VkDevice _device,
1303bf215546Sopenharmony_ci   const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
1304bf215546Sopenharmony_ci   const VkAllocationCallbacks *pAllocator,
1305bf215546Sopenharmony_ci   VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)
1306bf215546Sopenharmony_ci{
1307bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
1308bf215546Sopenharmony_ci   struct v3dv_descriptor_update_template *template;
1309bf215546Sopenharmony_ci
1310bf215546Sopenharmony_ci   size_t size = sizeof(*template) +
1311bf215546Sopenharmony_ci      pCreateInfo->descriptorUpdateEntryCount * sizeof(template->entries[0]);
1312bf215546Sopenharmony_ci   template = vk_object_alloc(&device->vk, pAllocator, size,
1313bf215546Sopenharmony_ci                              VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE);
1314bf215546Sopenharmony_ci   if (template == NULL)
1315bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1316bf215546Sopenharmony_ci
1317bf215546Sopenharmony_ci   template->bind_point = pCreateInfo->pipelineBindPoint;
1318bf215546Sopenharmony_ci
1319bf215546Sopenharmony_ci   assert(pCreateInfo->templateType ==
1320bf215546Sopenharmony_ci          VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET);
1321bf215546Sopenharmony_ci   template->set = pCreateInfo->set;
1322bf215546Sopenharmony_ci
1323bf215546Sopenharmony_ci   template->entry_count = pCreateInfo->descriptorUpdateEntryCount;
1324bf215546Sopenharmony_ci   for (uint32_t i = 0; i < template->entry_count; i++) {
1325bf215546Sopenharmony_ci      const VkDescriptorUpdateTemplateEntry *pEntry =
1326bf215546Sopenharmony_ci         &pCreateInfo->pDescriptorUpdateEntries[i];
1327bf215546Sopenharmony_ci
1328bf215546Sopenharmony_ci      template->entries[i] = (struct v3dv_descriptor_template_entry) {
1329bf215546Sopenharmony_ci         .type = pEntry->descriptorType,
1330bf215546Sopenharmony_ci         .binding = pEntry->dstBinding,
1331bf215546Sopenharmony_ci         .array_element = pEntry->dstArrayElement,
1332bf215546Sopenharmony_ci         .array_count = pEntry->descriptorCount,
1333bf215546Sopenharmony_ci         .offset = pEntry->offset,
1334bf215546Sopenharmony_ci         .stride = pEntry->stride,
1335bf215546Sopenharmony_ci      };
1336bf215546Sopenharmony_ci   }
1337bf215546Sopenharmony_ci
1338bf215546Sopenharmony_ci   *pDescriptorUpdateTemplate =
1339bf215546Sopenharmony_ci      v3dv_descriptor_update_template_to_handle(template);
1340bf215546Sopenharmony_ci
1341bf215546Sopenharmony_ci   return VK_SUCCESS;
1342bf215546Sopenharmony_ci}
1343bf215546Sopenharmony_ci
1344bf215546Sopenharmony_civoid
1345bf215546Sopenharmony_civ3dv_DestroyDescriptorUpdateTemplate(
1346bf215546Sopenharmony_ci   VkDevice _device,
1347bf215546Sopenharmony_ci   VkDescriptorUpdateTemplate descriptorUpdateTemplate,
1348bf215546Sopenharmony_ci   const VkAllocationCallbacks *pAllocator)
1349bf215546Sopenharmony_ci{
1350bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
1351bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_descriptor_update_template, template,
1352bf215546Sopenharmony_ci                    descriptorUpdateTemplate);
1353bf215546Sopenharmony_ci
1354bf215546Sopenharmony_ci   if (!template)
1355bf215546Sopenharmony_ci      return;
1356bf215546Sopenharmony_ci
1357bf215546Sopenharmony_ci   vk_object_free(&device->vk, pAllocator, template);
1358bf215546Sopenharmony_ci}
1359bf215546Sopenharmony_ci
1360bf215546Sopenharmony_civoid
1361bf215546Sopenharmony_civ3dv_UpdateDescriptorSetWithTemplate(
1362bf215546Sopenharmony_ci   VkDevice _device,
1363bf215546Sopenharmony_ci   VkDescriptorSet descriptorSet,
1364bf215546Sopenharmony_ci   VkDescriptorUpdateTemplate descriptorUpdateTemplate,
1365bf215546Sopenharmony_ci   const void *pData)
1366bf215546Sopenharmony_ci{
1367bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
1368bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_descriptor_set, set, descriptorSet);
1369bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_descriptor_update_template, template,
1370bf215546Sopenharmony_ci                    descriptorUpdateTemplate);
1371bf215546Sopenharmony_ci
1372bf215546Sopenharmony_ci   for (int i = 0; i < template->entry_count; i++) {
1373bf215546Sopenharmony_ci      const struct v3dv_descriptor_template_entry *entry =
1374bf215546Sopenharmony_ci         &template->entries[i];
1375bf215546Sopenharmony_ci
1376bf215546Sopenharmony_ci      const struct v3dv_descriptor_set_binding_layout *binding_layout =
1377bf215546Sopenharmony_ci         set->layout->binding + entry->binding;
1378bf215546Sopenharmony_ci
1379bf215546Sopenharmony_ci      struct v3dv_descriptor *descriptor =
1380bf215546Sopenharmony_ci         set->descriptors +
1381bf215546Sopenharmony_ci         binding_layout->descriptor_index;
1382bf215546Sopenharmony_ci
1383bf215546Sopenharmony_ci      switch (entry->type) {
1384bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1385bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1386bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1387bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1388bf215546Sopenharmony_ci         for (uint32_t j = 0; j < entry->array_count; j++) {
1389bf215546Sopenharmony_ci            const VkDescriptorBufferInfo *info =
1390bf215546Sopenharmony_ci               pData + entry->offset + j * entry->stride;
1391bf215546Sopenharmony_ci            write_buffer_descriptor(descriptor + entry->array_element + j,
1392bf215546Sopenharmony_ci                                    entry->type, info);
1393bf215546Sopenharmony_ci         }
1394bf215546Sopenharmony_ci         break;
1395bf215546Sopenharmony_ci
1396bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLER:
1397bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1398bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1399bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1400bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1401bf215546Sopenharmony_ci         for (uint32_t j = 0; j < entry->array_count; j++) {
1402bf215546Sopenharmony_ci            const VkDescriptorImageInfo *info =
1403bf215546Sopenharmony_ci               pData + entry->offset + j * entry->stride;
1404bf215546Sopenharmony_ci            V3DV_FROM_HANDLE(v3dv_image_view, iview, info->imageView);
1405bf215546Sopenharmony_ci            V3DV_FROM_HANDLE(v3dv_sampler, sampler, info->sampler);
1406bf215546Sopenharmony_ci            write_image_descriptor(device, descriptor + entry->array_element + j,
1407bf215546Sopenharmony_ci                                   entry->type, set, binding_layout, iview,
1408bf215546Sopenharmony_ci                                   sampler, entry->array_element + j);
1409bf215546Sopenharmony_ci         }
1410bf215546Sopenharmony_ci         break;
1411bf215546Sopenharmony_ci
1412bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1413bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1414bf215546Sopenharmony_ci         for (uint32_t j = 0; j < entry->array_count; j++) {
1415bf215546Sopenharmony_ci            const VkBufferView *_bview =
1416bf215546Sopenharmony_ci               pData + entry->offset + j * entry->stride;
1417bf215546Sopenharmony_ci            V3DV_FROM_HANDLE(v3dv_buffer_view, bview, *_bview);
1418bf215546Sopenharmony_ci            write_buffer_view_descriptor(device,
1419bf215546Sopenharmony_ci                                         descriptor + entry->array_element + j,
1420bf215546Sopenharmony_ci                                         entry->type, set, binding_layout, bview,
1421bf215546Sopenharmony_ci                                         entry->array_element + j);
1422bf215546Sopenharmony_ci         }
1423bf215546Sopenharmony_ci         break;
1424bf215546Sopenharmony_ci
1425bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: {
1426bf215546Sopenharmony_ci         write_inline_uniform_descriptor(device, descriptor, set,
1427bf215546Sopenharmony_ci                                         binding_layout,
1428bf215546Sopenharmony_ci                                         pData + entry->offset,
1429bf215546Sopenharmony_ci                                         entry->array_element, /* offset */
1430bf215546Sopenharmony_ci                                         entry->array_count);  /* size */
1431bf215546Sopenharmony_ci         break;
1432bf215546Sopenharmony_ci      }
1433bf215546Sopenharmony_ci
1434bf215546Sopenharmony_ci      default:
1435bf215546Sopenharmony_ci         unreachable("Unsupported descriptor type");
1436bf215546Sopenharmony_ci      }
1437bf215546Sopenharmony_ci   }
1438bf215546Sopenharmony_ci}
1439bf215546Sopenharmony_ci
1440bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
1441bf215546Sopenharmony_civ3dv_CreateSamplerYcbcrConversion(
1442bf215546Sopenharmony_ci    VkDevice _device,
1443bf215546Sopenharmony_ci    const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
1444bf215546Sopenharmony_ci    const VkAllocationCallbacks *pAllocator,
1445bf215546Sopenharmony_ci    VkSamplerYcbcrConversion *pYcbcrConversion)
1446bf215546Sopenharmony_ci{
1447bf215546Sopenharmony_ci   unreachable("Ycbcr sampler conversion is not supported");
1448bf215546Sopenharmony_ci   return VK_SUCCESS;
1449bf215546Sopenharmony_ci}
1450bf215546Sopenharmony_ci
1451bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1452bf215546Sopenharmony_civ3dv_DestroySamplerYcbcrConversion(
1453bf215546Sopenharmony_ci    VkDevice _device,
1454bf215546Sopenharmony_ci    VkSamplerYcbcrConversion YcbcrConversion,
1455bf215546Sopenharmony_ci    const VkAllocationCallbacks *pAllocator)
1456bf215546Sopenharmony_ci{
1457bf215546Sopenharmony_ci   unreachable("Ycbcr sampler conversion is not supported");
1458bf215546Sopenharmony_ci}
1459