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 
11 struct 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 
30 enum vn_feedback_type {
31    VN_FEEDBACK_TYPE_FENCE,
32    VN_FEEDBACK_TYPE_TIMELINE_SEMAPHORE,
33    VN_FEEDBACK_TYPE_EVENT,
34 };
35 
36 struct 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 
50 struct vn_feedback_cmd_pool {
51    simple_mtx_t mutex;
52 
53    VkCommandPool pool;
54 };
55 
56 VkResult
57 vn_feedback_pool_init(struct vn_device *dev,
58                       struct vn_feedback_pool *pool,
59                       uint32_t size,
60                       const VkAllocationCallbacks *alloc);
61 
62 void
63 vn_feedback_pool_fini(struct vn_feedback_pool *pool);
64 
65 struct vn_feedback_slot *
66 vn_feedback_pool_alloc(struct vn_feedback_pool *pool,
67                        enum vn_feedback_type type);
68 
69 void
70 vn_feedback_pool_free(struct vn_feedback_pool *pool,
71                       struct vn_feedback_slot *slot);
72 
73 static inline VkResult
vn_feedback_get_status(struct vn_feedback_slot *slot)74 vn_feedback_get_status(struct vn_feedback_slot *slot)
75 {
76    return *slot->status;
77 }
78 
79 static inline void
vn_feedback_reset_status(struct vn_feedback_slot *slot)80 vn_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 
88 static inline void
vn_feedback_set_status(struct vn_feedback_slot *slot, VkResult status)89 vn_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 
96 static inline uint64_t
vn_feedback_get_counter(struct vn_feedback_slot *slot)97 vn_feedback_get_counter(struct vn_feedback_slot *slot)
98 {
99    assert(slot->type == VN_FEEDBACK_TYPE_TIMELINE_SEMAPHORE);
100    return *slot->counter;
101 }
102 
103 static inline void
vn_feedback_set_counter(struct vn_feedback_slot *slot, uint64_t counter)104 vn_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 
110 void
111 vn_feedback_event_cmd_record(VkCommandBuffer cmd_handle,
112                              VkEvent ev_handle,
113                              VkPipelineStageFlags stage_mask,
114                              VkResult status);
115 
116 VkResult
117 vn_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 
122 void
123 vn_feedback_fence_cmd_free(VkDevice dev_handle,
124                            struct vn_feedback_cmd_pool *pool,
125                            VkCommandBuffer cmd_handle);
126 
127 VkResult
128 vn_feedback_cmd_pools_init(struct vn_device *dev);
129 
130 void
131 vn_feedback_cmd_pools_fini(struct vn_device *dev);
132 
133 #endif /* VN_FEEDBACK_H */
134