• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2024 Collabora Ltd.
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include <assert.h>
7 #include <fcntl.h>
8 #include <stdbool.h>
9 #include <string.h>
10 #include <unistd.h>
11 
12 #include "util/mesa-blake3.h"
13 
14 #include "vk_descriptor_update_template.h"
15 #include "vk_descriptors.h"
16 #include "vk_format.h"
17 #include "vk_log.h"
18 #include "vk_util.h"
19 
20 #include "util/bitset.h"
21 
22 #include "genxml/gen_macros.h"
23 
24 #include "panvk_descriptor_set_layout.h"
25 #include "panvk_device.h"
26 #include "panvk_entrypoints.h"
27 #include "panvk_macros.h"
28 #include "panvk_sampler.h"
29 
30 #define PANVK_MAX_DESCS_PER_SET (1 << 24)
31 
32 static bool
binding_has_immutable_samplers(const VkDescriptorSetLayoutBinding * binding)33 binding_has_immutable_samplers(const VkDescriptorSetLayoutBinding *binding)
34 {
35    switch (binding->descriptorType) {
36    case VK_DESCRIPTOR_TYPE_SAMPLER:
37    case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
38       return binding->pImmutableSamplers != NULL;
39 
40    default:
41       return false;
42    }
43 }
44 
45 VkResult
panvk_per_arch(CreateDescriptorSetLayout)46 panvk_per_arch(CreateDescriptorSetLayout)(
47    VkDevice _device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
48    const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout)
49 {
50    VK_FROM_HANDLE(panvk_device, device, _device);
51    VkDescriptorSetLayoutBinding *bindings = NULL;
52    unsigned num_bindings = 0;
53    VkResult result;
54 
55    unsigned immutable_sampler_count = 0;
56    for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
57       const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[j];
58       num_bindings = MAX2(num_bindings, binding->binding + 1);
59 
60       /* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding:
61        *
62        *    "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or
63        *    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then
64        *    pImmutableSamplers can be used to initialize a set of immutable
65        *    samplers. [...]  If descriptorType is not one of these descriptor
66        *    types, then pImmutableSamplers is ignored.
67        *
68        * We need to be careful here and only parse pImmutableSamplers if we
69        * have one of the right descriptor types.
70        */
71       if (binding_has_immutable_samplers(binding))
72          immutable_sampler_count += binding->descriptorCount;
73    }
74 
75    if (pCreateInfo->bindingCount) {
76       result = vk_create_sorted_bindings(pCreateInfo->pBindings,
77                                          pCreateInfo->bindingCount, &bindings);
78       if (result != VK_SUCCESS)
79          return panvk_error(device, result);
80 
81       num_bindings = bindings[pCreateInfo->bindingCount - 1].binding + 1;
82    }
83 
84    VK_MULTIALLOC(ma);
85    VK_MULTIALLOC_DECL(&ma, struct panvk_descriptor_set_layout, layout, 1);
86    VK_MULTIALLOC_DECL(&ma, struct panvk_descriptor_set_binding_layout,
87                       binding_layouts, num_bindings);
88    VK_MULTIALLOC_DECL(&ma, struct mali_sampler_packed, samplers,
89                       immutable_sampler_count);
90 
91    if (!vk_descriptor_set_layout_multizalloc(&device->vk, &ma)) {
92       free(bindings);
93       return panvk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
94    }
95 
96    layout->flags = pCreateInfo->flags;
97    layout->bindings = binding_layouts;
98    layout->binding_count = num_bindings;
99 
100    const VkDescriptorSetLayoutBindingFlagsCreateInfo *binding_flags_info =
101       vk_find_struct_const(pCreateInfo->pNext,
102                            DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO);
103 
104    unsigned desc_idx = 0;
105    unsigned dyn_buf_idx = 0;
106    for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
107       const VkDescriptorSetLayoutBinding *binding = &bindings[i];
108       struct panvk_descriptor_set_binding_layout *binding_layout =
109          &layout->bindings[binding->binding];
110 
111       if (binding->descriptorCount == 0)
112          continue;
113 
114       binding_layout->type = binding->descriptorType;
115 
116       if (binding_flags_info && binding_flags_info->bindingCount > 0) {
117          assert(binding_flags_info->bindingCount == pCreateInfo->bindingCount);
118          binding_layout->flags = binding_flags_info->pBindingFlags[i];
119       }
120 
121       binding_layout->desc_count = binding->descriptorCount;
122 
123       if (binding_has_immutable_samplers(binding)) {
124          binding_layout->immutable_samplers = samplers;
125          samplers += binding->descriptorCount;
126          for (uint32_t j = 0; j < binding->descriptorCount; j++) {
127             VK_FROM_HANDLE(panvk_sampler, sampler,
128                            binding->pImmutableSamplers[j]);
129             binding_layout->immutable_samplers[j] = sampler->desc;
130          }
131       }
132 
133       if (vk_descriptor_type_is_dynamic(binding_layout->type)) {
134          binding_layout->desc_idx = dyn_buf_idx;
135          dyn_buf_idx += binding_layout->desc_count;
136       } else {
137          binding_layout->desc_idx = desc_idx;
138          desc_idx += panvk_get_desc_stride(binding_layout->type) *
139                      binding_layout->desc_count;
140       }
141    }
142 
143    layout->desc_count = desc_idx;
144    layout->dyn_buf_count = dyn_buf_idx;
145 
146    struct mesa_blake3 hash_ctx;
147    _mesa_blake3_init(&hash_ctx);
148 
149    _mesa_blake3_update(&hash_ctx, &layout->binding_count,
150                        sizeof(layout->binding_count));
151    _mesa_blake3_update(&hash_ctx, &layout->desc_count,
152                        sizeof(layout->desc_count));
153    _mesa_blake3_update(&hash_ctx, &layout->dyn_buf_count,
154                        sizeof(layout->dyn_buf_count));
155 
156    for (uint32_t b = 0; b < num_bindings; b++) {
157       _mesa_blake3_update(&hash_ctx, &layout->bindings[b].type,
158                           sizeof(layout->bindings[b].type));
159       _mesa_blake3_update(&hash_ctx, &layout->bindings[b].flags,
160                           sizeof(layout->bindings[b].flags));
161       _mesa_blake3_update(&hash_ctx, &layout->bindings[b].desc_count,
162                           sizeof(layout->bindings[b].desc_count));
163       /* Immutable samplers are ignored for now */
164    }
165 
166    _mesa_blake3_final(&hash_ctx, layout->vk.blake3);
167 
168    free(bindings);
169    *pSetLayout = panvk_descriptor_set_layout_to_handle(layout);
170 
171    return VK_SUCCESS;
172 }
173 
174 void
panvk_per_arch(GetDescriptorSetLayoutSupport)175 panvk_per_arch(GetDescriptorSetLayoutSupport)(
176    VkDevice _device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
177    VkDescriptorSetLayoutSupport *pSupport)
178 {
179    pSupport->supported = false;
180 
181    unsigned desc_count = 0, dyn_buf_count = 0;
182    for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
183       const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[i];
184       VkDescriptorType type = binding->descriptorType;
185 
186       if (vk_descriptor_type_is_dynamic(type))
187          dyn_buf_count += binding->descriptorCount;
188       else
189          desc_count += panvk_get_desc_stride(type) * binding->descriptorCount;
190    }
191 
192    if (desc_count > PANVK_MAX_DESCS_PER_SET ||
193        dyn_buf_count > MAX_DYNAMIC_BUFFERS)
194       return;
195 
196    pSupport->supported = true;
197 }
198