1 /*
2 * Copyright © 2021 Collabora Ltd.
3 *
4 * Derived from:
5 * Copyright © 2016 Red Hat.
6 * Copyright © 2016 Bas Nieuwenhuizen
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 */
27 #include "panvk_private.h"
28
29 #include <assert.h>
30 #include <fcntl.h>
31 #include <stdbool.h>
32 #include <string.h>
33 #include <unistd.h>
34
35 #include "util/mesa-sha1.h"
36 #include "vk_descriptors.h"
37 #include "vk_util.h"
38
39 /* FIXME: make sure those values are correct */
40 #define PANVK_MAX_TEXTURES (1 << 16)
41 #define PANVK_MAX_IMAGES (1 << 8)
42 #define PANVK_MAX_SAMPLERS (1 << 16)
43 #define PANVK_MAX_UBOS 255
44
45 void
panvk_GetDescriptorSetLayoutSupport(VkDevice _device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,VkDescriptorSetLayoutSupport * pSupport)46 panvk_GetDescriptorSetLayoutSupport(
47 VkDevice _device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
48 VkDescriptorSetLayoutSupport *pSupport)
49 {
50 VK_FROM_HANDLE(panvk_device, device, _device);
51
52 pSupport->supported = false;
53
54 VkDescriptorSetLayoutBinding *bindings;
55 VkResult result = vk_create_sorted_bindings(
56 pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings);
57 if (result != VK_SUCCESS) {
58 vk_error(device, result);
59 return;
60 }
61
62 unsigned sampler_idx = 0, tex_idx = 0, ubo_idx = 0;
63 unsigned img_idx = 0;
64 UNUSED unsigned dynoffset_idx = 0;
65
66 for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
67 const VkDescriptorSetLayoutBinding *binding = &bindings[i];
68
69 switch (binding->descriptorType) {
70 case VK_DESCRIPTOR_TYPE_SAMPLER:
71 sampler_idx += binding->descriptorCount;
72 break;
73 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
74 sampler_idx += binding->descriptorCount;
75 tex_idx += binding->descriptorCount;
76 break;
77 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
78 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
79 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
80 tex_idx += binding->descriptorCount;
81 break;
82 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
83 dynoffset_idx += binding->descriptorCount;
84 FALLTHROUGH;
85 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
86 ubo_idx += binding->descriptorCount;
87 break;
88 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
89 dynoffset_idx += binding->descriptorCount;
90 FALLTHROUGH;
91 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
92 break;
93 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
94 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
95 img_idx += binding->descriptorCount;
96 break;
97 default:
98 unreachable("Invalid descriptor type");
99 }
100 }
101
102 /* The maximum values apply to all sets attached to a pipeline since all
103 * sets descriptors have to be merged in a single array.
104 */
105 if (tex_idx > PANVK_MAX_TEXTURES / MAX_SETS ||
106 sampler_idx > PANVK_MAX_SAMPLERS / MAX_SETS ||
107 ubo_idx > PANVK_MAX_UBOS / MAX_SETS ||
108 img_idx > PANVK_MAX_IMAGES / MAX_SETS)
109 return;
110
111 pSupport->supported = true;
112 }
113
114 /*
115 * Pipeline layouts. These have nothing to do with the pipeline. They are
116 * just multiple descriptor set layouts pasted together.
117 */
118
119 VkResult
panvk_CreatePipelineLayout(VkDevice _device,const VkPipelineLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPipelineLayout * pPipelineLayout)120 panvk_CreatePipelineLayout(VkDevice _device,
121 const VkPipelineLayoutCreateInfo *pCreateInfo,
122 const VkAllocationCallbacks *pAllocator,
123 VkPipelineLayout *pPipelineLayout)
124 {
125 VK_FROM_HANDLE(panvk_device, device, _device);
126 struct panvk_pipeline_layout *layout;
127 struct mesa_sha1 ctx;
128
129 layout =
130 vk_pipeline_layout_zalloc(&device->vk, sizeof(*layout), pCreateInfo);
131 if (layout == NULL)
132 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
133
134 _mesa_sha1_init(&ctx);
135
136 unsigned sampler_idx = 0, tex_idx = 0, ubo_idx = 0;
137 unsigned dyn_ubo_idx = 0, dyn_ssbo_idx = 0, img_idx = 0;
138 for (unsigned set = 0; set < pCreateInfo->setLayoutCount; set++) {
139 const struct panvk_descriptor_set_layout *set_layout =
140 vk_to_panvk_descriptor_set_layout(layout->vk.set_layouts[set]);
141
142 layout->sets[set].sampler_offset = sampler_idx;
143 layout->sets[set].tex_offset = tex_idx;
144 layout->sets[set].ubo_offset = ubo_idx;
145 layout->sets[set].dyn_ubo_offset = dyn_ubo_idx;
146 layout->sets[set].dyn_ssbo_offset = dyn_ssbo_idx;
147 layout->sets[set].img_offset = img_idx;
148 sampler_idx += set_layout->num_samplers;
149 tex_idx += set_layout->num_textures;
150 ubo_idx += set_layout->num_ubos;
151 dyn_ubo_idx += set_layout->num_dyn_ubos;
152 dyn_ssbo_idx += set_layout->num_dyn_ssbos;
153 img_idx += set_layout->num_imgs;
154
155 for (unsigned b = 0; b < set_layout->binding_count; b++) {
156 const struct panvk_descriptor_set_binding_layout *binding_layout =
157 &set_layout->bindings[b];
158
159 if (binding_layout->immutable_samplers) {
160 for (unsigned s = 0; s < binding_layout->array_size; s++) {
161 struct panvk_sampler *sampler =
162 binding_layout->immutable_samplers[s];
163
164 _mesa_sha1_update(&ctx, &sampler->desc, sizeof(sampler->desc));
165 }
166 }
167 _mesa_sha1_update(&ctx, &binding_layout->type,
168 sizeof(binding_layout->type));
169 _mesa_sha1_update(&ctx, &binding_layout->array_size,
170 sizeof(binding_layout->array_size));
171 _mesa_sha1_update(&ctx, &binding_layout->shader_stages,
172 sizeof(binding_layout->shader_stages));
173 }
174 }
175
176 for (unsigned range = 0; range < pCreateInfo->pushConstantRangeCount;
177 range++) {
178 layout->push_constants.size =
179 MAX2(pCreateInfo->pPushConstantRanges[range].offset +
180 pCreateInfo->pPushConstantRanges[range].size,
181 layout->push_constants.size);
182 }
183
184 layout->num_samplers = sampler_idx;
185 layout->num_textures = tex_idx;
186 layout->num_ubos = ubo_idx;
187 layout->num_dyn_ubos = dyn_ubo_idx;
188 layout->num_dyn_ssbos = dyn_ssbo_idx;
189 layout->num_imgs = img_idx;
190
191 /* Some NIR texture operations don't require a sampler, but Bifrost/Midgard
192 * ones always expect one. Add a dummy sampler to deal with this limitation.
193 */
194 if (layout->num_textures) {
195 layout->num_samplers++;
196 for (unsigned set = 0; set < pCreateInfo->setLayoutCount; set++)
197 layout->sets[set].sampler_offset++;
198 }
199
200 _mesa_sha1_final(&ctx, layout->sha1);
201
202 *pPipelineLayout = panvk_pipeline_layout_to_handle(layout);
203 return VK_SUCCESS;
204 }
205
206 VkResult
panvk_CreateDescriptorPool(VkDevice _device,const VkDescriptorPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorPool * pDescriptorPool)207 panvk_CreateDescriptorPool(VkDevice _device,
208 const VkDescriptorPoolCreateInfo *pCreateInfo,
209 const VkAllocationCallbacks *pAllocator,
210 VkDescriptorPool *pDescriptorPool)
211 {
212 VK_FROM_HANDLE(panvk_device, device, _device);
213 struct panvk_descriptor_pool *pool;
214
215 pool = vk_object_zalloc(&device->vk, pAllocator,
216 sizeof(struct panvk_descriptor_pool),
217 VK_OBJECT_TYPE_DESCRIPTOR_POOL);
218 if (!pool)
219 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
220
221 pool->max.sets = pCreateInfo->maxSets;
222
223 for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
224 unsigned desc_count = pCreateInfo->pPoolSizes[i].descriptorCount;
225
226 switch (pCreateInfo->pPoolSizes[i].type) {
227 case VK_DESCRIPTOR_TYPE_SAMPLER:
228 pool->max.samplers += desc_count;
229 break;
230 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
231 pool->max.combined_image_samplers += desc_count;
232 break;
233 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
234 pool->max.sampled_images += desc_count;
235 break;
236 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
237 pool->max.storage_images += desc_count;
238 break;
239 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
240 pool->max.uniform_texel_bufs += desc_count;
241 break;
242 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
243 pool->max.storage_texel_bufs += desc_count;
244 break;
245 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
246 pool->max.input_attachments += desc_count;
247 break;
248 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
249 pool->max.uniform_bufs += desc_count;
250 break;
251 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
252 pool->max.storage_bufs += desc_count;
253 break;
254 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
255 pool->max.uniform_dyn_bufs += desc_count;
256 break;
257 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
258 pool->max.storage_dyn_bufs += desc_count;
259 break;
260 default:
261 unreachable("Invalid descriptor type");
262 }
263 }
264
265 *pDescriptorPool = panvk_descriptor_pool_to_handle(pool);
266 return VK_SUCCESS;
267 }
268
269 void
panvk_DestroyDescriptorPool(VkDevice _device,VkDescriptorPool _pool,const VkAllocationCallbacks * pAllocator)270 panvk_DestroyDescriptorPool(VkDevice _device, VkDescriptorPool _pool,
271 const VkAllocationCallbacks *pAllocator)
272 {
273 VK_FROM_HANDLE(panvk_device, device, _device);
274 VK_FROM_HANDLE(panvk_descriptor_pool, pool, _pool);
275
276 if (pool)
277 vk_object_free(&device->vk, pAllocator, pool);
278 }
279
280 VkResult
panvk_ResetDescriptorPool(VkDevice _device,VkDescriptorPool _pool,VkDescriptorPoolResetFlags flags)281 panvk_ResetDescriptorPool(VkDevice _device, VkDescriptorPool _pool,
282 VkDescriptorPoolResetFlags flags)
283 {
284 VK_FROM_HANDLE(panvk_descriptor_pool, pool, _pool);
285 memset(&pool->cur, 0, sizeof(pool->cur));
286 return VK_SUCCESS;
287 }
288
289 static void
panvk_descriptor_set_destroy(struct panvk_device * device,struct panvk_descriptor_pool * pool,struct panvk_descriptor_set * set)290 panvk_descriptor_set_destroy(struct panvk_device *device,
291 struct panvk_descriptor_pool *pool,
292 struct panvk_descriptor_set *set)
293 {
294 vk_free(&device->vk.alloc, set->textures);
295 vk_free(&device->vk.alloc, set->samplers);
296 vk_free(&device->vk.alloc, set->ubos);
297 vk_free(&device->vk.alloc, set->dyn_ubos);
298 vk_free(&device->vk.alloc, set->dyn_ssbos);
299 vk_free(&device->vk.alloc, set->img_fmts);
300 vk_free(&device->vk.alloc, set->img_attrib_bufs);
301 if (set->desc_bo)
302 panvk_priv_bo_destroy(set->desc_bo, NULL);
303 vk_object_free(&device->vk, NULL, set);
304 }
305
306 VkResult
panvk_FreeDescriptorSets(VkDevice _device,VkDescriptorPool descriptorPool,uint32_t count,const VkDescriptorSet * pDescriptorSets)307 panvk_FreeDescriptorSets(VkDevice _device, VkDescriptorPool descriptorPool,
308 uint32_t count, const VkDescriptorSet *pDescriptorSets)
309 {
310 VK_FROM_HANDLE(panvk_device, device, _device);
311 VK_FROM_HANDLE(panvk_descriptor_pool, pool, descriptorPool);
312
313 for (unsigned i = 0; i < count; i++) {
314 VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorSets[i]);
315
316 if (set)
317 panvk_descriptor_set_destroy(device, pool, set);
318 }
319 return VK_SUCCESS;
320 }
321
322 VkResult
panvk_CreateSamplerYcbcrConversion(VkDevice device,const VkSamplerYcbcrConversionCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSamplerYcbcrConversion * pYcbcrConversion)323 panvk_CreateSamplerYcbcrConversion(
324 VkDevice device, const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
325 const VkAllocationCallbacks *pAllocator,
326 VkSamplerYcbcrConversion *pYcbcrConversion)
327 {
328 panvk_stub();
329 return VK_SUCCESS;
330 }
331
332 void
panvk_DestroySamplerYcbcrConversion(VkDevice device,VkSamplerYcbcrConversion ycbcrConversion,const VkAllocationCallbacks * pAllocator)333 panvk_DestroySamplerYcbcrConversion(VkDevice device,
334 VkSamplerYcbcrConversion ycbcrConversion,
335 const VkAllocationCallbacks *pAllocator)
336 {
337 panvk_stub();
338 }
339