xref: /aosp_15_r20/external/mesa3d/src/asahi/vulkan/hk_descriptor_table.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2024 Valve Corporation
3  * Copyright 2024 Alyssa Rosenzweig
4  * Copyright 2022-2023 Collabora Ltd. and Red Hat Inc.
5  * SPDX-License-Identifier: MIT
6  */
7 #include "hk_descriptor_table.h"
8 
9 #include "hk_device.h"
10 #include "hk_physical_device.h"
11 
12 #include "asahi/lib/agx_bo.h"
13 #include <sys/mman.h>
14 
15 static VkResult
hk_descriptor_table_grow_locked(struct hk_device * dev,struct hk_descriptor_table * table,uint32_t new_alloc)16 hk_descriptor_table_grow_locked(struct hk_device *dev,
17                                 struct hk_descriptor_table *table,
18                                 uint32_t new_alloc)
19 {
20    struct agx_bo *new_bo;
21    uint32_t *new_free_table;
22 
23    assert(new_alloc > table->alloc && new_alloc <= table->max_alloc);
24 
25    const uint32_t new_bo_size = new_alloc * table->desc_size;
26    new_bo = agx_bo_create(&dev->dev, new_bo_size, 0, 0, "Descriptor table");
27 
28    if (new_bo == NULL) {
29       return vk_errorf(dev, VK_ERROR_OUT_OF_DEVICE_MEMORY,
30                        "Failed to allocate the descriptor table");
31    }
32 
33    void *new_map = new_bo->map;
34 
35    assert(table->bo == NULL && "not yet implemented sparse binding");
36    table->bo = new_bo;
37    table->map = new_map;
38 
39    const size_t new_free_table_size = new_alloc * sizeof(uint32_t);
40    new_free_table =
41       vk_realloc(&dev->vk.alloc, table->free_table, new_free_table_size, 4,
42                  VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
43    if (new_free_table == NULL) {
44       return vk_errorf(dev, VK_ERROR_OUT_OF_HOST_MEMORY,
45                        "Failed to allocate image descriptor free table");
46    }
47    table->free_table = new_free_table;
48 
49    table->alloc = new_alloc;
50 
51    return VK_SUCCESS;
52 }
53 
54 VkResult
hk_descriptor_table_init(struct hk_device * dev,struct hk_descriptor_table * table,uint32_t descriptor_size,uint32_t min_descriptor_count,uint32_t max_descriptor_count)55 hk_descriptor_table_init(struct hk_device *dev,
56                          struct hk_descriptor_table *table,
57                          uint32_t descriptor_size,
58                          uint32_t min_descriptor_count,
59                          uint32_t max_descriptor_count)
60 {
61    memset(table, 0, sizeof(*table));
62    VkResult result;
63 
64    simple_mtx_init(&table->mutex, mtx_plain);
65 
66    assert(util_is_power_of_two_nonzero(min_descriptor_count));
67    assert(util_is_power_of_two_nonzero(max_descriptor_count));
68 
69    /* TODO: sparse binding for stable gpu va */
70    min_descriptor_count = max_descriptor_count;
71 
72    table->desc_size = descriptor_size;
73    table->alloc = 0;
74    table->max_alloc = max_descriptor_count;
75    table->next_desc = 0;
76    table->free_count = 0;
77 
78    result = hk_descriptor_table_grow_locked(dev, table, min_descriptor_count);
79    if (result != VK_SUCCESS) {
80       hk_descriptor_table_finish(dev, table);
81       return result;
82    }
83 
84    return VK_SUCCESS;
85 }
86 
87 void
hk_descriptor_table_finish(struct hk_device * dev,struct hk_descriptor_table * table)88 hk_descriptor_table_finish(struct hk_device *dev,
89                            struct hk_descriptor_table *table)
90 {
91    agx_bo_unreference(&dev->dev, table->bo);
92    vk_free(&dev->vk.alloc, table->free_table);
93    simple_mtx_destroy(&table->mutex);
94 }
95 
96 #define HK_IMAGE_DESC_INVALID
97 
98 static VkResult
hk_descriptor_table_alloc_locked(struct hk_device * dev,struct hk_descriptor_table * table,uint32_t * index_out)99 hk_descriptor_table_alloc_locked(struct hk_device *dev,
100                                  struct hk_descriptor_table *table,
101                                  uint32_t *index_out)
102 {
103    VkResult result;
104 
105    if (table->free_count > 0) {
106       *index_out = table->free_table[--table->free_count];
107       return VK_SUCCESS;
108    }
109 
110    if (table->next_desc < table->alloc) {
111       *index_out = table->next_desc++;
112       return VK_SUCCESS;
113    }
114 
115    if (table->next_desc >= table->max_alloc) {
116       return vk_errorf(dev, VK_ERROR_OUT_OF_HOST_MEMORY,
117                        "Descriptor table not large enough");
118    }
119 
120    result = hk_descriptor_table_grow_locked(dev, table, table->alloc * 2);
121    if (result != VK_SUCCESS)
122       return result;
123 
124    assert(table->next_desc < table->alloc);
125    *index_out = table->next_desc++;
126 
127    return VK_SUCCESS;
128 }
129 
130 static VkResult
hk_descriptor_table_add_locked(struct hk_device * dev,struct hk_descriptor_table * table,const void * desc_data,size_t desc_size,uint32_t * index_out)131 hk_descriptor_table_add_locked(struct hk_device *dev,
132                                struct hk_descriptor_table *table,
133                                const void *desc_data, size_t desc_size,
134                                uint32_t *index_out)
135 {
136    VkResult result = hk_descriptor_table_alloc_locked(dev, table, index_out);
137    if (result != VK_SUCCESS)
138       return result;
139 
140    void *map = (char *)table->map + (*index_out * table->desc_size);
141 
142    assert(desc_size == table->desc_size);
143    memcpy(map, desc_data, table->desc_size);
144 
145    return VK_SUCCESS;
146 }
147 
148 VkResult
hk_descriptor_table_add(struct hk_device * dev,struct hk_descriptor_table * table,const void * desc_data,size_t desc_size,uint32_t * index_out)149 hk_descriptor_table_add(struct hk_device *dev,
150                         struct hk_descriptor_table *table,
151                         const void *desc_data, size_t desc_size,
152                         uint32_t *index_out)
153 {
154    simple_mtx_lock(&table->mutex);
155    VkResult result = hk_descriptor_table_add_locked(dev, table, desc_data,
156                                                     desc_size, index_out);
157    simple_mtx_unlock(&table->mutex);
158 
159    return result;
160 }
161 
162 void
hk_descriptor_table_remove(struct hk_device * dev,struct hk_descriptor_table * table,uint32_t index)163 hk_descriptor_table_remove(struct hk_device *dev,
164                            struct hk_descriptor_table *table, uint32_t index)
165 {
166    simple_mtx_lock(&table->mutex);
167 
168    void *map = (char *)table->map + (index * table->desc_size);
169    memset(map, 0, table->desc_size);
170 
171    /* Sanity check for double-free */
172    assert(table->free_count < table->alloc);
173    for (uint32_t i = 0; i < table->free_count; i++)
174       assert(table->free_table[i] != index);
175 
176    table->free_table[table->free_count++] = index;
177 
178    simple_mtx_unlock(&table->mutex);
179 }
180