1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2016 Red Hat.
3bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci * Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22bf215546Sopenharmony_ci * IN THE SOFTWARE.
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci#include <assert.h>
25bf215546Sopenharmony_ci#include <fcntl.h>
26bf215546Sopenharmony_ci#include <stdbool.h>
27bf215546Sopenharmony_ci#include <string.h>
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "util/mesa-sha1.h"
30bf215546Sopenharmony_ci#include "radv_private.h"
31bf215546Sopenharmony_ci#include "sid.h"
32bf215546Sopenharmony_ci#include "vk_descriptors.h"
33bf215546Sopenharmony_ci#include "vk_format.h"
34bf215546Sopenharmony_ci#include "vk_util.h"
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_cistatic unsigned
37bf215546Sopenharmony_ciradv_descriptor_type_buffer_count(VkDescriptorType type)
38bf215546Sopenharmony_ci{
39bf215546Sopenharmony_ci   switch (type) {
40bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLER:
41bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
42bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
43bf215546Sopenharmony_ci         return 0;
44bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
45bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
46bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
47bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
48bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_MUTABLE_VALVE:
49bf215546Sopenharmony_ci         return 3;
50bf215546Sopenharmony_ci      default:
51bf215546Sopenharmony_ci         return 1;
52bf215546Sopenharmony_ci   }
53bf215546Sopenharmony_ci}
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_cistatic bool
56bf215546Sopenharmony_cihas_equal_immutable_samplers(const VkSampler *samplers, uint32_t count)
57bf215546Sopenharmony_ci{
58bf215546Sopenharmony_ci   if (!samplers)
59bf215546Sopenharmony_ci      return false;
60bf215546Sopenharmony_ci   for (uint32_t i = 1; i < count; ++i) {
61bf215546Sopenharmony_ci      if (memcmp(radv_sampler_from_handle(samplers[0])->state,
62bf215546Sopenharmony_ci                 radv_sampler_from_handle(samplers[i])->state, 16)) {
63bf215546Sopenharmony_ci         return false;
64bf215546Sopenharmony_ci      }
65bf215546Sopenharmony_ci   }
66bf215546Sopenharmony_ci   return true;
67bf215546Sopenharmony_ci}
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_cistatic bool
70bf215546Sopenharmony_ciradv_mutable_descriptor_type_size_alignment(const VkMutableDescriptorTypeListVALVE *list,
71bf215546Sopenharmony_ci                                            uint64_t *out_size, uint64_t *out_align)
72bf215546Sopenharmony_ci{
73bf215546Sopenharmony_ci   uint32_t max_size = 0;
74bf215546Sopenharmony_ci   uint32_t max_align = 0;
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   for (uint32_t i = 0; i < list->descriptorTypeCount; i++) {
77bf215546Sopenharmony_ci      uint32_t size = 0;
78bf215546Sopenharmony_ci      uint32_t align = 0;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci      switch (list->pDescriptorTypes[i]) {
81bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
82bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
83bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
84bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
85bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLER:
86bf215546Sopenharmony_ci         size = 16;
87bf215546Sopenharmony_ci         align = 16;
88bf215546Sopenharmony_ci         break;
89bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
90bf215546Sopenharmony_ci         size = 32;
91bf215546Sopenharmony_ci         align = 32;
92bf215546Sopenharmony_ci         break;
93bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
94bf215546Sopenharmony_ci         size = 64;
95bf215546Sopenharmony_ci         align = 32;
96bf215546Sopenharmony_ci         break;
97bf215546Sopenharmony_ci      default:
98bf215546Sopenharmony_ci         return false;
99bf215546Sopenharmony_ci      }
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci      max_size = MAX2(max_size, size);
102bf215546Sopenharmony_ci      max_align = MAX2(max_align, align);
103bf215546Sopenharmony_ci   }
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   *out_size = max_size;
106bf215546Sopenharmony_ci   *out_align = max_align;
107bf215546Sopenharmony_ci   return true;
108bf215546Sopenharmony_ci}
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
111bf215546Sopenharmony_ciradv_CreateDescriptorSetLayout(VkDevice _device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
112bf215546Sopenharmony_ci                               const VkAllocationCallbacks *pAllocator,
113bf215546Sopenharmony_ci                               VkDescriptorSetLayout *pSetLayout)
114bf215546Sopenharmony_ci{
115bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
116bf215546Sopenharmony_ci   struct radv_descriptor_set_layout *set_layout;
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
119bf215546Sopenharmony_ci   const VkDescriptorSetLayoutBindingFlagsCreateInfo *variable_flags =
120bf215546Sopenharmony_ci      vk_find_struct_const(pCreateInfo->pNext, DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO);
121bf215546Sopenharmony_ci   const VkMutableDescriptorTypeCreateInfoVALVE *mutable_info =
122bf215546Sopenharmony_ci      vk_find_struct_const(pCreateInfo->pNext, MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE);
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   uint32_t num_bindings = 0;
125bf215546Sopenharmony_ci   uint32_t immutable_sampler_count = 0;
126bf215546Sopenharmony_ci   uint32_t ycbcr_sampler_count = 0;
127bf215546Sopenharmony_ci   for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
128bf215546Sopenharmony_ci      num_bindings = MAX2(num_bindings, pCreateInfo->pBindings[j].binding + 1);
129bf215546Sopenharmony_ci      if ((pCreateInfo->pBindings[j].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
130bf215546Sopenharmony_ci           pCreateInfo->pBindings[j].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) &&
131bf215546Sopenharmony_ci          pCreateInfo->pBindings[j].pImmutableSamplers) {
132bf215546Sopenharmony_ci         immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount;
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci         bool has_ycbcr_sampler = false;
135bf215546Sopenharmony_ci         for (unsigned i = 0; i < pCreateInfo->pBindings[j].descriptorCount; ++i) {
136bf215546Sopenharmony_ci            if (radv_sampler_from_handle(pCreateInfo->pBindings[j].pImmutableSamplers[i])
137bf215546Sopenharmony_ci                   ->ycbcr_sampler)
138bf215546Sopenharmony_ci               has_ycbcr_sampler = true;
139bf215546Sopenharmony_ci         }
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci         if (has_ycbcr_sampler)
142bf215546Sopenharmony_ci            ycbcr_sampler_count += pCreateInfo->pBindings[j].descriptorCount;
143bf215546Sopenharmony_ci      }
144bf215546Sopenharmony_ci   }
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci   uint32_t samplers_offset = offsetof(struct radv_descriptor_set_layout, binding[num_bindings]);
147bf215546Sopenharmony_ci   size_t size = samplers_offset + immutable_sampler_count * 4 * sizeof(uint32_t);
148bf215546Sopenharmony_ci   if (ycbcr_sampler_count > 0) {
149bf215546Sopenharmony_ci      /* Store block of offsets first, followed by the conversion descriptors (padded to the struct
150bf215546Sopenharmony_ci       * alignment) */
151bf215546Sopenharmony_ci      size += num_bindings * sizeof(uint32_t);
152bf215546Sopenharmony_ci      size = ALIGN(size, alignof(struct radv_sampler_ycbcr_conversion_state));
153bf215546Sopenharmony_ci      size += ycbcr_sampler_count * sizeof(struct radv_sampler_ycbcr_conversion_state);
154bf215546Sopenharmony_ci   }
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci   /* We need to allocate decriptor set layouts off the device allocator with DEVICE scope because
157bf215546Sopenharmony_ci    * they are reference counted and may not be destroyed when vkDestroyDescriptorSetLayout is
158bf215546Sopenharmony_ci    * called.
159bf215546Sopenharmony_ci    */
160bf215546Sopenharmony_ci   set_layout = vk_descriptor_set_layout_zalloc(&device->vk, size);
161bf215546Sopenharmony_ci   if (!set_layout)
162bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci   set_layout->flags = pCreateInfo->flags;
165bf215546Sopenharmony_ci   set_layout->layout_size = size;
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci   /* We just allocate all the samplers at the end of the struct */
168bf215546Sopenharmony_ci   uint32_t *samplers = (uint32_t *)&set_layout->binding[num_bindings];
169bf215546Sopenharmony_ci   struct radv_sampler_ycbcr_conversion_state *ycbcr_samplers = NULL;
170bf215546Sopenharmony_ci   uint32_t *ycbcr_sampler_offsets = NULL;
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci   if (ycbcr_sampler_count > 0) {
173bf215546Sopenharmony_ci      ycbcr_sampler_offsets = samplers + 4 * immutable_sampler_count;
174bf215546Sopenharmony_ci      set_layout->ycbcr_sampler_offsets_offset = (char *)ycbcr_sampler_offsets - (char *)set_layout;
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci      uintptr_t first_ycbcr_sampler_offset =
177bf215546Sopenharmony_ci         (uintptr_t)ycbcr_sampler_offsets + sizeof(uint32_t) * num_bindings;
178bf215546Sopenharmony_ci      first_ycbcr_sampler_offset =
179bf215546Sopenharmony_ci         ALIGN(first_ycbcr_sampler_offset, alignof(struct radv_sampler_ycbcr_conversion_state));
180bf215546Sopenharmony_ci      ycbcr_samplers = (struct radv_sampler_ycbcr_conversion_state *)first_ycbcr_sampler_offset;
181bf215546Sopenharmony_ci   } else
182bf215546Sopenharmony_ci      set_layout->ycbcr_sampler_offsets_offset = 0;
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci   VkDescriptorSetLayoutBinding *bindings = NULL;
185bf215546Sopenharmony_ci   VkResult result =
186bf215546Sopenharmony_ci      vk_create_sorted_bindings(pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings);
187bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
188bf215546Sopenharmony_ci      vk_descriptor_set_layout_unref(&device->vk, &set_layout->vk);
189bf215546Sopenharmony_ci      return vk_error(device, result);
190bf215546Sopenharmony_ci   }
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci   set_layout->binding_count = num_bindings;
193bf215546Sopenharmony_ci   set_layout->shader_stages = 0;
194bf215546Sopenharmony_ci   set_layout->dynamic_shader_stages = 0;
195bf215546Sopenharmony_ci   set_layout->has_immutable_samplers = false;
196bf215546Sopenharmony_ci   set_layout->size = 0;
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci   uint32_t buffer_count = 0;
199bf215546Sopenharmony_ci   uint32_t dynamic_offset_count = 0;
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
202bf215546Sopenharmony_ci      const VkDescriptorSetLayoutBinding *binding = bindings + j;
203bf215546Sopenharmony_ci      uint32_t b = binding->binding;
204bf215546Sopenharmony_ci      uint32_t alignment = 0;
205bf215546Sopenharmony_ci      unsigned binding_buffer_count =
206bf215546Sopenharmony_ci         radv_descriptor_type_buffer_count(binding->descriptorType);
207bf215546Sopenharmony_ci      uint32_t descriptor_count = binding->descriptorCount;
208bf215546Sopenharmony_ci      bool has_ycbcr_sampler = false;
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci      /* main image + fmask */
211bf215546Sopenharmony_ci      uint32_t max_sampled_image_descriptors = 2;
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci      if (binding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER &&
214bf215546Sopenharmony_ci          binding->pImmutableSamplers) {
215bf215546Sopenharmony_ci         for (unsigned i = 0; i < binding->descriptorCount; ++i) {
216bf215546Sopenharmony_ci            struct radv_sampler_ycbcr_conversion *conversion =
217bf215546Sopenharmony_ci               radv_sampler_from_handle(binding->pImmutableSamplers[i])->ycbcr_sampler;
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci            if (conversion) {
220bf215546Sopenharmony_ci               has_ycbcr_sampler = true;
221bf215546Sopenharmony_ci               max_sampled_image_descriptors = MAX2(max_sampled_image_descriptors,
222bf215546Sopenharmony_ci                                                    vk_format_get_plane_count(conversion->state.format));
223bf215546Sopenharmony_ci            }
224bf215546Sopenharmony_ci         }
225bf215546Sopenharmony_ci      }
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci      switch (binding->descriptorType) {
228bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
229bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
230bf215546Sopenharmony_ci         assert(!(pCreateInfo->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
231bf215546Sopenharmony_ci         set_layout->binding[b].dynamic_offset_count = 1;
232bf215546Sopenharmony_ci         set_layout->dynamic_shader_stages |= binding->stageFlags;
233bf215546Sopenharmony_ci         if (binding->stageFlags & RADV_RT_STAGE_BITS)
234bf215546Sopenharmony_ci            set_layout->dynamic_shader_stages |= VK_SHADER_STAGE_COMPUTE_BIT;
235bf215546Sopenharmony_ci         set_layout->binding[b].size = 0;
236bf215546Sopenharmony_ci         alignment = 1;
237bf215546Sopenharmony_ci         break;
238bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
239bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
240bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
241bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
242bf215546Sopenharmony_ci         set_layout->binding[b].size = 16;
243bf215546Sopenharmony_ci         alignment = 16;
244bf215546Sopenharmony_ci         break;
245bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
246bf215546Sopenharmony_ci         set_layout->binding[b].size = 32;
247bf215546Sopenharmony_ci         alignment = 32;
248bf215546Sopenharmony_ci         break;
249bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
250bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
251bf215546Sopenharmony_ci         /* main descriptor + fmask descriptor */
252bf215546Sopenharmony_ci         set_layout->binding[b].size = 64;
253bf215546Sopenharmony_ci         alignment = 32;
254bf215546Sopenharmony_ci         break;
255bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
256bf215546Sopenharmony_ci         /* main descriptor + fmask descriptor + sampler */
257bf215546Sopenharmony_ci         set_layout->binding[b].size = 96;
258bf215546Sopenharmony_ci         alignment = 32;
259bf215546Sopenharmony_ci         break;
260bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLER:
261bf215546Sopenharmony_ci         set_layout->binding[b].size = 16;
262bf215546Sopenharmony_ci         alignment = 16;
263bf215546Sopenharmony_ci         break;
264bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_MUTABLE_VALVE: {
265bf215546Sopenharmony_ci         uint64_t mutable_size = 0, mutable_align = 0;
266bf215546Sopenharmony_ci         radv_mutable_descriptor_type_size_alignment(&mutable_info->pMutableDescriptorTypeLists[j],
267bf215546Sopenharmony_ci                                                     &mutable_size, &mutable_align);
268bf215546Sopenharmony_ci         assert(mutable_size && mutable_align);
269bf215546Sopenharmony_ci         set_layout->binding[b].size = mutable_size;
270bf215546Sopenharmony_ci         alignment = mutable_align;
271bf215546Sopenharmony_ci         break;
272bf215546Sopenharmony_ci      }
273bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
274bf215546Sopenharmony_ci         alignment = 16;
275bf215546Sopenharmony_ci         set_layout->binding[b].size = descriptor_count;
276bf215546Sopenharmony_ci         descriptor_count = 1;
277bf215546Sopenharmony_ci         break;
278bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
279bf215546Sopenharmony_ci         set_layout->binding[b].size = 16;
280bf215546Sopenharmony_ci         alignment = 16;
281bf215546Sopenharmony_ci         break;
282bf215546Sopenharmony_ci      default:
283bf215546Sopenharmony_ci         break;
284bf215546Sopenharmony_ci      }
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci      set_layout->size = align(set_layout->size, alignment);
287bf215546Sopenharmony_ci      set_layout->binding[b].type = binding->descriptorType;
288bf215546Sopenharmony_ci      set_layout->binding[b].array_size = descriptor_count;
289bf215546Sopenharmony_ci      set_layout->binding[b].offset = set_layout->size;
290bf215546Sopenharmony_ci      set_layout->binding[b].buffer_offset = buffer_count;
291bf215546Sopenharmony_ci      set_layout->binding[b].dynamic_offset_offset = dynamic_offset_count;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci      if (variable_flags && binding->binding < variable_flags->bindingCount &&
294bf215546Sopenharmony_ci          (variable_flags->pBindingFlags[binding->binding] &
295bf215546Sopenharmony_ci           VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT)) {
296bf215546Sopenharmony_ci         assert(
297bf215546Sopenharmony_ci            !binding->pImmutableSamplers); /* Terribly ill defined  how many samplers are valid */
298bf215546Sopenharmony_ci         assert(binding->binding == num_bindings - 1);
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_ci         set_layout->has_variable_descriptors = true;
301bf215546Sopenharmony_ci      }
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci      if ((binding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
304bf215546Sopenharmony_ci           binding->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) &&
305bf215546Sopenharmony_ci          binding->pImmutableSamplers) {
306bf215546Sopenharmony_ci         set_layout->binding[b].immutable_samplers_offset = samplers_offset;
307bf215546Sopenharmony_ci         set_layout->binding[b].immutable_samplers_equal =
308bf215546Sopenharmony_ci            has_equal_immutable_samplers(binding->pImmutableSamplers, binding->descriptorCount);
309bf215546Sopenharmony_ci         set_layout->has_immutable_samplers = true;
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci         for (uint32_t i = 0; i < binding->descriptorCount; i++)
312bf215546Sopenharmony_ci            memcpy(samplers + 4 * i,
313bf215546Sopenharmony_ci                   &radv_sampler_from_handle(binding->pImmutableSamplers[i])->state, 16);
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci         /* Don't reserve space for the samplers if they're not accessed. */
316bf215546Sopenharmony_ci         if (set_layout->binding[b].immutable_samplers_equal) {
317bf215546Sopenharmony_ci            if (binding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER &&
318bf215546Sopenharmony_ci                max_sampled_image_descriptors <= 2)
319bf215546Sopenharmony_ci               set_layout->binding[b].size -= 32;
320bf215546Sopenharmony_ci            else if (binding->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
321bf215546Sopenharmony_ci               set_layout->binding[b].size -= 16;
322bf215546Sopenharmony_ci         }
323bf215546Sopenharmony_ci         samplers += 4 * binding->descriptorCount;
324bf215546Sopenharmony_ci         samplers_offset += 4 * sizeof(uint32_t) * binding->descriptorCount;
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci         if (has_ycbcr_sampler) {
327bf215546Sopenharmony_ci            ycbcr_sampler_offsets[b] = (const char *)ycbcr_samplers - (const char *)set_layout;
328bf215546Sopenharmony_ci            for (uint32_t i = 0; i < binding->descriptorCount; i++) {
329bf215546Sopenharmony_ci               if (radv_sampler_from_handle(binding->pImmutableSamplers[i])->ycbcr_sampler)
330bf215546Sopenharmony_ci                  ycbcr_samplers[i] =
331bf215546Sopenharmony_ci                     radv_sampler_from_handle(binding->pImmutableSamplers[i])->ycbcr_sampler->state;
332bf215546Sopenharmony_ci               else
333bf215546Sopenharmony_ci                  ycbcr_samplers[i].format = VK_FORMAT_UNDEFINED;
334bf215546Sopenharmony_ci            }
335bf215546Sopenharmony_ci            ycbcr_samplers += binding->descriptorCount;
336bf215546Sopenharmony_ci         }
337bf215546Sopenharmony_ci      }
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci      set_layout->size += descriptor_count * set_layout->binding[b].size;
340bf215546Sopenharmony_ci      buffer_count += descriptor_count * binding_buffer_count;
341bf215546Sopenharmony_ci      dynamic_offset_count += descriptor_count * set_layout->binding[b].dynamic_offset_count;
342bf215546Sopenharmony_ci      set_layout->shader_stages |= binding->stageFlags;
343bf215546Sopenharmony_ci   }
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   free(bindings);
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci   set_layout->buffer_count = buffer_count;
348bf215546Sopenharmony_ci   set_layout->dynamic_offset_count = dynamic_offset_count;
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci   *pSetLayout = radv_descriptor_set_layout_to_handle(set_layout);
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci   return VK_SUCCESS;
353bf215546Sopenharmony_ci}
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
356bf215546Sopenharmony_ciradv_GetDescriptorSetLayoutSupport(VkDevice device,
357bf215546Sopenharmony_ci                                   const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
358bf215546Sopenharmony_ci                                   VkDescriptorSetLayoutSupport *pSupport)
359bf215546Sopenharmony_ci{
360bf215546Sopenharmony_ci   VkDescriptorSetLayoutBinding *bindings = NULL;
361bf215546Sopenharmony_ci   VkResult result =
362bf215546Sopenharmony_ci      vk_create_sorted_bindings(pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings);
363bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
364bf215546Sopenharmony_ci      pSupport->supported = false;
365bf215546Sopenharmony_ci      return;
366bf215546Sopenharmony_ci   }
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci   const VkDescriptorSetLayoutBindingFlagsCreateInfo *variable_flags =
369bf215546Sopenharmony_ci      vk_find_struct_const(pCreateInfo->pNext, DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO);
370bf215546Sopenharmony_ci   VkDescriptorSetVariableDescriptorCountLayoutSupport *variable_count = vk_find_struct(
371bf215546Sopenharmony_ci      (void *)pCreateInfo->pNext, DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT);
372bf215546Sopenharmony_ci   const VkMutableDescriptorTypeCreateInfoVALVE *mutable_info =
373bf215546Sopenharmony_ci      vk_find_struct_const(pCreateInfo->pNext, MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE);
374bf215546Sopenharmony_ci   if (variable_count) {
375bf215546Sopenharmony_ci      variable_count->maxVariableDescriptorCount = 0;
376bf215546Sopenharmony_ci   }
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   bool supported = true;
379bf215546Sopenharmony_ci   uint64_t size = 0;
380bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
381bf215546Sopenharmony_ci      const VkDescriptorSetLayoutBinding *binding = bindings + i;
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci      uint64_t descriptor_size = 0;
384bf215546Sopenharmony_ci      uint64_t descriptor_alignment = 1;
385bf215546Sopenharmony_ci      uint32_t descriptor_count = binding->descriptorCount;
386bf215546Sopenharmony_ci      switch (binding->descriptorType) {
387bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
388bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
389bf215546Sopenharmony_ci         break;
390bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
391bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
392bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
393bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
394bf215546Sopenharmony_ci         descriptor_size = 16;
395bf215546Sopenharmony_ci         descriptor_alignment = 16;
396bf215546Sopenharmony_ci         break;
397bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
398bf215546Sopenharmony_ci         descriptor_size = 32;
399bf215546Sopenharmony_ci         descriptor_alignment = 32;
400bf215546Sopenharmony_ci         break;
401bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
402bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
403bf215546Sopenharmony_ci         descriptor_size = 64;
404bf215546Sopenharmony_ci         descriptor_alignment = 32;
405bf215546Sopenharmony_ci         break;
406bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
407bf215546Sopenharmony_ci         if (!has_equal_immutable_samplers(binding->pImmutableSamplers, descriptor_count)) {
408bf215546Sopenharmony_ci            descriptor_size = 64;
409bf215546Sopenharmony_ci         } else {
410bf215546Sopenharmony_ci            descriptor_size = 96;
411bf215546Sopenharmony_ci         }
412bf215546Sopenharmony_ci         descriptor_alignment = 32;
413bf215546Sopenharmony_ci         break;
414bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLER:
415bf215546Sopenharmony_ci         if (!has_equal_immutable_samplers(binding->pImmutableSamplers, descriptor_count)) {
416bf215546Sopenharmony_ci            descriptor_size = 16;
417bf215546Sopenharmony_ci            descriptor_alignment = 16;
418bf215546Sopenharmony_ci         }
419bf215546Sopenharmony_ci         break;
420bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
421bf215546Sopenharmony_ci         descriptor_alignment = 16;
422bf215546Sopenharmony_ci         descriptor_size = descriptor_count;
423bf215546Sopenharmony_ci         descriptor_count = 1;
424bf215546Sopenharmony_ci         break;
425bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_MUTABLE_VALVE:
426bf215546Sopenharmony_ci         if (!radv_mutable_descriptor_type_size_alignment(
427bf215546Sopenharmony_ci                &mutable_info->pMutableDescriptorTypeLists[i], &descriptor_size,
428bf215546Sopenharmony_ci                &descriptor_alignment)) {
429bf215546Sopenharmony_ci            supported = false;
430bf215546Sopenharmony_ci         }
431bf215546Sopenharmony_ci         break;
432bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
433bf215546Sopenharmony_ci         descriptor_size = 16;
434bf215546Sopenharmony_ci         descriptor_alignment = 16;
435bf215546Sopenharmony_ci         break;
436bf215546Sopenharmony_ci      default:
437bf215546Sopenharmony_ci         break;
438bf215546Sopenharmony_ci      }
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci      if (size && !align_u64(size, descriptor_alignment)) {
441bf215546Sopenharmony_ci         supported = false;
442bf215546Sopenharmony_ci      }
443bf215546Sopenharmony_ci      size = align_u64(size, descriptor_alignment);
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ci      uint64_t max_count = INT32_MAX;
446bf215546Sopenharmony_ci      if (binding->descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK)
447bf215546Sopenharmony_ci         max_count = INT32_MAX - size;
448bf215546Sopenharmony_ci      else if (descriptor_size)
449bf215546Sopenharmony_ci         max_count = (INT32_MAX - size) / descriptor_size;
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci      if (max_count < descriptor_count) {
452bf215546Sopenharmony_ci         supported = false;
453bf215546Sopenharmony_ci      }
454bf215546Sopenharmony_ci      if (variable_flags && binding->binding < variable_flags->bindingCount && variable_count &&
455bf215546Sopenharmony_ci          (variable_flags->pBindingFlags[binding->binding] &
456bf215546Sopenharmony_ci           VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT)) {
457bf215546Sopenharmony_ci         variable_count->maxVariableDescriptorCount = MIN2(UINT32_MAX, max_count);
458bf215546Sopenharmony_ci      }
459bf215546Sopenharmony_ci      size += descriptor_count * descriptor_size;
460bf215546Sopenharmony_ci   }
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci   free(bindings);
463bf215546Sopenharmony_ci
464bf215546Sopenharmony_ci   pSupport->supported = supported;
465bf215546Sopenharmony_ci}
466bf215546Sopenharmony_ci
467bf215546Sopenharmony_ci/*
468bf215546Sopenharmony_ci * Pipeline layouts.  These have nothing to do with the pipeline.  They are
469bf215546Sopenharmony_ci * just multiple descriptor set layouts pasted together.
470bf215546Sopenharmony_ci */
471bf215546Sopenharmony_civoid
472bf215546Sopenharmony_ciradv_pipeline_layout_init(struct radv_device *device, struct radv_pipeline_layout *layout,
473bf215546Sopenharmony_ci                          bool independent_sets)
474bf215546Sopenharmony_ci{
475bf215546Sopenharmony_ci   memset(layout, 0, sizeof(*layout));
476bf215546Sopenharmony_ci
477bf215546Sopenharmony_ci   vk_object_base_init(&device->vk, &layout->base, VK_OBJECT_TYPE_PIPELINE_LAYOUT);
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci   layout->independent_sets = independent_sets;
480bf215546Sopenharmony_ci}
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_civoid
483bf215546Sopenharmony_ciradv_pipeline_layout_add_set(struct radv_pipeline_layout *layout, uint32_t set_idx,
484bf215546Sopenharmony_ci                             struct radv_descriptor_set_layout *set_layout)
485bf215546Sopenharmony_ci{
486bf215546Sopenharmony_ci   unsigned dynamic_offset_count = 0;
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci   if (layout->set[set_idx].layout)
489bf215546Sopenharmony_ci      return;
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci   layout->num_sets = MAX2(set_idx + 1, layout->num_sets);
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_ci   layout->set[set_idx].layout = set_layout;
494bf215546Sopenharmony_ci   vk_descriptor_set_layout_ref(&set_layout->vk);
495bf215546Sopenharmony_ci
496bf215546Sopenharmony_ci   for (uint32_t b = 0; b < set_layout->binding_count; b++) {
497bf215546Sopenharmony_ci      dynamic_offset_count += set_layout->binding[b].array_size * set_layout->binding[b].dynamic_offset_count;
498bf215546Sopenharmony_ci   }
499bf215546Sopenharmony_ci
500bf215546Sopenharmony_ci   layout->set[set_idx].dynamic_offset_start = layout->dynamic_offset_count;
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci   layout->dynamic_offset_count += dynamic_offset_count;
503bf215546Sopenharmony_ci   layout->dynamic_shader_stages |= set_layout->dynamic_shader_stages;
504bf215546Sopenharmony_ci}
505bf215546Sopenharmony_ci
506bf215546Sopenharmony_civoid
507bf215546Sopenharmony_ciradv_pipeline_layout_hash(struct radv_pipeline_layout *layout)
508bf215546Sopenharmony_ci{
509bf215546Sopenharmony_ci   struct mesa_sha1 ctx;
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci   _mesa_sha1_init(&ctx);
512bf215546Sopenharmony_ci   for (uint32_t i = 0; i < layout->num_sets; i++) {
513bf215546Sopenharmony_ci      struct radv_descriptor_set_layout *set_layout = layout->set[i].layout;
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci      if (!set_layout)
516bf215546Sopenharmony_ci         continue;
517bf215546Sopenharmony_ci
518bf215546Sopenharmony_ci      /* Hash the entire set layout except for the vk_object_base and the reference counter. The
519bf215546Sopenharmony_ci       * rest of the set layout is carefully constructed to not have pointers so a full hash instead
520bf215546Sopenharmony_ci       * of a per-field hash should be ok.
521bf215546Sopenharmony_ci       */
522bf215546Sopenharmony_ci      uint32_t hash_offset = sizeof(struct vk_object_base) + sizeof(uint32_t);
523bf215546Sopenharmony_ci      _mesa_sha1_update(&ctx, (const char *)set_layout + hash_offset,
524bf215546Sopenharmony_ci                        set_layout->layout_size - hash_offset);
525bf215546Sopenharmony_ci   }
526bf215546Sopenharmony_ci   _mesa_sha1_update(&ctx, &layout->push_constant_size, sizeof(layout->push_constant_size));
527bf215546Sopenharmony_ci   _mesa_sha1_final(&ctx, layout->sha1);
528bf215546Sopenharmony_ci}
529bf215546Sopenharmony_ci
530bf215546Sopenharmony_civoid
531bf215546Sopenharmony_ciradv_pipeline_layout_finish(struct radv_device *device, struct radv_pipeline_layout *layout)
532bf215546Sopenharmony_ci{
533bf215546Sopenharmony_ci   for (uint32_t i = 0; i < layout->num_sets; i++) {
534bf215546Sopenharmony_ci      if (!layout->set[i].layout)
535bf215546Sopenharmony_ci         continue;
536bf215546Sopenharmony_ci
537bf215546Sopenharmony_ci      vk_descriptor_set_layout_unref(&device->vk, &layout->set[i].layout->vk);
538bf215546Sopenharmony_ci   }
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_ci   vk_object_base_finish(&layout->base);
541bf215546Sopenharmony_ci}
542bf215546Sopenharmony_ci
543bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
544bf215546Sopenharmony_ciradv_CreatePipelineLayout(VkDevice _device, const VkPipelineLayoutCreateInfo *pCreateInfo,
545bf215546Sopenharmony_ci                          const VkAllocationCallbacks *pAllocator,
546bf215546Sopenharmony_ci                          VkPipelineLayout *pPipelineLayout)
547bf215546Sopenharmony_ci{
548bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
549bf215546Sopenharmony_ci   struct radv_pipeline_layout *layout;
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
552bf215546Sopenharmony_ci
553bf215546Sopenharmony_ci   layout = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*layout), 8,
554bf215546Sopenharmony_ci                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
555bf215546Sopenharmony_ci   if (layout == NULL)
556bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci   radv_pipeline_layout_init(device, layout,
559bf215546Sopenharmony_ci                             pCreateInfo->flags & VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_ci   layout->num_sets = pCreateInfo->setLayoutCount;
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_ci   for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) {
564bf215546Sopenharmony_ci      RADV_FROM_HANDLE(radv_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[set]);
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_ci      /* From the Vulkan spec 1.3.211:
567bf215546Sopenharmony_ci       *
568bf215546Sopenharmony_ci       * "VUID-VkPipelineLayoutCreateInfo-flags-06562
569bf215546Sopenharmony_ci       *  If flags: does not include VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT, elements of
570bf215546Sopenharmony_ci       *  pSetLayouts must be valid VkDescriptorSetLayout objects"
571bf215546Sopenharmony_ci       */
572bf215546Sopenharmony_ci      if (set_layout == NULL) {
573bf215546Sopenharmony_ci         assert(layout->independent_sets);
574bf215546Sopenharmony_ci         continue;
575bf215546Sopenharmony_ci      }
576bf215546Sopenharmony_ci
577bf215546Sopenharmony_ci      radv_pipeline_layout_add_set(layout, set, set_layout);
578bf215546Sopenharmony_ci   }
579bf215546Sopenharmony_ci
580bf215546Sopenharmony_ci   layout->push_constant_size = 0;
581bf215546Sopenharmony_ci
582bf215546Sopenharmony_ci   for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
583bf215546Sopenharmony_ci      const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i;
584bf215546Sopenharmony_ci      layout->push_constant_size = MAX2(layout->push_constant_size, range->offset + range->size);
585bf215546Sopenharmony_ci   }
586bf215546Sopenharmony_ci
587bf215546Sopenharmony_ci   layout->push_constant_size = align(layout->push_constant_size, 16);
588bf215546Sopenharmony_ci
589bf215546Sopenharmony_ci   radv_pipeline_layout_hash(layout);
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_ci   *pPipelineLayout = radv_pipeline_layout_to_handle(layout);
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci   return VK_SUCCESS;
594bf215546Sopenharmony_ci}
595bf215546Sopenharmony_ci
596bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
597bf215546Sopenharmony_ciradv_DestroyPipelineLayout(VkDevice _device, VkPipelineLayout _pipelineLayout,
598bf215546Sopenharmony_ci                           const VkAllocationCallbacks *pAllocator)
599bf215546Sopenharmony_ci{
600bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
601bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_pipeline_layout, pipeline_layout, _pipelineLayout);
602bf215546Sopenharmony_ci
603bf215546Sopenharmony_ci   if (!pipeline_layout)
604bf215546Sopenharmony_ci      return;
605bf215546Sopenharmony_ci
606bf215546Sopenharmony_ci   radv_pipeline_layout_finish(device, pipeline_layout);
607bf215546Sopenharmony_ci
608bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, pAllocator, pipeline_layout);
609bf215546Sopenharmony_ci}
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_cistatic VkResult
612bf215546Sopenharmony_ciradv_descriptor_set_create(struct radv_device *device, struct radv_descriptor_pool *pool,
613bf215546Sopenharmony_ci                           struct radv_descriptor_set_layout *layout, const uint32_t *variable_count,
614bf215546Sopenharmony_ci                           struct radv_descriptor_set **out_set)
615bf215546Sopenharmony_ci{
616bf215546Sopenharmony_ci   if (pool->entry_count == pool->max_entry_count)
617bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_POOL_MEMORY;
618bf215546Sopenharmony_ci
619bf215546Sopenharmony_ci   struct radv_descriptor_set *set;
620bf215546Sopenharmony_ci   uint32_t buffer_count = layout->buffer_count;
621bf215546Sopenharmony_ci   if (variable_count) {
622bf215546Sopenharmony_ci      unsigned stride =
623bf215546Sopenharmony_ci         radv_descriptor_type_buffer_count(layout->binding[layout->binding_count - 1].type);
624bf215546Sopenharmony_ci      buffer_count =
625bf215546Sopenharmony_ci         layout->binding[layout->binding_count - 1].buffer_offset + *variable_count * stride;
626bf215546Sopenharmony_ci   }
627bf215546Sopenharmony_ci   unsigned range_offset =
628bf215546Sopenharmony_ci      sizeof(struct radv_descriptor_set_header) + sizeof(struct radeon_winsys_bo *) * buffer_count;
629bf215546Sopenharmony_ci   const unsigned dynamic_offset_count = layout->dynamic_offset_count;
630bf215546Sopenharmony_ci   unsigned mem_size =
631bf215546Sopenharmony_ci      range_offset + sizeof(struct radv_descriptor_range) * dynamic_offset_count;
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci   if (pool->host_memory_base) {
634bf215546Sopenharmony_ci      if (pool->host_memory_end - pool->host_memory_ptr < mem_size)
635bf215546Sopenharmony_ci         return VK_ERROR_OUT_OF_POOL_MEMORY;
636bf215546Sopenharmony_ci
637bf215546Sopenharmony_ci      set = (struct radv_descriptor_set *)pool->host_memory_ptr;
638bf215546Sopenharmony_ci      pool->host_memory_ptr += mem_size;
639bf215546Sopenharmony_ci   } else {
640bf215546Sopenharmony_ci      set = vk_alloc2(&device->vk.alloc, NULL, mem_size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
641bf215546Sopenharmony_ci
642bf215546Sopenharmony_ci      if (!set)
643bf215546Sopenharmony_ci         return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
644bf215546Sopenharmony_ci   }
645bf215546Sopenharmony_ci
646bf215546Sopenharmony_ci   memset(set, 0, mem_size);
647bf215546Sopenharmony_ci
648bf215546Sopenharmony_ci   vk_object_base_init(&device->vk, &set->header.base, VK_OBJECT_TYPE_DESCRIPTOR_SET);
649bf215546Sopenharmony_ci
650bf215546Sopenharmony_ci   if (dynamic_offset_count) {
651bf215546Sopenharmony_ci      set->header.dynamic_descriptors =
652bf215546Sopenharmony_ci         (struct radv_descriptor_range *)((uint8_t *)set + range_offset);
653bf215546Sopenharmony_ci   }
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_ci   set->header.layout = layout;
656bf215546Sopenharmony_ci   set->header.buffer_count = buffer_count;
657bf215546Sopenharmony_ci   uint32_t layout_size = layout->size;
658bf215546Sopenharmony_ci   if (variable_count) {
659bf215546Sopenharmony_ci      uint32_t stride = layout->binding[layout->binding_count - 1].size;
660bf215546Sopenharmony_ci      if (layout->binding[layout->binding_count - 1].type ==
661bf215546Sopenharmony_ci          VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK)
662bf215546Sopenharmony_ci         stride = 1;
663bf215546Sopenharmony_ci
664bf215546Sopenharmony_ci      layout_size = layout->binding[layout->binding_count - 1].offset + *variable_count * stride;
665bf215546Sopenharmony_ci   }
666bf215546Sopenharmony_ci   layout_size = align_u32(layout_size, 32);
667bf215546Sopenharmony_ci   set->header.size = layout_size;
668bf215546Sopenharmony_ci
669bf215546Sopenharmony_ci   /* try to allocate linearly first, so that we don't spend
670bf215546Sopenharmony_ci    * time looking for gaps if the app only allocates &
671bf215546Sopenharmony_ci    * resets via the pool. */
672bf215546Sopenharmony_ci   if (pool->current_offset + layout_size <= pool->size) {
673bf215546Sopenharmony_ci      set->header.bo = pool->bo;
674bf215546Sopenharmony_ci      set->header.mapped_ptr = (uint32_t *)(pool->mapped_ptr + pool->current_offset);
675bf215546Sopenharmony_ci      set->header.va = pool->bo ? (radv_buffer_get_va(set->header.bo) + pool->current_offset) : 0;
676bf215546Sopenharmony_ci      if (!pool->host_memory_base) {
677bf215546Sopenharmony_ci         pool->entries[pool->entry_count].offset = pool->current_offset;
678bf215546Sopenharmony_ci         pool->entries[pool->entry_count].size = layout_size;
679bf215546Sopenharmony_ci      }
680bf215546Sopenharmony_ci      pool->entries[pool->entry_count].set = set;
681bf215546Sopenharmony_ci      pool->current_offset += layout_size;
682bf215546Sopenharmony_ci   } else if (!pool->host_memory_base) {
683bf215546Sopenharmony_ci      uint64_t offset = 0;
684bf215546Sopenharmony_ci      int index;
685bf215546Sopenharmony_ci
686bf215546Sopenharmony_ci      for (index = 0; index < pool->entry_count; ++index) {
687bf215546Sopenharmony_ci         if (pool->entries[index].offset - offset >= layout_size)
688bf215546Sopenharmony_ci            break;
689bf215546Sopenharmony_ci         offset = pool->entries[index].offset + pool->entries[index].size;
690bf215546Sopenharmony_ci      }
691bf215546Sopenharmony_ci
692bf215546Sopenharmony_ci      if (pool->size - offset < layout_size) {
693bf215546Sopenharmony_ci         vk_free2(&device->vk.alloc, NULL, set);
694bf215546Sopenharmony_ci         return VK_ERROR_OUT_OF_POOL_MEMORY;
695bf215546Sopenharmony_ci      }
696bf215546Sopenharmony_ci      set->header.bo = pool->bo;
697bf215546Sopenharmony_ci      set->header.mapped_ptr = (uint32_t *)(pool->mapped_ptr + offset);
698bf215546Sopenharmony_ci      set->header.va = pool->bo ? (radv_buffer_get_va(set->header.bo) + offset) : 0;
699bf215546Sopenharmony_ci      memmove(&pool->entries[index + 1], &pool->entries[index],
700bf215546Sopenharmony_ci              sizeof(pool->entries[0]) * (pool->entry_count - index));
701bf215546Sopenharmony_ci      pool->entries[index].offset = offset;
702bf215546Sopenharmony_ci      pool->entries[index].size = layout_size;
703bf215546Sopenharmony_ci      pool->entries[index].set = set;
704bf215546Sopenharmony_ci   } else
705bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_POOL_MEMORY;
706bf215546Sopenharmony_ci
707bf215546Sopenharmony_ci   if (layout->has_immutable_samplers) {
708bf215546Sopenharmony_ci      for (unsigned i = 0; i < layout->binding_count; ++i) {
709bf215546Sopenharmony_ci         if (!layout->binding[i].immutable_samplers_offset ||
710bf215546Sopenharmony_ci             layout->binding[i].immutable_samplers_equal)
711bf215546Sopenharmony_ci            continue;
712bf215546Sopenharmony_ci
713bf215546Sopenharmony_ci         unsigned offset = layout->binding[i].offset / 4;
714bf215546Sopenharmony_ci         if (layout->binding[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
715bf215546Sopenharmony_ci            offset += radv_combined_image_descriptor_sampler_offset(layout->binding + i) / 4;
716bf215546Sopenharmony_ci
717bf215546Sopenharmony_ci         const uint32_t *samplers =
718bf215546Sopenharmony_ci            (const uint32_t *)((const char *)layout + layout->binding[i].immutable_samplers_offset);
719bf215546Sopenharmony_ci         for (unsigned j = 0; j < layout->binding[i].array_size; ++j) {
720bf215546Sopenharmony_ci            memcpy(set->header.mapped_ptr + offset, samplers + 4 * j, 16);
721bf215546Sopenharmony_ci            offset += layout->binding[i].size / 4;
722bf215546Sopenharmony_ci         }
723bf215546Sopenharmony_ci      }
724bf215546Sopenharmony_ci   }
725bf215546Sopenharmony_ci
726bf215546Sopenharmony_ci   pool->entry_count++;
727bf215546Sopenharmony_ci   vk_descriptor_set_layout_ref(&layout->vk);
728bf215546Sopenharmony_ci   *out_set = set;
729bf215546Sopenharmony_ci   return VK_SUCCESS;
730bf215546Sopenharmony_ci}
731bf215546Sopenharmony_ci
732bf215546Sopenharmony_cistatic void
733bf215546Sopenharmony_ciradv_descriptor_set_destroy(struct radv_device *device, struct radv_descriptor_pool *pool,
734bf215546Sopenharmony_ci                            struct radv_descriptor_set *set, bool free_bo)
735bf215546Sopenharmony_ci{
736bf215546Sopenharmony_ci   vk_descriptor_set_layout_unref(&device->vk, &set->header.layout->vk);
737bf215546Sopenharmony_ci
738bf215546Sopenharmony_ci   if (pool->host_memory_base)
739bf215546Sopenharmony_ci      return;
740bf215546Sopenharmony_ci
741bf215546Sopenharmony_ci   if (free_bo && !pool->host_memory_base) {
742bf215546Sopenharmony_ci      for (int i = 0; i < pool->entry_count; ++i) {
743bf215546Sopenharmony_ci         if (pool->entries[i].set == set) {
744bf215546Sopenharmony_ci            memmove(&pool->entries[i], &pool->entries[i + 1],
745bf215546Sopenharmony_ci                    sizeof(pool->entries[i]) * (pool->entry_count - i - 1));
746bf215546Sopenharmony_ci            --pool->entry_count;
747bf215546Sopenharmony_ci            break;
748bf215546Sopenharmony_ci         }
749bf215546Sopenharmony_ci      }
750bf215546Sopenharmony_ci   }
751bf215546Sopenharmony_ci   vk_object_base_finish(&set->header.base);
752bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, NULL, set);
753bf215546Sopenharmony_ci}
754bf215546Sopenharmony_ci
755bf215546Sopenharmony_cistatic void
756bf215546Sopenharmony_ciradv_destroy_descriptor_pool(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
757bf215546Sopenharmony_ci                             struct radv_descriptor_pool *pool)
758bf215546Sopenharmony_ci{
759bf215546Sopenharmony_ci   for (int i = 0; i < pool->entry_count; ++i) {
760bf215546Sopenharmony_ci      radv_descriptor_set_destroy(device, pool, pool->entries[i].set, false);
761bf215546Sopenharmony_ci   }
762bf215546Sopenharmony_ci
763bf215546Sopenharmony_ci   if (pool->bo)
764bf215546Sopenharmony_ci      device->ws->buffer_destroy(device->ws, pool->bo);
765bf215546Sopenharmony_ci   if (pool->host_bo)
766bf215546Sopenharmony_ci      vk_free2(&device->vk.alloc, pAllocator, pool->host_bo);
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_ci   vk_object_base_finish(&pool->base);
769bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, pAllocator, pool);
770bf215546Sopenharmony_ci}
771bf215546Sopenharmony_ci
772bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
773bf215546Sopenharmony_ciradv_CreateDescriptorPool(VkDevice _device, const VkDescriptorPoolCreateInfo *pCreateInfo,
774bf215546Sopenharmony_ci                          const VkAllocationCallbacks *pAllocator,
775bf215546Sopenharmony_ci                          VkDescriptorPool *pDescriptorPool)
776bf215546Sopenharmony_ci{
777bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
778bf215546Sopenharmony_ci   struct radv_descriptor_pool *pool;
779bf215546Sopenharmony_ci   uint64_t size = sizeof(struct radv_descriptor_pool);
780bf215546Sopenharmony_ci   uint64_t bo_size = 0, bo_count = 0, range_count = 0;
781bf215546Sopenharmony_ci
782bf215546Sopenharmony_ci   const VkMutableDescriptorTypeCreateInfoVALVE *mutable_info =
783bf215546Sopenharmony_ci      vk_find_struct_const(pCreateInfo->pNext, MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE);
784bf215546Sopenharmony_ci
785bf215546Sopenharmony_ci   vk_foreach_struct_const(ext, pCreateInfo->pNext)
786bf215546Sopenharmony_ci   {
787bf215546Sopenharmony_ci      switch (ext->sType) {
788bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO: {
789bf215546Sopenharmony_ci         const VkDescriptorPoolInlineUniformBlockCreateInfo *info =
790bf215546Sopenharmony_ci            (const VkDescriptorPoolInlineUniformBlockCreateInfo *)ext;
791bf215546Sopenharmony_ci         /* the sizes are 4 aligned, and we need to align to at
792bf215546Sopenharmony_ci          * most 32, which needs at most 28 bytes extra per
793bf215546Sopenharmony_ci          * binding. */
794bf215546Sopenharmony_ci         bo_size += 28llu * info->maxInlineUniformBlockBindings;
795bf215546Sopenharmony_ci         break;
796bf215546Sopenharmony_ci      }
797bf215546Sopenharmony_ci      default:
798bf215546Sopenharmony_ci         break;
799bf215546Sopenharmony_ci      }
800bf215546Sopenharmony_ci   }
801bf215546Sopenharmony_ci
802bf215546Sopenharmony_ci   for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
803bf215546Sopenharmony_ci      bo_count += radv_descriptor_type_buffer_count(pCreateInfo->pPoolSizes[i].type) *
804bf215546Sopenharmony_ci         pCreateInfo->pPoolSizes[i].descriptorCount;
805bf215546Sopenharmony_ci
806bf215546Sopenharmony_ci      switch (pCreateInfo->pPoolSizes[i].type) {
807bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
808bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
809bf215546Sopenharmony_ci         range_count += pCreateInfo->pPoolSizes[i].descriptorCount;
810bf215546Sopenharmony_ci         break;
811bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
812bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
813bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
814bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
815bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLER:
816bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
817bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
818bf215546Sopenharmony_ci         /* 32 as we may need to align for images */
819bf215546Sopenharmony_ci         bo_size += 32 * pCreateInfo->pPoolSizes[i].descriptorCount;
820bf215546Sopenharmony_ci         break;
821bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
822bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
823bf215546Sopenharmony_ci         bo_size += 64 * pCreateInfo->pPoolSizes[i].descriptorCount;
824bf215546Sopenharmony_ci         break;
825bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_MUTABLE_VALVE:
826bf215546Sopenharmony_ci         /* Per spec, if a mutable descriptor type list is provided for the pool entry, we
827bf215546Sopenharmony_ci          * allocate enough memory to hold any subset of that list.
828bf215546Sopenharmony_ci          * If there is no mutable descriptor type list available,
829bf215546Sopenharmony_ci          * we must allocate enough for any supported mutable descriptor type, i.e. 64 bytes. */
830bf215546Sopenharmony_ci         if (mutable_info && i < mutable_info->mutableDescriptorTypeListCount) {
831bf215546Sopenharmony_ci            uint64_t mutable_size, mutable_alignment;
832bf215546Sopenharmony_ci            if (radv_mutable_descriptor_type_size_alignment(
833bf215546Sopenharmony_ci                   &mutable_info->pMutableDescriptorTypeLists[i], &mutable_size,
834bf215546Sopenharmony_ci                   &mutable_alignment)) {
835bf215546Sopenharmony_ci               /* 32 as we may need to align for images */
836bf215546Sopenharmony_ci               mutable_size = align(mutable_size, 32);
837bf215546Sopenharmony_ci               bo_size += mutable_size * pCreateInfo->pPoolSizes[i].descriptorCount;
838bf215546Sopenharmony_ci            }
839bf215546Sopenharmony_ci         } else {
840bf215546Sopenharmony_ci            bo_size += 64 * pCreateInfo->pPoolSizes[i].descriptorCount;
841bf215546Sopenharmony_ci         }
842bf215546Sopenharmony_ci         break;
843bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
844bf215546Sopenharmony_ci         bo_size += 96 * pCreateInfo->pPoolSizes[i].descriptorCount;
845bf215546Sopenharmony_ci         break;
846bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
847bf215546Sopenharmony_ci         bo_size += pCreateInfo->pPoolSizes[i].descriptorCount;
848bf215546Sopenharmony_ci         break;
849bf215546Sopenharmony_ci      default:
850bf215546Sopenharmony_ci         break;
851bf215546Sopenharmony_ci      }
852bf215546Sopenharmony_ci   }
853bf215546Sopenharmony_ci
854bf215546Sopenharmony_ci   uint64_t entries_size = sizeof(struct radv_descriptor_pool_entry) * pCreateInfo->maxSets;
855bf215546Sopenharmony_ci   size += entries_size;
856bf215546Sopenharmony_ci
857bf215546Sopenharmony_ci   if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) {
858bf215546Sopenharmony_ci      uint64_t host_size = pCreateInfo->maxSets * sizeof(struct radv_descriptor_set);
859bf215546Sopenharmony_ci      host_size += sizeof(struct radeon_winsys_bo *) * bo_count;
860bf215546Sopenharmony_ci      host_size += sizeof(struct radv_descriptor_range) * range_count;
861bf215546Sopenharmony_ci      size += host_size;
862bf215546Sopenharmony_ci   }
863bf215546Sopenharmony_ci
864bf215546Sopenharmony_ci   pool = vk_alloc2(&device->vk.alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
865bf215546Sopenharmony_ci   if (!pool)
866bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
867bf215546Sopenharmony_ci
868bf215546Sopenharmony_ci   memset(pool, 0, sizeof(*pool));
869bf215546Sopenharmony_ci
870bf215546Sopenharmony_ci   vk_object_base_init(&device->vk, &pool->base, VK_OBJECT_TYPE_DESCRIPTOR_POOL);
871bf215546Sopenharmony_ci
872bf215546Sopenharmony_ci   if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) {
873bf215546Sopenharmony_ci      pool->host_memory_base = (uint8_t *)pool + sizeof(struct radv_descriptor_pool) + entries_size;
874bf215546Sopenharmony_ci      pool->host_memory_ptr = pool->host_memory_base;
875bf215546Sopenharmony_ci      pool->host_memory_end = (uint8_t *)pool + size;
876bf215546Sopenharmony_ci   }
877bf215546Sopenharmony_ci
878bf215546Sopenharmony_ci   if (bo_size) {
879bf215546Sopenharmony_ci      if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE)) {
880bf215546Sopenharmony_ci         enum radeon_bo_flag flags = RADEON_FLAG_NO_INTERPROCESS_SHARING | RADEON_FLAG_READ_ONLY |
881bf215546Sopenharmony_ci                                     RADEON_FLAG_32BIT;
882bf215546Sopenharmony_ci
883bf215546Sopenharmony_ci         if (device->instance->zero_vram)
884bf215546Sopenharmony_ci            flags |= RADEON_FLAG_ZERO_VRAM;
885bf215546Sopenharmony_ci
886bf215546Sopenharmony_ci         VkResult result = device->ws->buffer_create(
887bf215546Sopenharmony_ci            device->ws, bo_size, 32, RADEON_DOMAIN_VRAM, flags, RADV_BO_PRIORITY_DESCRIPTOR, 0,
888bf215546Sopenharmony_ci            &pool->bo);
889bf215546Sopenharmony_ci         if (result != VK_SUCCESS) {
890bf215546Sopenharmony_ci            radv_destroy_descriptor_pool(device, pAllocator, pool);
891bf215546Sopenharmony_ci            return vk_error(device, result);
892bf215546Sopenharmony_ci         }
893bf215546Sopenharmony_ci         pool->mapped_ptr = (uint8_t *)device->ws->buffer_map(pool->bo);
894bf215546Sopenharmony_ci         if (!pool->mapped_ptr) {
895bf215546Sopenharmony_ci            radv_destroy_descriptor_pool(device, pAllocator, pool);
896bf215546Sopenharmony_ci            return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
897bf215546Sopenharmony_ci         }
898bf215546Sopenharmony_ci      } else {
899bf215546Sopenharmony_ci         pool->host_bo =
900bf215546Sopenharmony_ci            vk_alloc2(&device->vk.alloc, pAllocator, bo_size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
901bf215546Sopenharmony_ci         if (!pool->host_bo) {
902bf215546Sopenharmony_ci            radv_destroy_descriptor_pool(device, pAllocator, pool);
903bf215546Sopenharmony_ci            return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
904bf215546Sopenharmony_ci         }
905bf215546Sopenharmony_ci         pool->mapped_ptr = pool->host_bo;
906bf215546Sopenharmony_ci      }
907bf215546Sopenharmony_ci   }
908bf215546Sopenharmony_ci   pool->size = bo_size;
909bf215546Sopenharmony_ci   pool->max_entry_count = pCreateInfo->maxSets;
910bf215546Sopenharmony_ci
911bf215546Sopenharmony_ci   *pDescriptorPool = radv_descriptor_pool_to_handle(pool);
912bf215546Sopenharmony_ci   return VK_SUCCESS;
913bf215546Sopenharmony_ci}
914bf215546Sopenharmony_ci
915bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
916bf215546Sopenharmony_ciradv_DestroyDescriptorPool(VkDevice _device, VkDescriptorPool _pool,
917bf215546Sopenharmony_ci                           const VkAllocationCallbacks *pAllocator)
918bf215546Sopenharmony_ci{
919bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
920bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_descriptor_pool, pool, _pool);
921bf215546Sopenharmony_ci
922bf215546Sopenharmony_ci   if (!pool)
923bf215546Sopenharmony_ci      return;
924bf215546Sopenharmony_ci
925bf215546Sopenharmony_ci   radv_destroy_descriptor_pool(device, pAllocator, pool);
926bf215546Sopenharmony_ci}
927bf215546Sopenharmony_ci
928bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
929bf215546Sopenharmony_ciradv_ResetDescriptorPool(VkDevice _device, VkDescriptorPool descriptorPool,
930bf215546Sopenharmony_ci                         VkDescriptorPoolResetFlags flags)
931bf215546Sopenharmony_ci{
932bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
933bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_descriptor_pool, pool, descriptorPool);
934bf215546Sopenharmony_ci
935bf215546Sopenharmony_ci   for (int i = 0; i < pool->entry_count; ++i) {
936bf215546Sopenharmony_ci      radv_descriptor_set_destroy(device, pool, pool->entries[i].set, false);
937bf215546Sopenharmony_ci   }
938bf215546Sopenharmony_ci   pool->entry_count = 0;
939bf215546Sopenharmony_ci
940bf215546Sopenharmony_ci   pool->current_offset = 0;
941bf215546Sopenharmony_ci   pool->host_memory_ptr = pool->host_memory_base;
942bf215546Sopenharmony_ci
943bf215546Sopenharmony_ci   return VK_SUCCESS;
944bf215546Sopenharmony_ci}
945bf215546Sopenharmony_ci
946bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
947bf215546Sopenharmony_ciradv_AllocateDescriptorSets(VkDevice _device, const VkDescriptorSetAllocateInfo *pAllocateInfo,
948bf215546Sopenharmony_ci                            VkDescriptorSet *pDescriptorSets)
949bf215546Sopenharmony_ci{
950bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
951bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_descriptor_pool, pool, pAllocateInfo->descriptorPool);
952bf215546Sopenharmony_ci
953bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
954bf215546Sopenharmony_ci   uint32_t i;
955bf215546Sopenharmony_ci   struct radv_descriptor_set *set = NULL;
956bf215546Sopenharmony_ci
957bf215546Sopenharmony_ci   const VkDescriptorSetVariableDescriptorCountAllocateInfo *variable_counts = vk_find_struct_const(
958bf215546Sopenharmony_ci      pAllocateInfo->pNext, DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO);
959bf215546Sopenharmony_ci   const uint32_t zero = 0;
960bf215546Sopenharmony_ci
961bf215546Sopenharmony_ci   /* allocate a set of buffers for each shader to contain descriptors */
962bf215546Sopenharmony_ci   for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
963bf215546Sopenharmony_ci      RADV_FROM_HANDLE(radv_descriptor_set_layout, layout, pAllocateInfo->pSetLayouts[i]);
964bf215546Sopenharmony_ci
965bf215546Sopenharmony_ci      const uint32_t *variable_count = NULL;
966bf215546Sopenharmony_ci      if (layout->has_variable_descriptors && variable_counts) {
967bf215546Sopenharmony_ci         if (i < variable_counts->descriptorSetCount)
968bf215546Sopenharmony_ci            variable_count = variable_counts->pDescriptorCounts + i;
969bf215546Sopenharmony_ci         else
970bf215546Sopenharmony_ci            variable_count = &zero;
971bf215546Sopenharmony_ci      }
972bf215546Sopenharmony_ci
973bf215546Sopenharmony_ci      assert(!(layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
974bf215546Sopenharmony_ci
975bf215546Sopenharmony_ci      result = radv_descriptor_set_create(device, pool, layout, variable_count, &set);
976bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
977bf215546Sopenharmony_ci         break;
978bf215546Sopenharmony_ci
979bf215546Sopenharmony_ci      pDescriptorSets[i] = radv_descriptor_set_to_handle(set);
980bf215546Sopenharmony_ci   }
981bf215546Sopenharmony_ci
982bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
983bf215546Sopenharmony_ci      radv_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool, i, pDescriptorSets);
984bf215546Sopenharmony_ci      for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
985bf215546Sopenharmony_ci         pDescriptorSets[i] = VK_NULL_HANDLE;
986bf215546Sopenharmony_ci      }
987bf215546Sopenharmony_ci   }
988bf215546Sopenharmony_ci   return result;
989bf215546Sopenharmony_ci}
990bf215546Sopenharmony_ci
991bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
992bf215546Sopenharmony_ciradv_FreeDescriptorSets(VkDevice _device, VkDescriptorPool descriptorPool, uint32_t count,
993bf215546Sopenharmony_ci                        const VkDescriptorSet *pDescriptorSets)
994bf215546Sopenharmony_ci{
995bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
996bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_descriptor_pool, pool, descriptorPool);
997bf215546Sopenharmony_ci
998bf215546Sopenharmony_ci   for (uint32_t i = 0; i < count; i++) {
999bf215546Sopenharmony_ci      RADV_FROM_HANDLE(radv_descriptor_set, set, pDescriptorSets[i]);
1000bf215546Sopenharmony_ci
1001bf215546Sopenharmony_ci      if (set && !pool->host_memory_base)
1002bf215546Sopenharmony_ci         radv_descriptor_set_destroy(device, pool, set, true);
1003bf215546Sopenharmony_ci   }
1004bf215546Sopenharmony_ci   return VK_SUCCESS;
1005bf215546Sopenharmony_ci}
1006bf215546Sopenharmony_ci
1007bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1008bf215546Sopenharmony_ciwrite_texel_buffer_descriptor(struct radv_device *device, struct radv_cmd_buffer *cmd_buffer,
1009bf215546Sopenharmony_ci                              unsigned *dst, struct radeon_winsys_bo **buffer_list,
1010bf215546Sopenharmony_ci                              const VkBufferView _buffer_view)
1011bf215546Sopenharmony_ci{
1012bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_buffer_view, buffer_view, _buffer_view);
1013bf215546Sopenharmony_ci
1014bf215546Sopenharmony_ci   if (!buffer_view) {
1015bf215546Sopenharmony_ci      memset(dst, 0, 4 * 4);
1016bf215546Sopenharmony_ci      if (!cmd_buffer)
1017bf215546Sopenharmony_ci         *buffer_list = NULL;
1018bf215546Sopenharmony_ci      return;
1019bf215546Sopenharmony_ci   }
1020bf215546Sopenharmony_ci
1021bf215546Sopenharmony_ci   memcpy(dst, buffer_view->state, 4 * 4);
1022bf215546Sopenharmony_ci
1023bf215546Sopenharmony_ci   if (cmd_buffer)
1024bf215546Sopenharmony_ci      radv_cs_add_buffer(device->ws, cmd_buffer->cs, buffer_view->bo);
1025bf215546Sopenharmony_ci   else
1026bf215546Sopenharmony_ci      *buffer_list = buffer_view->bo;
1027bf215546Sopenharmony_ci}
1028bf215546Sopenharmony_ci
1029bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1030bf215546Sopenharmony_ciwrite_buffer_descriptor(struct radv_device *device, struct radv_cmd_buffer *cmd_buffer,
1031bf215546Sopenharmony_ci                        unsigned *dst, struct radeon_winsys_bo **buffer_list,
1032bf215546Sopenharmony_ci                        const VkDescriptorBufferInfo *buffer_info)
1033bf215546Sopenharmony_ci{
1034bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_buffer, buffer, buffer_info->buffer);
1035bf215546Sopenharmony_ci
1036bf215546Sopenharmony_ci   if (!buffer) {
1037bf215546Sopenharmony_ci      memset(dst, 0, 4 * 4);
1038bf215546Sopenharmony_ci      if (!cmd_buffer)
1039bf215546Sopenharmony_ci         *buffer_list = NULL;
1040bf215546Sopenharmony_ci      return;
1041bf215546Sopenharmony_ci   }
1042bf215546Sopenharmony_ci
1043bf215546Sopenharmony_ci   uint64_t va = radv_buffer_get_va(buffer->bo);
1044bf215546Sopenharmony_ci
1045bf215546Sopenharmony_ci   uint32_t range = vk_buffer_range(&buffer->vk, buffer_info->offset, buffer_info->range);
1046bf215546Sopenharmony_ci   assert(buffer->vk.size > 0 && range > 0);
1047bf215546Sopenharmony_ci
1048bf215546Sopenharmony_ci   /* robustBufferAccess is relaxed enough to allow this (in combination
1049bf215546Sopenharmony_ci    * with the alignment/size we return from vkGetBufferMemoryRequirements)
1050bf215546Sopenharmony_ci    * and this allows the shader compiler to create more efficient 8/16-bit
1051bf215546Sopenharmony_ci    * buffer accesses. */
1052bf215546Sopenharmony_ci   range = align(range, 4);
1053bf215546Sopenharmony_ci
1054bf215546Sopenharmony_ci   va += buffer_info->offset + buffer->offset;
1055bf215546Sopenharmony_ci
1056bf215546Sopenharmony_ci   uint32_t rsrc_word3 =
1057bf215546Sopenharmony_ci      S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) |
1058bf215546Sopenharmony_ci      S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W);
1059bf215546Sopenharmony_ci
1060bf215546Sopenharmony_ci   if (device->physical_device->rad_info.gfx_level >= GFX11) {
1061bf215546Sopenharmony_ci      rsrc_word3 |= S_008F0C_FORMAT(V_008F0C_GFX11_FORMAT_32_FLOAT) |
1062bf215546Sopenharmony_ci                    S_008F0C_OOB_SELECT(V_008F0C_OOB_SELECT_RAW);
1063bf215546Sopenharmony_ci   } else if (device->physical_device->rad_info.gfx_level >= GFX10) {
1064bf215546Sopenharmony_ci      rsrc_word3 |= S_008F0C_FORMAT(V_008F0C_GFX10_FORMAT_32_FLOAT) |
1065bf215546Sopenharmony_ci                    S_008F0C_OOB_SELECT(V_008F0C_OOB_SELECT_RAW) | S_008F0C_RESOURCE_LEVEL(1);
1066bf215546Sopenharmony_ci   } else {
1067bf215546Sopenharmony_ci      rsrc_word3 |= S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) |
1068bf215546Sopenharmony_ci                    S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32);
1069bf215546Sopenharmony_ci   }
1070bf215546Sopenharmony_ci
1071bf215546Sopenharmony_ci   dst[0] = va;
1072bf215546Sopenharmony_ci   dst[1] = S_008F04_BASE_ADDRESS_HI(va >> 32);
1073bf215546Sopenharmony_ci   dst[2] = range;
1074bf215546Sopenharmony_ci   dst[3] = rsrc_word3;
1075bf215546Sopenharmony_ci
1076bf215546Sopenharmony_ci   if (cmd_buffer)
1077bf215546Sopenharmony_ci      radv_cs_add_buffer(device->ws, cmd_buffer->cs, buffer->bo);
1078bf215546Sopenharmony_ci   else
1079bf215546Sopenharmony_ci      *buffer_list = buffer->bo;
1080bf215546Sopenharmony_ci}
1081bf215546Sopenharmony_ci
1082bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1083bf215546Sopenharmony_ciwrite_block_descriptor(struct radv_device *device, struct radv_cmd_buffer *cmd_buffer, void *dst,
1084bf215546Sopenharmony_ci                       const VkWriteDescriptorSet *writeset)
1085bf215546Sopenharmony_ci{
1086bf215546Sopenharmony_ci   const VkWriteDescriptorSetInlineUniformBlock *inline_ub =
1087bf215546Sopenharmony_ci      vk_find_struct_const(writeset->pNext, WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK);
1088bf215546Sopenharmony_ci
1089bf215546Sopenharmony_ci   memcpy(dst, inline_ub->pData, inline_ub->dataSize);
1090bf215546Sopenharmony_ci}
1091bf215546Sopenharmony_ci
1092bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1093bf215546Sopenharmony_ciwrite_dynamic_buffer_descriptor(struct radv_device *device, struct radv_descriptor_range *range,
1094bf215546Sopenharmony_ci                                struct radeon_winsys_bo **buffer_list,
1095bf215546Sopenharmony_ci                                const VkDescriptorBufferInfo *buffer_info)
1096bf215546Sopenharmony_ci{
1097bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_buffer, buffer, buffer_info->buffer);
1098bf215546Sopenharmony_ci   uint64_t va;
1099bf215546Sopenharmony_ci   unsigned size;
1100bf215546Sopenharmony_ci
1101bf215546Sopenharmony_ci   if (!buffer) {
1102bf215546Sopenharmony_ci      range->va = 0;
1103bf215546Sopenharmony_ci      *buffer_list = NULL;
1104bf215546Sopenharmony_ci      return;
1105bf215546Sopenharmony_ci   }
1106bf215546Sopenharmony_ci
1107bf215546Sopenharmony_ci   va = radv_buffer_get_va(buffer->bo);
1108bf215546Sopenharmony_ci
1109bf215546Sopenharmony_ci   size = vk_buffer_range(&buffer->vk, buffer_info->offset, buffer_info->range);
1110bf215546Sopenharmony_ci   assert(buffer->vk.size > 0 && size > 0);
1111bf215546Sopenharmony_ci
1112bf215546Sopenharmony_ci   /* robustBufferAccess is relaxed enough to allow this (in combination
1113bf215546Sopenharmony_ci    * with the alignment/size we return from vkGetBufferMemoryRequirements)
1114bf215546Sopenharmony_ci    * and this allows the shader compiler to create more efficient 8/16-bit
1115bf215546Sopenharmony_ci    * buffer accesses. */
1116bf215546Sopenharmony_ci   size = align(size, 4);
1117bf215546Sopenharmony_ci
1118bf215546Sopenharmony_ci   va += buffer_info->offset + buffer->offset;
1119bf215546Sopenharmony_ci   range->va = va;
1120bf215546Sopenharmony_ci   range->size = size;
1121bf215546Sopenharmony_ci
1122bf215546Sopenharmony_ci   *buffer_list = buffer->bo;
1123bf215546Sopenharmony_ci}
1124bf215546Sopenharmony_ci
1125bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1126bf215546Sopenharmony_ciwrite_image_descriptor(struct radv_device *device, struct radv_cmd_buffer *cmd_buffer,
1127bf215546Sopenharmony_ci                       unsigned size, unsigned *dst, struct radeon_winsys_bo **buffer_list,
1128bf215546Sopenharmony_ci                       VkDescriptorType descriptor_type, const VkDescriptorImageInfo *image_info)
1129bf215546Sopenharmony_ci{
1130bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_image_view, iview, image_info->imageView);
1131bf215546Sopenharmony_ci   union radv_descriptor *descriptor;
1132bf215546Sopenharmony_ci
1133bf215546Sopenharmony_ci   if (!iview) {
1134bf215546Sopenharmony_ci      memset(dst, 0, size);
1135bf215546Sopenharmony_ci      if (!cmd_buffer)
1136bf215546Sopenharmony_ci         *buffer_list = NULL;
1137bf215546Sopenharmony_ci      return;
1138bf215546Sopenharmony_ci   }
1139bf215546Sopenharmony_ci
1140bf215546Sopenharmony_ci   if (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
1141bf215546Sopenharmony_ci      descriptor = &iview->storage_descriptor;
1142bf215546Sopenharmony_ci   } else {
1143bf215546Sopenharmony_ci      descriptor = &iview->descriptor;
1144bf215546Sopenharmony_ci   }
1145bf215546Sopenharmony_ci   assert(size > 0);
1146bf215546Sopenharmony_ci
1147bf215546Sopenharmony_ci   memcpy(dst, descriptor, size);
1148bf215546Sopenharmony_ci
1149bf215546Sopenharmony_ci   const uint32_t max_bindings = sizeof(iview->image->bindings) /
1150bf215546Sopenharmony_ci                                 sizeof(iview->image->bindings[0]);
1151bf215546Sopenharmony_ci   for (uint32_t b = 0; b < max_bindings; b++) {
1152bf215546Sopenharmony_ci      if (cmd_buffer) {
1153bf215546Sopenharmony_ci         if (iview->image->bindings[b].bo)
1154bf215546Sopenharmony_ci            radv_cs_add_buffer(device->ws, cmd_buffer->cs, iview->image->bindings[b].bo);
1155bf215546Sopenharmony_ci      } else {
1156bf215546Sopenharmony_ci         *buffer_list = iview->image->bindings[b].bo;
1157bf215546Sopenharmony_ci         buffer_list++;
1158bf215546Sopenharmony_ci      }
1159bf215546Sopenharmony_ci   }
1160bf215546Sopenharmony_ci}
1161bf215546Sopenharmony_ci
1162bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1163bf215546Sopenharmony_ciwrite_combined_image_sampler_descriptor(struct radv_device *device,
1164bf215546Sopenharmony_ci                                        struct radv_cmd_buffer *cmd_buffer, unsigned sampler_offset,
1165bf215546Sopenharmony_ci                                        unsigned *dst, struct radeon_winsys_bo **buffer_list,
1166bf215546Sopenharmony_ci                                        VkDescriptorType descriptor_type,
1167bf215546Sopenharmony_ci                                        const VkDescriptorImageInfo *image_info, bool has_sampler)
1168bf215546Sopenharmony_ci{
1169bf215546Sopenharmony_ci   write_image_descriptor(device, cmd_buffer, sampler_offset, dst, buffer_list, descriptor_type,
1170bf215546Sopenharmony_ci                          image_info);
1171bf215546Sopenharmony_ci   /* copy over sampler state */
1172bf215546Sopenharmony_ci   if (has_sampler) {
1173bf215546Sopenharmony_ci      RADV_FROM_HANDLE(radv_sampler, sampler, image_info->sampler);
1174bf215546Sopenharmony_ci      memcpy(dst + sampler_offset / sizeof(*dst), sampler->state, 16);
1175bf215546Sopenharmony_ci   }
1176bf215546Sopenharmony_ci}
1177bf215546Sopenharmony_ci
1178bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1179bf215546Sopenharmony_ciwrite_sampler_descriptor(struct radv_device *device, unsigned *dst,
1180bf215546Sopenharmony_ci                         const VkDescriptorImageInfo *image_info)
1181bf215546Sopenharmony_ci{
1182bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_sampler, sampler, image_info->sampler);
1183bf215546Sopenharmony_ci
1184bf215546Sopenharmony_ci   memcpy(dst, sampler->state, 16);
1185bf215546Sopenharmony_ci}
1186bf215546Sopenharmony_ci
1187bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1188bf215546Sopenharmony_ciwrite_accel_struct(void *ptr, VkAccelerationStructureKHR _accel_struct)
1189bf215546Sopenharmony_ci{
1190bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_acceleration_structure, accel_struct, _accel_struct);
1191bf215546Sopenharmony_ci   uint64_t va = accel_struct ? radv_accel_struct_get_va(accel_struct) : 0;
1192bf215546Sopenharmony_ci   memcpy(ptr, &va, sizeof(va));
1193bf215546Sopenharmony_ci}
1194bf215546Sopenharmony_ci
1195bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1196bf215546Sopenharmony_ciradv_update_descriptor_sets_impl(struct radv_device *device, struct radv_cmd_buffer *cmd_buffer,
1197bf215546Sopenharmony_ci                                 VkDescriptorSet dstSetOverride, uint32_t descriptorWriteCount,
1198bf215546Sopenharmony_ci                                 const VkWriteDescriptorSet *pDescriptorWrites,
1199bf215546Sopenharmony_ci                                 uint32_t descriptorCopyCount,
1200bf215546Sopenharmony_ci                                 const VkCopyDescriptorSet *pDescriptorCopies)
1201bf215546Sopenharmony_ci{
1202bf215546Sopenharmony_ci   uint32_t i, j;
1203bf215546Sopenharmony_ci   for (i = 0; i < descriptorWriteCount; i++) {
1204bf215546Sopenharmony_ci      const VkWriteDescriptorSet *writeset = &pDescriptorWrites[i];
1205bf215546Sopenharmony_ci      RADV_FROM_HANDLE(radv_descriptor_set, set,
1206bf215546Sopenharmony_ci                       dstSetOverride ? dstSetOverride : writeset->dstSet);
1207bf215546Sopenharmony_ci      const struct radv_descriptor_set_binding_layout *binding_layout =
1208bf215546Sopenharmony_ci         set->header.layout->binding + writeset->dstBinding;
1209bf215546Sopenharmony_ci      uint32_t *ptr = set->header.mapped_ptr;
1210bf215546Sopenharmony_ci      struct radeon_winsys_bo **buffer_list = set->descriptors;
1211bf215546Sopenharmony_ci      /* Immutable samplers are not copied into push descriptors when they are
1212bf215546Sopenharmony_ci       * allocated, so if we are writing push descriptors we have to copy the
1213bf215546Sopenharmony_ci       * immutable samplers into them now.
1214bf215546Sopenharmony_ci       */
1215bf215546Sopenharmony_ci      const bool copy_immutable_samplers = cmd_buffer &&
1216bf215546Sopenharmony_ci                                           binding_layout->immutable_samplers_offset &&
1217bf215546Sopenharmony_ci                                           !binding_layout->immutable_samplers_equal;
1218bf215546Sopenharmony_ci      const uint32_t *samplers = radv_immutable_samplers(set->header.layout, binding_layout);
1219bf215546Sopenharmony_ci      const VkWriteDescriptorSetAccelerationStructureKHR *accel_structs = NULL;
1220bf215546Sopenharmony_ci
1221bf215546Sopenharmony_ci      ptr += binding_layout->offset / 4;
1222bf215546Sopenharmony_ci
1223bf215546Sopenharmony_ci      if (writeset->descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
1224bf215546Sopenharmony_ci         write_block_descriptor(device, cmd_buffer, (uint8_t *)ptr + writeset->dstArrayElement,
1225bf215546Sopenharmony_ci                                writeset);
1226bf215546Sopenharmony_ci         continue;
1227bf215546Sopenharmony_ci      } else if (writeset->descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) {
1228bf215546Sopenharmony_ci         accel_structs =
1229bf215546Sopenharmony_ci            vk_find_struct_const(writeset->pNext, WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR);
1230bf215546Sopenharmony_ci      }
1231bf215546Sopenharmony_ci
1232bf215546Sopenharmony_ci      ptr += binding_layout->size * writeset->dstArrayElement / 4;
1233bf215546Sopenharmony_ci      buffer_list += binding_layout->buffer_offset;
1234bf215546Sopenharmony_ci      buffer_list += writeset->dstArrayElement;
1235bf215546Sopenharmony_ci      for (j = 0; j < writeset->descriptorCount; ++j) {
1236bf215546Sopenharmony_ci         switch (writeset->descriptorType) {
1237bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1238bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
1239bf215546Sopenharmony_ci            unsigned idx = writeset->dstArrayElement + j;
1240bf215546Sopenharmony_ci            idx += binding_layout->dynamic_offset_offset;
1241bf215546Sopenharmony_ci            assert(!(set->header.layout->flags &
1242bf215546Sopenharmony_ci                     VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
1243bf215546Sopenharmony_ci            write_dynamic_buffer_descriptor(device, set->header.dynamic_descriptors + idx,
1244bf215546Sopenharmony_ci                                            buffer_list, writeset->pBufferInfo + j);
1245bf215546Sopenharmony_ci            break;
1246bf215546Sopenharmony_ci         }
1247bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1248bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1249bf215546Sopenharmony_ci            write_buffer_descriptor(device, cmd_buffer, ptr, buffer_list,
1250bf215546Sopenharmony_ci                                    writeset->pBufferInfo + j);
1251bf215546Sopenharmony_ci            break;
1252bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1253bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1254bf215546Sopenharmony_ci            write_texel_buffer_descriptor(device, cmd_buffer, ptr, buffer_list,
1255bf215546Sopenharmony_ci                                          writeset->pTexelBufferView[j]);
1256bf215546Sopenharmony_ci            break;
1257bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1258bf215546Sopenharmony_ci            write_image_descriptor(device, cmd_buffer, 32, ptr, buffer_list,
1259bf215546Sopenharmony_ci                                   writeset->descriptorType, writeset->pImageInfo + j);
1260bf215546Sopenharmony_ci            break;
1261bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1262bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1263bf215546Sopenharmony_ci            write_image_descriptor(device, cmd_buffer, 64, ptr, buffer_list,
1264bf215546Sopenharmony_ci                                   writeset->descriptorType, writeset->pImageInfo + j);
1265bf215546Sopenharmony_ci            break;
1266bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
1267bf215546Sopenharmony_ci            unsigned sampler_offset = radv_combined_image_descriptor_sampler_offset(binding_layout);
1268bf215546Sopenharmony_ci            write_combined_image_sampler_descriptor(
1269bf215546Sopenharmony_ci               device, cmd_buffer, sampler_offset, ptr, buffer_list, writeset->descriptorType,
1270bf215546Sopenharmony_ci               writeset->pImageInfo + j, !binding_layout->immutable_samplers_offset);
1271bf215546Sopenharmony_ci            if (copy_immutable_samplers) {
1272bf215546Sopenharmony_ci               const unsigned idx = writeset->dstArrayElement + j;
1273bf215546Sopenharmony_ci               memcpy((char *)ptr + sampler_offset, samplers + 4 * idx, 16);
1274bf215546Sopenharmony_ci            }
1275bf215546Sopenharmony_ci            break;
1276bf215546Sopenharmony_ci         }
1277bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_SAMPLER:
1278bf215546Sopenharmony_ci            if (!binding_layout->immutable_samplers_offset) {
1279bf215546Sopenharmony_ci               write_sampler_descriptor(device, ptr, writeset->pImageInfo + j);
1280bf215546Sopenharmony_ci            } else if (copy_immutable_samplers) {
1281bf215546Sopenharmony_ci               unsigned idx = writeset->dstArrayElement + j;
1282bf215546Sopenharmony_ci               memcpy(ptr, samplers + 4 * idx, 16);
1283bf215546Sopenharmony_ci            }
1284bf215546Sopenharmony_ci            break;
1285bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
1286bf215546Sopenharmony_ci            write_accel_struct(ptr, accel_structs->pAccelerationStructures[j]);
1287bf215546Sopenharmony_ci            break;
1288bf215546Sopenharmony_ci         default:
1289bf215546Sopenharmony_ci            break;
1290bf215546Sopenharmony_ci         }
1291bf215546Sopenharmony_ci         ptr += binding_layout->size / 4;
1292bf215546Sopenharmony_ci         ++buffer_list;
1293bf215546Sopenharmony_ci      }
1294bf215546Sopenharmony_ci   }
1295bf215546Sopenharmony_ci
1296bf215546Sopenharmony_ci   for (i = 0; i < descriptorCopyCount; i++) {
1297bf215546Sopenharmony_ci      const VkCopyDescriptorSet *copyset = &pDescriptorCopies[i];
1298bf215546Sopenharmony_ci      RADV_FROM_HANDLE(radv_descriptor_set, src_set, copyset->srcSet);
1299bf215546Sopenharmony_ci      RADV_FROM_HANDLE(radv_descriptor_set, dst_set, copyset->dstSet);
1300bf215546Sopenharmony_ci      const struct radv_descriptor_set_binding_layout *src_binding_layout =
1301bf215546Sopenharmony_ci         src_set->header.layout->binding + copyset->srcBinding;
1302bf215546Sopenharmony_ci      const struct radv_descriptor_set_binding_layout *dst_binding_layout =
1303bf215546Sopenharmony_ci         dst_set->header.layout->binding + copyset->dstBinding;
1304bf215546Sopenharmony_ci      uint32_t *src_ptr = src_set->header.mapped_ptr;
1305bf215546Sopenharmony_ci      uint32_t *dst_ptr = dst_set->header.mapped_ptr;
1306bf215546Sopenharmony_ci      struct radeon_winsys_bo **src_buffer_list = src_set->descriptors;
1307bf215546Sopenharmony_ci      struct radeon_winsys_bo **dst_buffer_list = dst_set->descriptors;
1308bf215546Sopenharmony_ci
1309bf215546Sopenharmony_ci      src_ptr += src_binding_layout->offset / 4;
1310bf215546Sopenharmony_ci      dst_ptr += dst_binding_layout->offset / 4;
1311bf215546Sopenharmony_ci
1312bf215546Sopenharmony_ci      if (src_binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
1313bf215546Sopenharmony_ci         src_ptr += copyset->srcArrayElement / 4;
1314bf215546Sopenharmony_ci         dst_ptr += copyset->dstArrayElement / 4;
1315bf215546Sopenharmony_ci
1316bf215546Sopenharmony_ci         memcpy(dst_ptr, src_ptr, copyset->descriptorCount);
1317bf215546Sopenharmony_ci         continue;
1318bf215546Sopenharmony_ci      }
1319bf215546Sopenharmony_ci
1320bf215546Sopenharmony_ci      src_ptr += src_binding_layout->size * copyset->srcArrayElement / 4;
1321bf215546Sopenharmony_ci      dst_ptr += dst_binding_layout->size * copyset->dstArrayElement / 4;
1322bf215546Sopenharmony_ci
1323bf215546Sopenharmony_ci      src_buffer_list += src_binding_layout->buffer_offset;
1324bf215546Sopenharmony_ci      src_buffer_list += copyset->srcArrayElement;
1325bf215546Sopenharmony_ci
1326bf215546Sopenharmony_ci      dst_buffer_list += dst_binding_layout->buffer_offset;
1327bf215546Sopenharmony_ci      dst_buffer_list += copyset->dstArrayElement;
1328bf215546Sopenharmony_ci
1329bf215546Sopenharmony_ci      /* In case of copies between mutable descriptor types
1330bf215546Sopenharmony_ci       * and non-mutable descriptor types. */
1331bf215546Sopenharmony_ci      size_t copy_size = MIN2(src_binding_layout->size, dst_binding_layout->size);
1332bf215546Sopenharmony_ci
1333bf215546Sopenharmony_ci      for (j = 0; j < copyset->descriptorCount; ++j) {
1334bf215546Sopenharmony_ci         switch (src_binding_layout->type) {
1335bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1336bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
1337bf215546Sopenharmony_ci            unsigned src_idx = copyset->srcArrayElement + j;
1338bf215546Sopenharmony_ci            unsigned dst_idx = copyset->dstArrayElement + j;
1339bf215546Sopenharmony_ci            struct radv_descriptor_range *src_range, *dst_range;
1340bf215546Sopenharmony_ci            src_idx += src_binding_layout->dynamic_offset_offset;
1341bf215546Sopenharmony_ci            dst_idx += dst_binding_layout->dynamic_offset_offset;
1342bf215546Sopenharmony_ci
1343bf215546Sopenharmony_ci            src_range = src_set->header.dynamic_descriptors + src_idx;
1344bf215546Sopenharmony_ci            dst_range = dst_set->header.dynamic_descriptors + dst_idx;
1345bf215546Sopenharmony_ci            *dst_range = *src_range;
1346bf215546Sopenharmony_ci            break;
1347bf215546Sopenharmony_ci         }
1348bf215546Sopenharmony_ci         default:
1349bf215546Sopenharmony_ci            memcpy(dst_ptr, src_ptr, copy_size);
1350bf215546Sopenharmony_ci         }
1351bf215546Sopenharmony_ci         src_ptr += src_binding_layout->size / 4;
1352bf215546Sopenharmony_ci         dst_ptr += dst_binding_layout->size / 4;
1353bf215546Sopenharmony_ci
1354bf215546Sopenharmony_ci         unsigned src_buffer_count = radv_descriptor_type_buffer_count(src_binding_layout->type);
1355bf215546Sopenharmony_ci         unsigned dst_buffer_count = radv_descriptor_type_buffer_count(dst_binding_layout->type);
1356bf215546Sopenharmony_ci         for (unsigned k = 0; k < dst_buffer_count; k++) {
1357bf215546Sopenharmony_ci            if (k < src_buffer_count)
1358bf215546Sopenharmony_ci               dst_buffer_list[k] = src_buffer_list[k];
1359bf215546Sopenharmony_ci            else
1360bf215546Sopenharmony_ci               dst_buffer_list[k] = NULL;
1361bf215546Sopenharmony_ci         }
1362bf215546Sopenharmony_ci
1363bf215546Sopenharmony_ci         dst_buffer_list += dst_buffer_count;
1364bf215546Sopenharmony_ci         src_buffer_list += src_buffer_count;
1365bf215546Sopenharmony_ci      }
1366bf215546Sopenharmony_ci   }
1367bf215546Sopenharmony_ci}
1368bf215546Sopenharmony_ci
1369bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1370bf215546Sopenharmony_ciradv_UpdateDescriptorSets(VkDevice _device, uint32_t descriptorWriteCount,
1371bf215546Sopenharmony_ci                          const VkWriteDescriptorSet *pDescriptorWrites,
1372bf215546Sopenharmony_ci                          uint32_t descriptorCopyCount,
1373bf215546Sopenharmony_ci                          const VkCopyDescriptorSet *pDescriptorCopies)
1374bf215546Sopenharmony_ci{
1375bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
1376bf215546Sopenharmony_ci
1377bf215546Sopenharmony_ci   radv_update_descriptor_sets_impl(device, NULL, VK_NULL_HANDLE, descriptorWriteCount,
1378bf215546Sopenharmony_ci                                    pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
1379bf215546Sopenharmony_ci}
1380bf215546Sopenharmony_ci
1381bf215546Sopenharmony_civoid
1382bf215546Sopenharmony_ciradv_cmd_update_descriptor_sets(struct radv_device *device, struct radv_cmd_buffer *cmd_buffer,
1383bf215546Sopenharmony_ci                                VkDescriptorSet dstSetOverride, uint32_t descriptorWriteCount,
1384bf215546Sopenharmony_ci                                const VkWriteDescriptorSet *pDescriptorWrites,
1385bf215546Sopenharmony_ci                                uint32_t descriptorCopyCount,
1386bf215546Sopenharmony_ci                                const VkCopyDescriptorSet *pDescriptorCopies)
1387bf215546Sopenharmony_ci{
1388bf215546Sopenharmony_ci   /* Assume cmd_buffer != NULL to optimize out cmd_buffer checks in generic code above. */
1389bf215546Sopenharmony_ci   assume(cmd_buffer != NULL);
1390bf215546Sopenharmony_ci   radv_update_descriptor_sets_impl(device, cmd_buffer, dstSetOverride, descriptorWriteCount,
1391bf215546Sopenharmony_ci                                    pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
1392bf215546Sopenharmony_ci}
1393bf215546Sopenharmony_ci
1394bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
1395bf215546Sopenharmony_ciradv_CreateDescriptorUpdateTemplate(VkDevice _device,
1396bf215546Sopenharmony_ci                                    const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
1397bf215546Sopenharmony_ci                                    const VkAllocationCallbacks *pAllocator,
1398bf215546Sopenharmony_ci                                    VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)
1399bf215546Sopenharmony_ci{
1400bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
1401bf215546Sopenharmony_ci   const uint32_t entry_count = pCreateInfo->descriptorUpdateEntryCount;
1402bf215546Sopenharmony_ci   const size_t size = sizeof(struct radv_descriptor_update_template) +
1403bf215546Sopenharmony_ci                       sizeof(struct radv_descriptor_update_template_entry) * entry_count;
1404bf215546Sopenharmony_ci   struct radv_descriptor_set_layout *set_layout = NULL;
1405bf215546Sopenharmony_ci   struct radv_descriptor_update_template *templ;
1406bf215546Sopenharmony_ci   uint32_t i;
1407bf215546Sopenharmony_ci
1408bf215546Sopenharmony_ci   templ = vk_alloc2(&device->vk.alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1409bf215546Sopenharmony_ci   if (!templ)
1410bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1411bf215546Sopenharmony_ci
1412bf215546Sopenharmony_ci   vk_object_base_init(&device->vk, &templ->base, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE);
1413bf215546Sopenharmony_ci
1414bf215546Sopenharmony_ci   templ->entry_count = entry_count;
1415bf215546Sopenharmony_ci
1416bf215546Sopenharmony_ci   if (pCreateInfo->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR) {
1417bf215546Sopenharmony_ci      RADV_FROM_HANDLE(radv_pipeline_layout, pipeline_layout, pCreateInfo->pipelineLayout);
1418bf215546Sopenharmony_ci
1419bf215546Sopenharmony_ci      /* descriptorSetLayout should be ignored for push descriptors
1420bf215546Sopenharmony_ci       * and instead it refers to pipelineLayout and set.
1421bf215546Sopenharmony_ci       */
1422bf215546Sopenharmony_ci      assert(pCreateInfo->set < MAX_SETS);
1423bf215546Sopenharmony_ci      set_layout = pipeline_layout->set[pCreateInfo->set].layout;
1424bf215546Sopenharmony_ci
1425bf215546Sopenharmony_ci      templ->bind_point = pCreateInfo->pipelineBindPoint;
1426bf215546Sopenharmony_ci   } else {
1427bf215546Sopenharmony_ci      assert(pCreateInfo->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET);
1428bf215546Sopenharmony_ci      set_layout = radv_descriptor_set_layout_from_handle(pCreateInfo->descriptorSetLayout);
1429bf215546Sopenharmony_ci   }
1430bf215546Sopenharmony_ci
1431bf215546Sopenharmony_ci   for (i = 0; i < entry_count; i++) {
1432bf215546Sopenharmony_ci      const VkDescriptorUpdateTemplateEntry *entry = &pCreateInfo->pDescriptorUpdateEntries[i];
1433bf215546Sopenharmony_ci      const struct radv_descriptor_set_binding_layout *binding_layout =
1434bf215546Sopenharmony_ci         set_layout->binding + entry->dstBinding;
1435bf215546Sopenharmony_ci      const uint32_t buffer_offset = binding_layout->buffer_offset + entry->dstArrayElement;
1436bf215546Sopenharmony_ci      const uint32_t *immutable_samplers = NULL;
1437bf215546Sopenharmony_ci      uint32_t dst_offset;
1438bf215546Sopenharmony_ci      uint32_t dst_stride;
1439bf215546Sopenharmony_ci
1440bf215546Sopenharmony_ci      /* dst_offset is an offset into dynamic_descriptors when the descriptor
1441bf215546Sopenharmony_ci         is dynamic, and an offset into mapped_ptr otherwise */
1442bf215546Sopenharmony_ci      switch (entry->descriptorType) {
1443bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1444bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1445bf215546Sopenharmony_ci         assert(pCreateInfo->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET);
1446bf215546Sopenharmony_ci         dst_offset = binding_layout->dynamic_offset_offset + entry->dstArrayElement;
1447bf215546Sopenharmony_ci         dst_stride = 0; /* Not used */
1448bf215546Sopenharmony_ci         break;
1449bf215546Sopenharmony_ci      default:
1450bf215546Sopenharmony_ci         switch (entry->descriptorType) {
1451bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1452bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_SAMPLER:
1453bf215546Sopenharmony_ci            /* Immutable samplers are copied into push descriptors when they are pushed */
1454bf215546Sopenharmony_ci            if (pCreateInfo->templateType ==
1455bf215546Sopenharmony_ci                   VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR &&
1456bf215546Sopenharmony_ci                binding_layout->immutable_samplers_offset &&
1457bf215546Sopenharmony_ci                !binding_layout->immutable_samplers_equal) {
1458bf215546Sopenharmony_ci               immutable_samplers =
1459bf215546Sopenharmony_ci                  radv_immutable_samplers(set_layout, binding_layout) + entry->dstArrayElement * 4;
1460bf215546Sopenharmony_ci            }
1461bf215546Sopenharmony_ci            break;
1462bf215546Sopenharmony_ci         default:
1463bf215546Sopenharmony_ci            break;
1464bf215546Sopenharmony_ci         }
1465bf215546Sopenharmony_ci         dst_offset = binding_layout->offset / 4;
1466bf215546Sopenharmony_ci         if (entry->descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK)
1467bf215546Sopenharmony_ci            dst_offset += entry->dstArrayElement / 4;
1468bf215546Sopenharmony_ci         else
1469bf215546Sopenharmony_ci            dst_offset += binding_layout->size * entry->dstArrayElement / 4;
1470bf215546Sopenharmony_ci
1471bf215546Sopenharmony_ci         dst_stride = binding_layout->size / 4;
1472bf215546Sopenharmony_ci         break;
1473bf215546Sopenharmony_ci      }
1474bf215546Sopenharmony_ci
1475bf215546Sopenharmony_ci      templ->entry[i] = (struct radv_descriptor_update_template_entry){
1476bf215546Sopenharmony_ci         .descriptor_type = entry->descriptorType,
1477bf215546Sopenharmony_ci         .descriptor_count = entry->descriptorCount,
1478bf215546Sopenharmony_ci         .src_offset = entry->offset,
1479bf215546Sopenharmony_ci         .src_stride = entry->stride,
1480bf215546Sopenharmony_ci         .dst_offset = dst_offset,
1481bf215546Sopenharmony_ci         .dst_stride = dst_stride,
1482bf215546Sopenharmony_ci         .buffer_offset = buffer_offset,
1483bf215546Sopenharmony_ci         .has_sampler = !binding_layout->immutable_samplers_offset,
1484bf215546Sopenharmony_ci         .sampler_offset = radv_combined_image_descriptor_sampler_offset(binding_layout),
1485bf215546Sopenharmony_ci         .immutable_samplers = immutable_samplers};
1486bf215546Sopenharmony_ci   }
1487bf215546Sopenharmony_ci
1488bf215546Sopenharmony_ci   *pDescriptorUpdateTemplate = radv_descriptor_update_template_to_handle(templ);
1489bf215546Sopenharmony_ci   return VK_SUCCESS;
1490bf215546Sopenharmony_ci}
1491bf215546Sopenharmony_ci
1492bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1493bf215546Sopenharmony_ciradv_DestroyDescriptorUpdateTemplate(VkDevice _device,
1494bf215546Sopenharmony_ci                                     VkDescriptorUpdateTemplate descriptorUpdateTemplate,
1495bf215546Sopenharmony_ci                                     const VkAllocationCallbacks *pAllocator)
1496bf215546Sopenharmony_ci{
1497bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
1498bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_descriptor_update_template, templ, descriptorUpdateTemplate);
1499bf215546Sopenharmony_ci
1500bf215546Sopenharmony_ci   if (!templ)
1501bf215546Sopenharmony_ci      return;
1502bf215546Sopenharmony_ci
1503bf215546Sopenharmony_ci   vk_object_base_finish(&templ->base);
1504bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, pAllocator, templ);
1505bf215546Sopenharmony_ci}
1506bf215546Sopenharmony_ci
1507bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1508bf215546Sopenharmony_ciradv_update_descriptor_set_with_template_impl(struct radv_device *device,
1509bf215546Sopenharmony_ci                                              struct radv_cmd_buffer *cmd_buffer,
1510bf215546Sopenharmony_ci                                              struct radv_descriptor_set *set,
1511bf215546Sopenharmony_ci                                              VkDescriptorUpdateTemplate descriptorUpdateTemplate,
1512bf215546Sopenharmony_ci                                              const void *pData)
1513bf215546Sopenharmony_ci{
1514bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_descriptor_update_template, templ, descriptorUpdateTemplate);
1515bf215546Sopenharmony_ci   uint32_t i;
1516bf215546Sopenharmony_ci
1517bf215546Sopenharmony_ci   for (i = 0; i < templ->entry_count; ++i) {
1518bf215546Sopenharmony_ci      struct radeon_winsys_bo **buffer_list = set->descriptors + templ->entry[i].buffer_offset;
1519bf215546Sopenharmony_ci      uint32_t *pDst = set->header.mapped_ptr + templ->entry[i].dst_offset;
1520bf215546Sopenharmony_ci      const uint8_t *pSrc = ((const uint8_t *)pData) + templ->entry[i].src_offset;
1521bf215546Sopenharmony_ci      uint32_t j;
1522bf215546Sopenharmony_ci
1523bf215546Sopenharmony_ci      if (templ->entry[i].descriptor_type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
1524bf215546Sopenharmony_ci         memcpy((uint8_t *)pDst, pSrc, templ->entry[i].descriptor_count);
1525bf215546Sopenharmony_ci         continue;
1526bf215546Sopenharmony_ci      }
1527bf215546Sopenharmony_ci
1528bf215546Sopenharmony_ci      for (j = 0; j < templ->entry[i].descriptor_count; ++j) {
1529bf215546Sopenharmony_ci         switch (templ->entry[i].descriptor_type) {
1530bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1531bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
1532bf215546Sopenharmony_ci            const unsigned idx = templ->entry[i].dst_offset + j;
1533bf215546Sopenharmony_ci            assert(!(set->header.layout->flags &
1534bf215546Sopenharmony_ci                     VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
1535bf215546Sopenharmony_ci            write_dynamic_buffer_descriptor(device, set->header.dynamic_descriptors + idx,
1536bf215546Sopenharmony_ci                                            buffer_list, (struct VkDescriptorBufferInfo *)pSrc);
1537bf215546Sopenharmony_ci            break;
1538bf215546Sopenharmony_ci         }
1539bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1540bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1541bf215546Sopenharmony_ci            write_buffer_descriptor(device, cmd_buffer, pDst, buffer_list,
1542bf215546Sopenharmony_ci                                    (struct VkDescriptorBufferInfo *)pSrc);
1543bf215546Sopenharmony_ci            break;
1544bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1545bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1546bf215546Sopenharmony_ci            write_texel_buffer_descriptor(device, cmd_buffer, pDst, buffer_list,
1547bf215546Sopenharmony_ci                                          *(VkBufferView *)pSrc);
1548bf215546Sopenharmony_ci            break;
1549bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1550bf215546Sopenharmony_ci            write_image_descriptor(device, cmd_buffer, 32, pDst, buffer_list,
1551bf215546Sopenharmony_ci                                   templ->entry[i].descriptor_type,
1552bf215546Sopenharmony_ci                                   (struct VkDescriptorImageInfo *)pSrc);
1553bf215546Sopenharmony_ci            break;
1554bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1555bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1556bf215546Sopenharmony_ci            write_image_descriptor(device, cmd_buffer, 64, pDst, buffer_list,
1557bf215546Sopenharmony_ci                                   templ->entry[i].descriptor_type,
1558bf215546Sopenharmony_ci                                   (struct VkDescriptorImageInfo *)pSrc);
1559bf215546Sopenharmony_ci            break;
1560bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1561bf215546Sopenharmony_ci            write_combined_image_sampler_descriptor(
1562bf215546Sopenharmony_ci               device, cmd_buffer, templ->entry[i].sampler_offset, pDst, buffer_list,
1563bf215546Sopenharmony_ci               templ->entry[i].descriptor_type, (struct VkDescriptorImageInfo *)pSrc,
1564bf215546Sopenharmony_ci               templ->entry[i].has_sampler);
1565bf215546Sopenharmony_ci            if (cmd_buffer && templ->entry[i].immutable_samplers) {
1566bf215546Sopenharmony_ci               memcpy((char *)pDst + templ->entry[i].sampler_offset,
1567bf215546Sopenharmony_ci                      templ->entry[i].immutable_samplers + 4 * j, 16);
1568bf215546Sopenharmony_ci            }
1569bf215546Sopenharmony_ci            break;
1570bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_SAMPLER:
1571bf215546Sopenharmony_ci            if (templ->entry[i].has_sampler)
1572bf215546Sopenharmony_ci               write_sampler_descriptor(device, pDst, (struct VkDescriptorImageInfo *)pSrc);
1573bf215546Sopenharmony_ci            else if (cmd_buffer && templ->entry[i].immutable_samplers)
1574bf215546Sopenharmony_ci               memcpy(pDst, templ->entry[i].immutable_samplers + 4 * j, 16);
1575bf215546Sopenharmony_ci            break;
1576bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
1577bf215546Sopenharmony_ci            write_accel_struct(pDst, *(const VkAccelerationStructureKHR *)pSrc);
1578bf215546Sopenharmony_ci            break;
1579bf215546Sopenharmony_ci         default:
1580bf215546Sopenharmony_ci            break;
1581bf215546Sopenharmony_ci         }
1582bf215546Sopenharmony_ci         pSrc += templ->entry[i].src_stride;
1583bf215546Sopenharmony_ci         pDst += templ->entry[i].dst_stride;
1584bf215546Sopenharmony_ci         ++buffer_list;
1585bf215546Sopenharmony_ci      }
1586bf215546Sopenharmony_ci   }
1587bf215546Sopenharmony_ci}
1588bf215546Sopenharmony_ci
1589bf215546Sopenharmony_civoid
1590bf215546Sopenharmony_ciradv_cmd_update_descriptor_set_with_template(struct radv_device *device,
1591bf215546Sopenharmony_ci                                             struct radv_cmd_buffer *cmd_buffer,
1592bf215546Sopenharmony_ci                                             struct radv_descriptor_set *set,
1593bf215546Sopenharmony_ci                                             VkDescriptorUpdateTemplate descriptorUpdateTemplate,
1594bf215546Sopenharmony_ci                                             const void *pData)
1595bf215546Sopenharmony_ci{
1596bf215546Sopenharmony_ci   /* Assume cmd_buffer != NULL to optimize out cmd_buffer checks in generic code above. */
1597bf215546Sopenharmony_ci   assume(cmd_buffer != NULL);
1598bf215546Sopenharmony_ci   radv_update_descriptor_set_with_template_impl(device, cmd_buffer, set, descriptorUpdateTemplate, pData);
1599bf215546Sopenharmony_ci}
1600bf215546Sopenharmony_ci
1601bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1602bf215546Sopenharmony_ciradv_UpdateDescriptorSetWithTemplate(VkDevice _device, VkDescriptorSet descriptorSet,
1603bf215546Sopenharmony_ci                                     VkDescriptorUpdateTemplate descriptorUpdateTemplate,
1604bf215546Sopenharmony_ci                                     const void *pData)
1605bf215546Sopenharmony_ci{
1606bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
1607bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_descriptor_set, set, descriptorSet);
1608bf215546Sopenharmony_ci
1609bf215546Sopenharmony_ci   radv_update_descriptor_set_with_template_impl(device, NULL, set, descriptorUpdateTemplate, pData);
1610bf215546Sopenharmony_ci}
1611bf215546Sopenharmony_ci
1612bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1613bf215546Sopenharmony_ciradv_GetDescriptorSetLayoutHostMappingInfoVALVE(
1614bf215546Sopenharmony_ci   VkDevice _device, const VkDescriptorSetBindingReferenceVALVE *pBindingReference,
1615bf215546Sopenharmony_ci   VkDescriptorSetLayoutHostMappingInfoVALVE *pHostMapping)
1616bf215546Sopenharmony_ci{
1617bf215546Sopenharmony_ci   struct radv_descriptor_set_layout *set_layout =
1618bf215546Sopenharmony_ci      radv_descriptor_set_layout_from_handle(pBindingReference->descriptorSetLayout);
1619bf215546Sopenharmony_ci
1620bf215546Sopenharmony_ci   const struct radv_descriptor_set_binding_layout *binding_layout =
1621bf215546Sopenharmony_ci      set_layout->binding + pBindingReference->binding;
1622bf215546Sopenharmony_ci
1623bf215546Sopenharmony_ci   pHostMapping->descriptorOffset = binding_layout->offset;
1624bf215546Sopenharmony_ci   pHostMapping->descriptorSize = binding_layout->size;
1625bf215546Sopenharmony_ci}
1626bf215546Sopenharmony_ci
1627bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1628bf215546Sopenharmony_ciradv_GetDescriptorSetHostMappingVALVE(VkDevice _device, VkDescriptorSet descriptorSet,
1629bf215546Sopenharmony_ci                                      void **ppData)
1630bf215546Sopenharmony_ci{
1631bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_descriptor_set, set, descriptorSet);
1632bf215546Sopenharmony_ci   *ppData = set->header.mapped_ptr;
1633bf215546Sopenharmony_ci}
1634bf215546Sopenharmony_ci
1635bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
1636bf215546Sopenharmony_ciradv_CreateSamplerYcbcrConversion(VkDevice _device,
1637bf215546Sopenharmony_ci                                  const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
1638bf215546Sopenharmony_ci                                  const VkAllocationCallbacks *pAllocator,
1639bf215546Sopenharmony_ci                                  VkSamplerYcbcrConversion *pYcbcrConversion)
1640bf215546Sopenharmony_ci{
1641bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
1642bf215546Sopenharmony_ci   struct radv_sampler_ycbcr_conversion *conversion = NULL;
1643bf215546Sopenharmony_ci
1644bf215546Sopenharmony_ci   conversion = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*conversion), 8,
1645bf215546Sopenharmony_ci                           VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1646bf215546Sopenharmony_ci
1647bf215546Sopenharmony_ci   if (conversion == NULL)
1648bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1649bf215546Sopenharmony_ci
1650bf215546Sopenharmony_ci   vk_object_base_init(&device->vk, &conversion->base, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION);
1651bf215546Sopenharmony_ci
1652bf215546Sopenharmony_ci   conversion->state.format = pCreateInfo->format;
1653bf215546Sopenharmony_ci   conversion->state.ycbcr_model = pCreateInfo->ycbcrModel;
1654bf215546Sopenharmony_ci   conversion->state.ycbcr_range = pCreateInfo->ycbcrRange;
1655bf215546Sopenharmony_ci   conversion->state.components = pCreateInfo->components;
1656bf215546Sopenharmony_ci   conversion->state.chroma_offsets[0] = pCreateInfo->xChromaOffset;
1657bf215546Sopenharmony_ci   conversion->state.chroma_offsets[1] = pCreateInfo->yChromaOffset;
1658bf215546Sopenharmony_ci   conversion->state.chroma_filter = pCreateInfo->chromaFilter;
1659bf215546Sopenharmony_ci
1660bf215546Sopenharmony_ci   *pYcbcrConversion = radv_sampler_ycbcr_conversion_to_handle(conversion);
1661bf215546Sopenharmony_ci   return VK_SUCCESS;
1662bf215546Sopenharmony_ci}
1663bf215546Sopenharmony_ci
1664bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1665bf215546Sopenharmony_ciradv_DestroySamplerYcbcrConversion(VkDevice _device, VkSamplerYcbcrConversion ycbcrConversion,
1666bf215546Sopenharmony_ci                                   const VkAllocationCallbacks *pAllocator)
1667bf215546Sopenharmony_ci{
1668bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
1669bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_sampler_ycbcr_conversion, ycbcr_conversion, ycbcrConversion);
1670bf215546Sopenharmony_ci
1671bf215546Sopenharmony_ci   if (!ycbcr_conversion)
1672bf215546Sopenharmony_ci      return;
1673bf215546Sopenharmony_ci
1674bf215546Sopenharmony_ci   vk_object_base_finish(&ycbcr_conversion->base);
1675bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, pAllocator, ycbcr_conversion);
1676bf215546Sopenharmony_ci}
1677