radv: Never try to create more than max_sets descriptor sets.
[mesa.git] / src / amd / vulkan / radv_descriptor_set.c
1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24 #include <assert.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include "util/mesa-sha1.h"
31 #include "radv_private.h"
32 #include "sid.h"
33
34 VkResult radv_CreateDescriptorSetLayout(
35 VkDevice _device,
36 const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
37 const VkAllocationCallbacks* pAllocator,
38 VkDescriptorSetLayout* pSetLayout)
39 {
40 RADV_FROM_HANDLE(radv_device, device, _device);
41 struct radv_descriptor_set_layout *set_layout;
42
43 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
44
45 uint32_t max_binding = 0;
46 uint32_t immutable_sampler_count = 0;
47 for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
48 max_binding = MAX2(max_binding, pCreateInfo->pBindings[j].binding);
49 if (pCreateInfo->pBindings[j].pImmutableSamplers)
50 immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount;
51 }
52
53 size_t size = sizeof(struct radv_descriptor_set_layout) +
54 (max_binding + 1) * sizeof(set_layout->binding[0]) +
55 immutable_sampler_count * sizeof(struct radv_sampler *);
56
57 set_layout = vk_alloc2(&device->alloc, pAllocator, size, 8,
58 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
59 if (!set_layout)
60 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
61
62 /* We just allocate all the samplers at the end of the struct */
63 struct radv_sampler **samplers =
64 (struct radv_sampler **)&set_layout->binding[max_binding + 1];
65
66 set_layout->binding_count = max_binding + 1;
67 set_layout->shader_stages = 0;
68 set_layout->size = 0;
69
70 memset(set_layout->binding, 0, size - sizeof(struct radv_descriptor_set_layout));
71
72 uint32_t buffer_count = 0;
73 uint32_t dynamic_offset_count = 0;
74
75 for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
76 const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[j];
77 uint32_t b = binding->binding;
78 uint32_t alignment;
79
80 switch (binding->descriptorType) {
81 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
82 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
83 set_layout->binding[b].dynamic_offset_count = 1;
84 set_layout->dynamic_shader_stages |= binding->stageFlags;
85 set_layout->binding[b].size = 0;
86 set_layout->binding[b].buffer_count = 1;
87 alignment = 1;
88 break;
89 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
90 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
91 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
92 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
93 set_layout->binding[b].size = 16;
94 set_layout->binding[b].buffer_count = 1;
95 alignment = 16;
96 break;
97 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
98 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
99 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
100 /* main descriptor + fmask descriptor */
101 set_layout->binding[b].size = 64;
102 set_layout->binding[b].buffer_count = 1;
103 alignment = 32;
104 break;
105 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
106 /* main descriptor + fmask descriptor + sampler */
107 set_layout->binding[b].size = 96;
108 set_layout->binding[b].buffer_count = 1;
109 alignment = 32;
110 break;
111 case VK_DESCRIPTOR_TYPE_SAMPLER:
112 set_layout->binding[b].size = 16;
113 alignment = 16;
114 break;
115 default:
116 unreachable("unknown descriptor type\n");
117 break;
118 }
119
120 set_layout->size = align(set_layout->size, alignment);
121 assert(binding->descriptorCount > 0);
122 set_layout->binding[b].type = binding->descriptorType;
123 set_layout->binding[b].array_size = binding->descriptorCount;
124 set_layout->binding[b].offset = set_layout->size;
125 set_layout->binding[b].buffer_offset = buffer_count;
126 set_layout->binding[b].dynamic_offset_offset = dynamic_offset_count;
127
128 set_layout->size += binding->descriptorCount * set_layout->binding[b].size;
129 buffer_count += binding->descriptorCount * set_layout->binding[b].buffer_count;
130 dynamic_offset_count += binding->descriptorCount *
131 set_layout->binding[b].dynamic_offset_count;
132
133
134 if (binding->pImmutableSamplers) {
135 set_layout->binding[b].immutable_samplers = samplers;
136 samplers += binding->descriptorCount;
137
138 for (uint32_t i = 0; i < binding->descriptorCount; i++)
139 set_layout->binding[b].immutable_samplers[i] =
140 radv_sampler_from_handle(binding->pImmutableSamplers[i]);
141 } else {
142 set_layout->binding[b].immutable_samplers = NULL;
143 }
144
145 set_layout->shader_stages |= binding->stageFlags;
146 }
147
148 set_layout->buffer_count = buffer_count;
149 set_layout->dynamic_offset_count = dynamic_offset_count;
150
151 *pSetLayout = radv_descriptor_set_layout_to_handle(set_layout);
152
153 return VK_SUCCESS;
154 }
155
156 void radv_DestroyDescriptorSetLayout(
157 VkDevice _device,
158 VkDescriptorSetLayout _set_layout,
159 const VkAllocationCallbacks* pAllocator)
160 {
161 RADV_FROM_HANDLE(radv_device, device, _device);
162 RADV_FROM_HANDLE(radv_descriptor_set_layout, set_layout, _set_layout);
163
164 if (!set_layout)
165 return;
166
167 vk_free2(&device->alloc, pAllocator, set_layout);
168 }
169
170 /*
171 * Pipeline layouts. These have nothing to do with the pipeline. They are
172 * just muttiple descriptor set layouts pasted together
173 */
174
175 VkResult radv_CreatePipelineLayout(
176 VkDevice _device,
177 const VkPipelineLayoutCreateInfo* pCreateInfo,
178 const VkAllocationCallbacks* pAllocator,
179 VkPipelineLayout* pPipelineLayout)
180 {
181 RADV_FROM_HANDLE(radv_device, device, _device);
182 struct radv_pipeline_layout *layout;
183 struct mesa_sha1 *ctx;
184
185 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
186
187 layout = vk_alloc2(&device->alloc, pAllocator, sizeof(*layout), 8,
188 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
189 if (layout == NULL)
190 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
191
192 layout->num_sets = pCreateInfo->setLayoutCount;
193
194 unsigned dynamic_offset_count = 0;
195
196
197 ctx = _mesa_sha1_init();
198 for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) {
199 RADV_FROM_HANDLE(radv_descriptor_set_layout, set_layout,
200 pCreateInfo->pSetLayouts[set]);
201 layout->set[set].layout = set_layout;
202
203 layout->set[set].dynamic_offset_start = dynamic_offset_count;
204 for (uint32_t b = 0; b < set_layout->binding_count; b++) {
205 dynamic_offset_count += set_layout->binding[b].array_size * set_layout->binding[b].dynamic_offset_count;
206 }
207 _mesa_sha1_update(ctx, set_layout->binding,
208 sizeof(set_layout->binding[0]) * set_layout->binding_count);
209 }
210
211 layout->dynamic_offset_count = dynamic_offset_count;
212 layout->push_constant_size = 0;
213 for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
214 const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i;
215 layout->push_constant_size = MAX2(layout->push_constant_size,
216 range->offset + range->size);
217 }
218
219 layout->push_constant_size = align(layout->push_constant_size, 16);
220 _mesa_sha1_update(ctx, &layout->push_constant_size,
221 sizeof(layout->push_constant_size));
222 _mesa_sha1_final(ctx, layout->sha1);
223 *pPipelineLayout = radv_pipeline_layout_to_handle(layout);
224
225 return VK_SUCCESS;
226 }
227
228 void radv_DestroyPipelineLayout(
229 VkDevice _device,
230 VkPipelineLayout _pipelineLayout,
231 const VkAllocationCallbacks* pAllocator)
232 {
233 RADV_FROM_HANDLE(radv_device, device, _device);
234 RADV_FROM_HANDLE(radv_pipeline_layout, pipeline_layout, _pipelineLayout);
235
236 if (!pipeline_layout)
237 return;
238 vk_free2(&device->alloc, pAllocator, pipeline_layout);
239 }
240
241 #define EMPTY 1
242
243 static VkResult
244 radv_descriptor_set_create(struct radv_device *device,
245 struct radv_descriptor_pool *pool,
246 struct radv_cmd_buffer *cmd_buffer,
247 const struct radv_descriptor_set_layout *layout,
248 struct radv_descriptor_set **out_set)
249 {
250 struct radv_descriptor_set *set;
251 unsigned mem_size = sizeof(struct radv_descriptor_set) +
252 sizeof(struct radeon_winsys_bo *) * layout->buffer_count;
253 set = vk_alloc2(&device->alloc, NULL, mem_size, 8,
254 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
255
256 if (!set)
257 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
258
259 memset(set, 0, mem_size);
260
261 if (layout->dynamic_offset_count) {
262 unsigned size = sizeof(struct radv_descriptor_range) *
263 layout->dynamic_offset_count;
264 set->dynamic_descriptors = vk_alloc2(&device->alloc, NULL, size, 8,
265 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
266
267 if (!set->dynamic_descriptors) {
268 vk_free2(&device->alloc, NULL, set);
269 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
270 }
271 }
272
273 set->layout = layout;
274 if (layout->size) {
275 uint32_t layout_size = align_u32(layout->size, 32);
276 set->size = layout->size;
277 if (!cmd_buffer) {
278 if (pool->current_offset + layout_size <= pool->size &&
279 pool->allocated_sets < pool->max_sets) {
280 set->bo = pool->bo;
281 set->mapped_ptr = (uint32_t*)(pool->mapped_ptr + pool->current_offset);
282 set->va = device->ws->buffer_get_va(set->bo) + pool->current_offset;
283 pool->current_offset += layout_size;
284 ++pool->allocated_sets;
285 } else {
286 int entry = pool->free_list, prev_entry = -1;
287 uint32_t offset;
288 while (entry >= 0) {
289 if (pool->free_nodes[entry].size >= layout_size) {
290 if (prev_entry >= 0)
291 pool->free_nodes[prev_entry].next = pool->free_nodes[entry].next;
292 else
293 pool->free_list = pool->free_nodes[entry].next;
294 break;
295 }
296 prev_entry = entry;
297 entry = pool->free_nodes[entry].next;
298 }
299
300 if (entry < 0) {
301 vk_free2(&device->alloc, NULL, set);
302 return vk_error(VK_ERROR_OUT_OF_POOL_MEMORY_KHR);
303 }
304 offset = pool->free_nodes[entry].offset;
305 pool->free_nodes[entry].next = pool->full_list;
306 pool->full_list = entry;
307
308 set->bo = pool->bo;
309 set->mapped_ptr = (uint32_t*)(pool->mapped_ptr + offset);
310 set->va = device->ws->buffer_get_va(set->bo) + offset;
311 }
312 } else {
313 unsigned bo_offset;
314 if (!radv_cmd_buffer_upload_alloc(cmd_buffer, set->size, 32,
315 &bo_offset,
316 (void**)&set->mapped_ptr)) {
317 vk_free2(&device->alloc, NULL, set->dynamic_descriptors);
318 vk_free2(&device->alloc, NULL, set);
319 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
320 }
321
322 set->va = device->ws->buffer_get_va(cmd_buffer->upload.upload_bo);
323 set->va += bo_offset;
324 }
325 }
326
327 if (pool)
328 list_add(&set->descriptor_pool, &pool->descriptor_sets);
329 else
330 list_inithead(&set->descriptor_pool);
331
332 for (unsigned i = 0; i < layout->binding_count; ++i) {
333 if (!layout->binding[i].immutable_samplers)
334 continue;
335
336 unsigned offset = layout->binding[i].offset / 4;
337 if (layout->binding[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
338 offset += 16;
339
340 for (unsigned j = 0; j < layout->binding[i].array_size; ++j) {
341 struct radv_sampler* sampler = layout->binding[i].immutable_samplers[j];
342
343 memcpy(set->mapped_ptr + offset, &sampler->state, 16);
344 offset += layout->binding[i].size / 4;
345 }
346
347 }
348 *out_set = set;
349 return VK_SUCCESS;
350 }
351
352 static void
353 radv_descriptor_set_destroy(struct radv_device *device,
354 struct radv_descriptor_pool *pool,
355 struct radv_descriptor_set *set,
356 bool free_bo)
357 {
358 if (free_bo && set->size) {
359 assert(pool->full_list >= 0);
360 int next = pool->free_nodes[pool->full_list].next;
361 pool->free_nodes[pool->full_list].next = pool->free_list;
362 pool->free_nodes[pool->full_list].offset = (uint8_t*)set->mapped_ptr - pool->mapped_ptr;
363 pool->free_nodes[pool->full_list].size = align_u32(set->size, 32);
364 pool->free_list = pool->full_list;
365 pool->full_list = next;
366 }
367 if (set->dynamic_descriptors)
368 vk_free2(&device->alloc, NULL, set->dynamic_descriptors);
369 if (!list_empty(&set->descriptor_pool))
370 list_del(&set->descriptor_pool);
371 vk_free2(&device->alloc, NULL, set);
372 }
373
374 VkResult
375 radv_temp_descriptor_set_create(struct radv_device *device,
376 struct radv_cmd_buffer *cmd_buffer,
377 VkDescriptorSetLayout _layout,
378 VkDescriptorSet *_set)
379 {
380 RADV_FROM_HANDLE(radv_descriptor_set_layout, layout, _layout);
381 struct radv_descriptor_set *set;
382 VkResult ret;
383
384 ret = radv_descriptor_set_create(device, NULL, cmd_buffer, layout, &set);
385 *_set = radv_descriptor_set_to_handle(set);
386 return ret;
387 }
388
389 void
390 radv_temp_descriptor_set_destroy(struct radv_device *device,
391 VkDescriptorSet _set)
392 {
393 RADV_FROM_HANDLE(radv_descriptor_set, set, _set);
394
395 radv_descriptor_set_destroy(device, NULL, set, false);
396 }
397
398 VkResult radv_CreateDescriptorPool(
399 VkDevice _device,
400 const VkDescriptorPoolCreateInfo* pCreateInfo,
401 const VkAllocationCallbacks* pAllocator,
402 VkDescriptorPool* pDescriptorPool)
403 {
404 RADV_FROM_HANDLE(radv_device, device, _device);
405 struct radv_descriptor_pool *pool;
406 unsigned max_sets = pCreateInfo->maxSets * 2;
407 int size = sizeof(struct radv_descriptor_pool) +
408 max_sets * sizeof(struct radv_descriptor_pool_free_node);
409 uint64_t bo_size = 0;
410 pool = vk_alloc2(&device->alloc, pAllocator, size, 8,
411 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
412 if (!pool)
413 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
414
415 memset(pool, 0, sizeof(*pool));
416
417 pool->free_list = -1;
418 pool->full_list = 0;
419 pool->free_nodes[max_sets - 1].next = -1;
420 pool->max_sets = max_sets;
421 pool->allocated_sets = 0;
422
423 for (int i = 0; i + 1 < max_sets; ++i)
424 pool->free_nodes[i].next = i + 1;
425
426 for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
427 switch(pCreateInfo->pPoolSizes[i].type) {
428 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
429 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
430 break;
431 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
432 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
433 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
434 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
435 case VK_DESCRIPTOR_TYPE_SAMPLER:
436 /* 32 as we may need to align for images */
437 bo_size += 32 * pCreateInfo->pPoolSizes[i].descriptorCount;
438 break;
439 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
440 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
441 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
442 bo_size += 64 * pCreateInfo->pPoolSizes[i].descriptorCount;
443 break;
444 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
445 bo_size += 96 * pCreateInfo->pPoolSizes[i].descriptorCount;
446 break;
447 default:
448 unreachable("unknown descriptor type\n");
449 break;
450 }
451 }
452
453 if (bo_size) {
454 pool->bo = device->ws->buffer_create(device->ws, bo_size,
455 32, RADEON_DOMAIN_VRAM, 0);
456 pool->mapped_ptr = (uint8_t*)device->ws->buffer_map(pool->bo);
457 }
458 pool->size = bo_size;
459
460 list_inithead(&pool->descriptor_sets);
461 *pDescriptorPool = radv_descriptor_pool_to_handle(pool);
462 return VK_SUCCESS;
463 }
464
465 void radv_DestroyDescriptorPool(
466 VkDevice _device,
467 VkDescriptorPool _pool,
468 const VkAllocationCallbacks* pAllocator)
469 {
470 RADV_FROM_HANDLE(radv_device, device, _device);
471 RADV_FROM_HANDLE(radv_descriptor_pool, pool, _pool);
472
473 if (!pool)
474 return;
475
476 list_for_each_entry_safe(struct radv_descriptor_set, set,
477 &pool->descriptor_sets, descriptor_pool) {
478 radv_descriptor_set_destroy(device, pool, set, false);
479 }
480
481 if (pool->bo)
482 device->ws->buffer_destroy(pool->bo);
483 vk_free2(&device->alloc, pAllocator, pool);
484 }
485
486 VkResult radv_ResetDescriptorPool(
487 VkDevice _device,
488 VkDescriptorPool descriptorPool,
489 VkDescriptorPoolResetFlags flags)
490 {
491 RADV_FROM_HANDLE(radv_device, device, _device);
492 RADV_FROM_HANDLE(radv_descriptor_pool, pool, descriptorPool);
493
494 list_for_each_entry_safe(struct radv_descriptor_set, set,
495 &pool->descriptor_sets, descriptor_pool) {
496 radv_descriptor_set_destroy(device, pool, set, false);
497 }
498
499 pool->allocated_sets = 0;
500 pool->current_offset = 0;
501 pool->free_list = -1;
502 pool->full_list = 0;
503 pool->free_nodes[pool->max_sets - 1].next = -1;
504
505 for (int i = 0; i + 1 < pool->max_sets; ++i)
506 pool->free_nodes[i].next = i + 1;
507
508 return VK_SUCCESS;
509 }
510
511 VkResult radv_AllocateDescriptorSets(
512 VkDevice _device,
513 const VkDescriptorSetAllocateInfo* pAllocateInfo,
514 VkDescriptorSet* pDescriptorSets)
515 {
516 RADV_FROM_HANDLE(radv_device, device, _device);
517 RADV_FROM_HANDLE(radv_descriptor_pool, pool, pAllocateInfo->descriptorPool);
518
519 VkResult result = VK_SUCCESS;
520 uint32_t i;
521 struct radv_descriptor_set *set;
522
523 /* allocate a set of buffers for each shader to contain descriptors */
524 for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
525 RADV_FROM_HANDLE(radv_descriptor_set_layout, layout,
526 pAllocateInfo->pSetLayouts[i]);
527
528 result = radv_descriptor_set_create(device, pool, NULL, layout, &set);
529 if (result != VK_SUCCESS)
530 break;
531
532 pDescriptorSets[i] = radv_descriptor_set_to_handle(set);
533 }
534
535 if (result != VK_SUCCESS)
536 radv_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool,
537 i, pDescriptorSets);
538 return result;
539 }
540
541 VkResult radv_FreeDescriptorSets(
542 VkDevice _device,
543 VkDescriptorPool descriptorPool,
544 uint32_t count,
545 const VkDescriptorSet* pDescriptorSets)
546 {
547 RADV_FROM_HANDLE(radv_device, device, _device);
548 RADV_FROM_HANDLE(radv_descriptor_pool, pool, descriptorPool);
549
550 for (uint32_t i = 0; i < count; i++) {
551 RADV_FROM_HANDLE(radv_descriptor_set, set, pDescriptorSets[i]);
552
553 if (set)
554 radv_descriptor_set_destroy(device, pool, set, true);
555 }
556 return VK_SUCCESS;
557 }
558
559 static void write_texel_buffer_descriptor(struct radv_device *device,
560 unsigned *dst,
561 struct radeon_winsys_bo **buffer_list,
562 const VkBufferView _buffer_view)
563 {
564 RADV_FROM_HANDLE(radv_buffer_view, buffer_view, _buffer_view);
565
566 memcpy(dst, buffer_view->state, 4 * 4);
567 *buffer_list = buffer_view->bo;
568 }
569
570 static void write_buffer_descriptor(struct radv_device *device,
571 unsigned *dst,
572 struct radeon_winsys_bo **buffer_list,
573 const VkDescriptorBufferInfo *buffer_info)
574 {
575 RADV_FROM_HANDLE(radv_buffer, buffer, buffer_info->buffer);
576 uint64_t va = device->ws->buffer_get_va(buffer->bo);
577 uint32_t range = buffer_info->range;
578
579 if (buffer_info->range == VK_WHOLE_SIZE)
580 range = buffer->size - buffer_info->offset;
581
582 va += buffer_info->offset + buffer->offset;
583 dst[0] = va;
584 dst[1] = S_008F04_BASE_ADDRESS_HI(va >> 32);
585 dst[2] = range;
586 dst[3] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) |
587 S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) |
588 S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) |
589 S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) |
590 S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) |
591 S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32);
592
593 *buffer_list = buffer->bo;
594 }
595
596 static void write_dynamic_buffer_descriptor(struct radv_device *device,
597 struct radv_descriptor_range *range,
598 struct radeon_winsys_bo **buffer_list,
599 const VkDescriptorBufferInfo *buffer_info)
600 {
601 RADV_FROM_HANDLE(radv_buffer, buffer, buffer_info->buffer);
602 uint64_t va = device->ws->buffer_get_va(buffer->bo);
603 unsigned size = buffer_info->range;
604
605 if (buffer_info->range == VK_WHOLE_SIZE)
606 size = buffer->size - buffer_info->offset;
607
608 va += buffer_info->offset + buffer->offset;
609 range->va = va;
610 range->size = size;
611
612 *buffer_list = buffer->bo;
613 }
614
615 static void
616 write_image_descriptor(struct radv_device *device,
617 unsigned *dst,
618 struct radeon_winsys_bo **buffer_list,
619 const VkDescriptorImageInfo *image_info)
620 {
621 RADV_FROM_HANDLE(radv_image_view, iview, image_info->imageView);
622 memcpy(dst, iview->descriptor, 8 * 4);
623 memcpy(dst + 8, iview->fmask_descriptor, 8 * 4);
624 *buffer_list = iview->bo;
625 }
626
627 static void
628 write_combined_image_sampler_descriptor(struct radv_device *device,
629 unsigned *dst,
630 struct radeon_winsys_bo **buffer_list,
631 const VkDescriptorImageInfo *image_info,
632 bool has_sampler)
633 {
634 RADV_FROM_HANDLE(radv_sampler, sampler, image_info->sampler);
635
636 write_image_descriptor(device, dst, buffer_list, image_info);
637 /* copy over sampler state */
638 if (has_sampler)
639 memcpy(dst + 16, sampler->state, 16);
640 }
641
642 static void
643 write_sampler_descriptor(struct radv_device *device,
644 unsigned *dst,
645 const VkDescriptorImageInfo *image_info)
646 {
647 RADV_FROM_HANDLE(radv_sampler, sampler, image_info->sampler);
648
649 memcpy(dst, sampler->state, 16);
650 }
651
652 void radv_UpdateDescriptorSets(
653 VkDevice _device,
654 uint32_t descriptorWriteCount,
655 const VkWriteDescriptorSet* pDescriptorWrites,
656 uint32_t descriptorCopyCount,
657 const VkCopyDescriptorSet* pDescriptorCopies)
658 {
659 RADV_FROM_HANDLE(radv_device, device, _device);
660 uint32_t i, j;
661 for (i = 0; i < descriptorWriteCount; i++) {
662 const VkWriteDescriptorSet *writeset = &pDescriptorWrites[i];
663 RADV_FROM_HANDLE(radv_descriptor_set, set, writeset->dstSet);
664 const struct radv_descriptor_set_binding_layout *binding_layout =
665 set->layout->binding + writeset->dstBinding;
666 uint32_t *ptr = set->mapped_ptr;
667 struct radeon_winsys_bo **buffer_list = set->descriptors;
668
669 ptr += binding_layout->offset / 4;
670 ptr += binding_layout->size * writeset->dstArrayElement / 4;
671 buffer_list += binding_layout->buffer_offset;
672 buffer_list += binding_layout->buffer_count * writeset->dstArrayElement;
673 for (j = 0; j < writeset->descriptorCount; ++j) {
674 switch(writeset->descriptorType) {
675 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
676 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
677 unsigned idx = writeset->dstArrayElement + j;
678 idx += binding_layout->dynamic_offset_offset;
679 write_dynamic_buffer_descriptor(device, set->dynamic_descriptors + idx,
680 buffer_list, writeset->pBufferInfo + j);
681 break;
682 }
683 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
684 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
685 write_buffer_descriptor(device, ptr, buffer_list,
686 writeset->pBufferInfo + j);
687 break;
688 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
689 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
690 write_texel_buffer_descriptor(device, ptr, buffer_list,
691 writeset->pTexelBufferView[j]);
692 break;
693 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
694 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
695 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
696 write_image_descriptor(device, ptr, buffer_list,
697 writeset->pImageInfo + j);
698 break;
699 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
700 write_combined_image_sampler_descriptor(device, ptr, buffer_list,
701 writeset->pImageInfo + j,
702 !binding_layout->immutable_samplers);
703 break;
704 case VK_DESCRIPTOR_TYPE_SAMPLER:
705 assert(!binding_layout->immutable_samplers);
706 write_sampler_descriptor(device, ptr,
707 writeset->pImageInfo + j);
708 break;
709 default:
710 unreachable("unimplemented descriptor type");
711 break;
712 }
713 ptr += binding_layout->size / 4;
714 buffer_list += binding_layout->buffer_count;
715 }
716
717 }
718 if (descriptorCopyCount)
719 radv_finishme("copy descriptors");
720 }