1/*
2 * Copyright 2022 Google LLC
3 * SPDX-License-Identifier: MIT
4 */
5
6#ifndef VN_FEEDBACK_H
7#define VN_FEEDBACK_H
8
9#include "vn_common.h"
10
11struct vn_feedback_pool {
12   /* single lock for simplicity though free_slots can use another */
13   simple_mtx_t mutex;
14
15   struct vn_device *device;
16   const VkAllocationCallbacks *alloc;
17
18   /* size in bytes of the feedback buffer */
19   uint32_t size;
20   /* size in bytes used of the active feedback buffer */
21   uint32_t used;
22
23   /* first entry is the active feedback buffer */
24   struct list_head feedback_buffers;
25
26   /* cache for returned feedback slots */
27   struct list_head free_slots;
28};
29
30enum vn_feedback_type {
31   VN_FEEDBACK_TYPE_FENCE,
32   VN_FEEDBACK_TYPE_TIMELINE_SEMAPHORE,
33   VN_FEEDBACK_TYPE_EVENT,
34};
35
36struct vn_feedback_slot {
37   enum vn_feedback_type type;
38   uint32_t offset;
39   VkBuffer buffer;
40
41   union {
42      void *data;
43      VkResult *status;
44      uint64_t *counter;
45   };
46
47   struct list_head head;
48};
49
50struct vn_feedback_cmd_pool {
51   simple_mtx_t mutex;
52
53   VkCommandPool pool;
54};
55
56VkResult
57vn_feedback_pool_init(struct vn_device *dev,
58                      struct vn_feedback_pool *pool,
59                      uint32_t size,
60                      const VkAllocationCallbacks *alloc);
61
62void
63vn_feedback_pool_fini(struct vn_feedback_pool *pool);
64
65struct vn_feedback_slot *
66vn_feedback_pool_alloc(struct vn_feedback_pool *pool,
67                       enum vn_feedback_type type);
68
69void
70vn_feedback_pool_free(struct vn_feedback_pool *pool,
71                      struct vn_feedback_slot *slot);
72
73static inline VkResult
74vn_feedback_get_status(struct vn_feedback_slot *slot)
75{
76   return *slot->status;
77}
78
79static inline void
80vn_feedback_reset_status(struct vn_feedback_slot *slot)
81{
82   assert(slot->type == VN_FEEDBACK_TYPE_FENCE ||
83          slot->type == VN_FEEDBACK_TYPE_EVENT);
84   *slot->status =
85      slot->type == VN_FEEDBACK_TYPE_FENCE ? VK_NOT_READY : VK_EVENT_RESET;
86}
87
88static inline void
89vn_feedback_set_status(struct vn_feedback_slot *slot, VkResult status)
90{
91   assert(slot->type == VN_FEEDBACK_TYPE_FENCE ||
92          slot->type == VN_FEEDBACK_TYPE_EVENT);
93   *slot->status = status;
94}
95
96static inline uint64_t
97vn_feedback_get_counter(struct vn_feedback_slot *slot)
98{
99   assert(slot->type == VN_FEEDBACK_TYPE_TIMELINE_SEMAPHORE);
100   return *slot->counter;
101}
102
103static inline void
104vn_feedback_set_counter(struct vn_feedback_slot *slot, uint64_t counter)
105{
106   assert(slot->type == VN_FEEDBACK_TYPE_TIMELINE_SEMAPHORE);
107   *slot->counter = counter;
108}
109
110void
111vn_feedback_event_cmd_record(VkCommandBuffer cmd_handle,
112                             VkEvent ev_handle,
113                             VkPipelineStageFlags stage_mask,
114                             VkResult status);
115
116VkResult
117vn_feedback_fence_cmd_alloc(VkDevice dev_handle,
118                            struct vn_feedback_cmd_pool *pool,
119                            struct vn_feedback_slot *slot,
120                            VkCommandBuffer *out_cmd_handle);
121
122void
123vn_feedback_fence_cmd_free(VkDevice dev_handle,
124                           struct vn_feedback_cmd_pool *pool,
125                           VkCommandBuffer cmd_handle);
126
127VkResult
128vn_feedback_cmd_pools_init(struct vn_device *dev);
129
130void
131vn_feedback_cmd_pools_fini(struct vn_device *dev);
132
133#endif /* VN_FEEDBACK_H */
134