~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/virtio/vulkan/vn_feedback.c

  • Committer: mmach
  • Date: 2023-11-02 21:31:35 UTC
  • Revision ID: netbit73@gmail.com-20231102213135-18d4tzh7tj0uz752
2023-11-02 22:11:57

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
#include "vn_command_buffer.h"
9
9
#include "vn_device.h"
10
10
#include "vn_physical_device.h"
 
11
#include "vn_query_pool.h"
11
12
#include "vn_queue.h"
12
13
 
13
 
/* coherent buffer with bound and mapped memory */
14
 
struct vn_feedback_buffer {
15
 
   VkBuffer buffer;
16
 
   VkDeviceMemory memory;
17
 
   void *data;
18
 
 
19
 
   struct list_head head;
20
 
};
21
 
 
22
14
static uint32_t
23
15
vn_get_memory_type_index(const VkPhysicalDeviceMemoryProperties *mem_props,
24
16
                         uint32_t mem_type_bits,
35
27
   return UINT32_MAX;
36
28
}
37
29
 
38
 
static VkResult
 
30
VkResult
39
31
vn_feedback_buffer_create(struct vn_device *dev,
40
32
                          uint32_t size,
41
33
                          const VkAllocationCallbacks *alloc,
128
120
   return result;
129
121
}
130
122
 
131
 
static void
 
123
void
132
124
vn_feedback_buffer_destroy(struct vn_device *dev,
133
125
                           struct vn_feedback_buffer *feedback_buf,
134
126
                           const VkAllocationCallbacks *alloc)
141
133
   vk_free(alloc, feedback_buf);
142
134
}
143
135
 
 
136
static inline uint32_t
 
137
vn_get_feedback_buffer_alignment(struct vn_feedback_buffer *feedback_buf)
 
138
{
 
139
   struct vn_buffer *buf = vn_buffer_from_handle(feedback_buf->buffer);
 
140
   return buf->requirements.memory.memoryRequirements.alignment;
 
141
}
 
142
 
144
143
static VkResult
145
144
vn_feedback_pool_grow_locked(struct vn_feedback_pool *pool)
146
145
{
154
153
      return result;
155
154
 
156
155
   pool->used = 0;
 
156
   pool->alignment = vn_get_feedback_buffer_alignment(feedback_buf);
157
157
 
158
158
   list_add(&feedback_buf->head, &pool->feedback_buffers);
159
159
 
172
172
   pool->alloc = alloc;
173
173
   pool->size = size;
174
174
   pool->used = size;
 
175
   pool->alignment = 1;
175
176
   list_inithead(&pool->feedback_buffers);
176
177
   list_inithead(&pool->free_slots);
177
178
 
198
199
                              uint32_t *out_offset)
199
200
{
200
201
   VN_TRACE_FUNC();
201
 
   const uint32_t aligned_size = align(size, 4);
202
202
 
203
 
   if (unlikely(aligned_size > pool->size - pool->used)) {
 
203
   /* Default values of pool->used and pool->alignment are used to trigger the
 
204
    * initial pool grow, and will be properly initialized after that.
 
205
    */
 
206
   if (unlikely(align(size, pool->alignment) > pool->size - pool->used)) {
204
207
      VkResult result = vn_feedback_pool_grow_locked(pool);
205
208
      if (result != VK_SUCCESS)
206
209
         return NULL;
207
210
 
208
 
      assert(aligned_size <= pool->size - pool->used);
 
211
      assert(align(size, pool->alignment) <= pool->size - pool->used);
209
212
   }
210
213
 
211
214
   *out_offset = pool->used;
212
 
   pool->used += aligned_size;
 
215
   pool->used += align(size, pool->alignment);
213
216
 
214
217
   return list_first_entry(&pool->feedback_buffers, struct vn_feedback_buffer,
215
218
                           head);
406
409
   vn_cmd_buffer_memory_barrier(cmd_handle, &dep_after, sync2);
407
410
}
408
411
 
 
412
static inline void
 
413
vn_feedback_cmd_record_flush_barrier(VkCommandBuffer cmd_handle,
 
414
                                     VkBuffer buffer,
 
415
                                     VkDeviceSize offset,
 
416
                                     VkDeviceSize size)
 
417
{
 
418
   const VkBufferMemoryBarrier buf_flush_barrier = {
 
419
      .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
 
420
      .pNext = NULL,
 
421
      .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
 
422
      .dstAccessMask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT,
 
423
      .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
 
424
      .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
 
425
      .buffer = buffer,
 
426
      .offset = offset,
 
427
      .size = size,
 
428
   };
 
429
   vn_CmdPipelineBarrier(cmd_handle, VK_PIPELINE_STAGE_TRANSFER_BIT,
 
430
                         VK_PIPELINE_STAGE_HOST_BIT, 0, 0, NULL, 1,
 
431
                         &buf_flush_barrier, 0, NULL);
 
432
}
 
433
 
409
434
static VkResult
410
435
vn_feedback_cmd_record(VkCommandBuffer cmd_handle,
411
436
                       struct vn_feedback_slot *dst_slot,
482
507
                       buf_size, VK_SUCCESS);
483
508
   }
484
509
 
485
 
   const VkBufferMemoryBarrier buf_barrier_after = {
486
 
      .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
487
 
      .pNext = NULL,
488
 
      .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
489
 
      .dstAccessMask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT,
490
 
      .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
491
 
      .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
492
 
      .buffer = dst_slot->buffer,
493
 
      .offset = dst_slot->offset,
494
 
      .size = buf_size,
495
 
   };
496
 
   vn_CmdPipelineBarrier(cmd_handle, VK_PIPELINE_STAGE_TRANSFER_BIT,
497
 
                         VK_PIPELINE_STAGE_HOST_BIT, 0, 0, NULL, 1,
498
 
                         &buf_barrier_after, 0, NULL);
 
510
   vn_feedback_cmd_record_flush_barrier(cmd_handle, dst_slot->buffer,
 
511
                                        dst_slot->offset, buf_size);
499
512
 
500
513
   return vn_EndCommandBuffer(cmd_handle);
501
514
}
502
515
 
 
516
void
 
517
vn_feedback_query_copy_cmd_record(VkCommandBuffer cmd_handle,
 
518
                                  VkQueryPool pool_handle,
 
519
                                  uint32_t query,
 
520
                                  uint32_t count)
 
521
{
 
522
   struct vn_query_pool *pool = vn_query_pool_from_handle(pool_handle);
 
523
 
 
524
   if (!pool->feedback)
 
525
      return;
 
526
 
 
527
   /* Results are always 64 bit and include availability bit (also 64 bit) */
 
528
   const size_t slot_size = (pool->result_array_size * 8) + 8;
 
529
   const size_t offset = slot_size * query;
 
530
 
 
531
   /* The first synchronization scope of vkCmdCopyQueryPoolResults does not
 
532
    * include the query feedback buffer. Insert a barrier to ensure ordering
 
533
    * against feedback buffer fill cmd injected in vkCmdResetQueryPool.
 
534
    */
 
535
   const VkBufferMemoryBarrier buf_barrier_before = {
 
536
      .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
 
537
      .pNext = NULL,
 
538
      .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
 
539
      .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
 
540
      .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
 
541
      .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
 
542
      .buffer = pool->feedback->buffer,
 
543
      .offset = offset,
 
544
      .size = slot_size * count,
 
545
   };
 
546
   vn_CmdPipelineBarrier(cmd_handle, VK_PIPELINE_STAGE_TRANSFER_BIT,
 
547
                         VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1,
 
548
                         &buf_barrier_before, 0, NULL);
 
549
 
 
550
   /* Per spec: "The first synchronization scope includes all commands
 
551
    * which reference the queries in queryPool indicated by query that
 
552
    * occur earlier in submission order. If flags does not include
 
553
    * VK_QUERY_RESULT_WAIT_BIT, vkCmdEndQueryIndexedEXT,
 
554
    * vkCmdWriteTimestamp2, vkCmdEndQuery, and vkCmdWriteTimestamp are
 
555
    * excluded from this scope."
 
556
    *
 
557
    * Set VK_QUERY_RESULT_WAIT_BIT to ensure ordering after
 
558
    * vkCmdEndQuery or vkCmdWriteTimestamp makes the query available.
 
559
    *
 
560
    * Set VK_QUERY_RESULT_64_BIT as we can convert it to 32 bit if app
 
561
    * requested that.
 
562
    */
 
563
   vn_CmdCopyQueryPoolResults(cmd_handle, pool_handle, query, count,
 
564
                              pool->feedback->buffer, offset, slot_size,
 
565
                              VK_QUERY_RESULT_WITH_AVAILABILITY_BIT |
 
566
                                 VK_QUERY_RESULT_64_BIT |
 
567
                                 VK_QUERY_RESULT_WAIT_BIT);
 
568
 
 
569
   /* Per spec: "vkCmdCopyQueryPoolResults is considered to be a transfer
 
570
    * operation, and its writes to buffer memory must be synchronized using
 
571
    * VK_PIPELINE_STAGE_TRANSFER_BIT and VK_ACCESS_TRANSFER_WRITE_BIT
 
572
    * before using the results."
 
573
    */
 
574
   vn_feedback_cmd_record_flush_barrier(cmd_handle, pool->feedback->buffer,
 
575
                                        offset, slot_size * count);
 
576
}
 
577
 
 
578
void
 
579
vn_feedback_query_reset_cmd_record(VkCommandBuffer cmd_handle,
 
580
                                   VkQueryPool pool_handle,
 
581
                                   uint32_t first_query,
 
582
                                   uint32_t count)
 
583
{
 
584
   struct vn_query_pool *pool = vn_query_pool_from_handle(pool_handle);
 
585
 
 
586
   if (!pool->feedback)
 
587
      return;
 
588
 
 
589
   /* Results are always 64 bit and include availability bit (also 64 bit) */
 
590
   const size_t slot_size = (pool->result_array_size * 8) + 8;
 
591
   const size_t offset = slot_size * first_query;
 
592
 
 
593
   const VkBufferMemoryBarrier buf_barrier_before = {
 
594
      .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
 
595
      .pNext = NULL,
 
596
      .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
 
597
      .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
 
598
      .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
 
599
      .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
 
600
      .buffer = pool->feedback->buffer,
 
601
      .offset = offset,
 
602
      .size = slot_size * count,
 
603
   };
 
604
 
 
605
   vn_CmdPipelineBarrier(cmd_handle, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
 
606
                         VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1,
 
607
                         &buf_barrier_before, 0, NULL);
 
608
 
 
609
   vn_CmdFillBuffer(cmd_handle, pool->feedback->buffer, offset,
 
610
                    slot_size * count, 0);
 
611
 
 
612
   vn_feedback_cmd_record_flush_barrier(cmd_handle, pool->feedback->buffer,
 
613
                                        offset, slot_size * count);
 
614
}
 
615
 
503
616
VkResult
504
617
vn_feedback_cmd_alloc(VkDevice dev_handle,
505
618
                      struct vn_feedback_cmd_pool *pool,