xref: /aosp_15_r20/external/mesa3d/src/virtio/vulkan/vn_buffer.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2019 Google LLC
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  *
5*61046927SAndroid Build Coastguard Worker  * based in part on anv and radv which are:
6*61046927SAndroid Build Coastguard Worker  * Copyright © 2015 Intel Corporation
7*61046927SAndroid Build Coastguard Worker  * Copyright © 2016 Red Hat.
8*61046927SAndroid Build Coastguard Worker  * Copyright © 2016 Bas Nieuwenhuizen
9*61046927SAndroid Build Coastguard Worker  */
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker #include "vn_buffer.h"
12*61046927SAndroid Build Coastguard Worker 
13*61046927SAndroid Build Coastguard Worker #include "venus-protocol/vn_protocol_driver_buffer.h"
14*61046927SAndroid Build Coastguard Worker #include "venus-protocol/vn_protocol_driver_buffer_view.h"
15*61046927SAndroid Build Coastguard Worker 
16*61046927SAndroid Build Coastguard Worker #include "vn_android.h"
17*61046927SAndroid Build Coastguard Worker #include "vn_device.h"
18*61046927SAndroid Build Coastguard Worker #include "vn_device_memory.h"
19*61046927SAndroid Build Coastguard Worker #include "vn_physical_device.h"
20*61046927SAndroid Build Coastguard Worker 
21*61046927SAndroid Build Coastguard Worker /* buffer commands */
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker static inline uint64_t
vn_buffer_get_cache_index(const VkBufferCreateInfo * create_info,struct vn_buffer_reqs_cache * cache)24*61046927SAndroid Build Coastguard Worker vn_buffer_get_cache_index(const VkBufferCreateInfo *create_info,
25*61046927SAndroid Build Coastguard Worker                           struct vn_buffer_reqs_cache *cache)
26*61046927SAndroid Build Coastguard Worker {
27*61046927SAndroid Build Coastguard Worker    /* For simplicity, cache only when below conditions are met:
28*61046927SAndroid Build Coastguard Worker     * - pNext is NULL
29*61046927SAndroid Build Coastguard Worker     * - VK_SHARING_MODE_EXCLUSIVE or VK_SHARING_MODE_CONCURRENT across all
30*61046927SAndroid Build Coastguard Worker     *
31*61046927SAndroid Build Coastguard Worker     * Combine sharing mode, flags and usage bits to form a unique index.
32*61046927SAndroid Build Coastguard Worker     *
33*61046927SAndroid Build Coastguard Worker     * Btw, we assume VkBufferCreateFlagBits won't exhaust all 32bits, at least
34*61046927SAndroid Build Coastguard Worker     * no earlier than VkBufferUsageFlagBits.
35*61046927SAndroid Build Coastguard Worker     */
36*61046927SAndroid Build Coastguard Worker    assert(!(create_info->flags & 0x80000000));
37*61046927SAndroid Build Coastguard Worker 
38*61046927SAndroid Build Coastguard Worker    const bool is_exclusive =
39*61046927SAndroid Build Coastguard Worker       create_info->sharingMode == VK_SHARING_MODE_EXCLUSIVE;
40*61046927SAndroid Build Coastguard Worker    const bool is_concurrent =
41*61046927SAndroid Build Coastguard Worker       create_info->sharingMode == VK_SHARING_MODE_CONCURRENT &&
42*61046927SAndroid Build Coastguard Worker       create_info->queueFamilyIndexCount == cache->queue_family_count;
43*61046927SAndroid Build Coastguard Worker    if (create_info->size <= cache->max_buffer_size &&
44*61046927SAndroid Build Coastguard Worker        create_info->pNext == NULL && (is_exclusive || is_concurrent)) {
45*61046927SAndroid Build Coastguard Worker       return (uint64_t)is_concurrent << 63 |
46*61046927SAndroid Build Coastguard Worker              (uint64_t)create_info->flags << 32 | create_info->usage;
47*61046927SAndroid Build Coastguard Worker    }
48*61046927SAndroid Build Coastguard Worker 
49*61046927SAndroid Build Coastguard Worker    /* index being zero suggests uncachable since usage must not be zero */
50*61046927SAndroid Build Coastguard Worker    return 0;
51*61046927SAndroid Build Coastguard Worker }
52*61046927SAndroid Build Coastguard Worker 
53*61046927SAndroid Build Coastguard Worker static inline uint64_t
vn_buffer_get_max_buffer_size(struct vn_physical_device * physical_dev)54*61046927SAndroid Build Coastguard Worker vn_buffer_get_max_buffer_size(struct vn_physical_device *physical_dev)
55*61046927SAndroid Build Coastguard Worker {
56*61046927SAndroid Build Coastguard Worker    /* Without maintenance4, hardcode the min of supported drivers:
57*61046927SAndroid Build Coastguard Worker     * - anv:  1ull << 30
58*61046927SAndroid Build Coastguard Worker     * - radv: UINT32_MAX - 4
59*61046927SAndroid Build Coastguard Worker     * - tu:   UINT32_MAX + 1
60*61046927SAndroid Build Coastguard Worker     * - lvp:  UINT32_MAX
61*61046927SAndroid Build Coastguard Worker     * - mali: UINT32_MAX
62*61046927SAndroid Build Coastguard Worker     */
63*61046927SAndroid Build Coastguard Worker    static const uint64_t safe_max_buffer_size = 1ULL << 30;
64*61046927SAndroid Build Coastguard Worker    return physical_dev->base.base.supported_features.maintenance4
65*61046927SAndroid Build Coastguard Worker              ? physical_dev->base.base.properties.maxBufferSize
66*61046927SAndroid Build Coastguard Worker              : safe_max_buffer_size;
67*61046927SAndroid Build Coastguard Worker }
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker void
vn_buffer_reqs_cache_init(struct vn_device * dev)70*61046927SAndroid Build Coastguard Worker vn_buffer_reqs_cache_init(struct vn_device *dev)
71*61046927SAndroid Build Coastguard Worker {
72*61046927SAndroid Build Coastguard Worker    assert(dev->physical_device->queue_family_count);
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker    dev->buffer_reqs_cache.max_buffer_size =
75*61046927SAndroid Build Coastguard Worker       vn_buffer_get_max_buffer_size(dev->physical_device);
76*61046927SAndroid Build Coastguard Worker    dev->buffer_reqs_cache.queue_family_count =
77*61046927SAndroid Build Coastguard Worker       dev->physical_device->queue_family_count;
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&dev->buffer_reqs_cache.mutex, mtx_plain);
80*61046927SAndroid Build Coastguard Worker    util_sparse_array_init(&dev->buffer_reqs_cache.entries,
81*61046927SAndroid Build Coastguard Worker                           sizeof(struct vn_buffer_reqs_cache_entry), 64);
82*61046927SAndroid Build Coastguard Worker }
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker static void
vn_buffer_reqs_cache_debug_dump(struct vn_buffer_reqs_cache * cache)85*61046927SAndroid Build Coastguard Worker vn_buffer_reqs_cache_debug_dump(struct vn_buffer_reqs_cache *cache)
86*61046927SAndroid Build Coastguard Worker {
87*61046927SAndroid Build Coastguard Worker    vn_log(NULL, "dumping buffer cache statistics");
88*61046927SAndroid Build Coastguard Worker    vn_log(NULL, "  cache hit: %d", cache->debug.cache_hit_count);
89*61046927SAndroid Build Coastguard Worker    vn_log(NULL, "  cache miss: %d", cache->debug.cache_miss_count);
90*61046927SAndroid Build Coastguard Worker    vn_log(NULL, "  cache skip: %d", cache->debug.cache_skip_count);
91*61046927SAndroid Build Coastguard Worker }
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker void
vn_buffer_reqs_cache_fini(struct vn_device * dev)94*61046927SAndroid Build Coastguard Worker vn_buffer_reqs_cache_fini(struct vn_device *dev)
95*61046927SAndroid Build Coastguard Worker {
96*61046927SAndroid Build Coastguard Worker    util_sparse_array_finish(&dev->buffer_reqs_cache.entries);
97*61046927SAndroid Build Coastguard Worker    simple_mtx_destroy(&dev->buffer_reqs_cache.mutex);
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker    if (VN_DEBUG(CACHE))
100*61046927SAndroid Build Coastguard Worker       vn_buffer_reqs_cache_debug_dump(&dev->buffer_reqs_cache);
101*61046927SAndroid Build Coastguard Worker }
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker static inline uint32_t
vn_buffer_get_ahb_memory_type_bits(struct vn_device * dev)104*61046927SAndroid Build Coastguard Worker vn_buffer_get_ahb_memory_type_bits(struct vn_device *dev)
105*61046927SAndroid Build Coastguard Worker {
106*61046927SAndroid Build Coastguard Worker    struct vn_buffer_reqs_cache *cache = &dev->buffer_reqs_cache;
107*61046927SAndroid Build Coastguard Worker    if (unlikely(!cache->ahb_mem_type_bits_valid)) {
108*61046927SAndroid Build Coastguard Worker       simple_mtx_lock(&cache->mutex);
109*61046927SAndroid Build Coastguard Worker       if (!cache->ahb_mem_type_bits_valid) {
110*61046927SAndroid Build Coastguard Worker          cache->ahb_mem_type_bits =
111*61046927SAndroid Build Coastguard Worker             vn_android_get_ahb_buffer_memory_type_bits(dev);
112*61046927SAndroid Build Coastguard Worker          cache->ahb_mem_type_bits_valid = true;
113*61046927SAndroid Build Coastguard Worker       }
114*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&cache->mutex);
115*61046927SAndroid Build Coastguard Worker    }
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker    return cache->ahb_mem_type_bits;
118*61046927SAndroid Build Coastguard Worker }
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker static inline VkDeviceSize
vn_buffer_get_aligned_memory_requirement_size(VkDeviceSize size,const VkMemoryRequirements * req)121*61046927SAndroid Build Coastguard Worker vn_buffer_get_aligned_memory_requirement_size(VkDeviceSize size,
122*61046927SAndroid Build Coastguard Worker                                               const VkMemoryRequirements *req)
123*61046927SAndroid Build Coastguard Worker {
124*61046927SAndroid Build Coastguard Worker    /* TODO remove comment after mandating VK_KHR_maintenance4
125*61046927SAndroid Build Coastguard Worker     *
126*61046927SAndroid Build Coastguard Worker     * This is based on below implementation defined behavior:
127*61046927SAndroid Build Coastguard Worker     *    req.size <= align64(info.size, req.alignment)
128*61046927SAndroid Build Coastguard Worker     */
129*61046927SAndroid Build Coastguard Worker    return align64(size, req->alignment);
130*61046927SAndroid Build Coastguard Worker }
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker static struct vn_buffer_reqs_cache_entry *
vn_buffer_get_cached_memory_requirements(struct vn_buffer_reqs_cache * cache,const VkBufferCreateInfo * create_info,struct vn_buffer_memory_requirements * out)133*61046927SAndroid Build Coastguard Worker vn_buffer_get_cached_memory_requirements(
134*61046927SAndroid Build Coastguard Worker    struct vn_buffer_reqs_cache *cache,
135*61046927SAndroid Build Coastguard Worker    const VkBufferCreateInfo *create_info,
136*61046927SAndroid Build Coastguard Worker    struct vn_buffer_memory_requirements *out)
137*61046927SAndroid Build Coastguard Worker {
138*61046927SAndroid Build Coastguard Worker    if (VN_PERF(NO_ASYNC_BUFFER_CREATE))
139*61046927SAndroid Build Coastguard Worker       return NULL;
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker    /* 12.7. Resource Memory Association
142*61046927SAndroid Build Coastguard Worker     *
143*61046927SAndroid Build Coastguard Worker     * The memoryTypeBits member is identical for all VkBuffer objects created
144*61046927SAndroid Build Coastguard Worker     * with the same value for the flags and usage members in the
145*61046927SAndroid Build Coastguard Worker     * VkBufferCreateInfo structure and the handleTypes member of the
146*61046927SAndroid Build Coastguard Worker     * VkExternalMemoryBufferCreateInfo structure passed to vkCreateBuffer.
147*61046927SAndroid Build Coastguard Worker     */
148*61046927SAndroid Build Coastguard Worker    const uint64_t idx = vn_buffer_get_cache_index(create_info, cache);
149*61046927SAndroid Build Coastguard Worker    if (idx) {
150*61046927SAndroid Build Coastguard Worker       struct vn_buffer_reqs_cache_entry *entry =
151*61046927SAndroid Build Coastguard Worker          util_sparse_array_get(&cache->entries, idx);
152*61046927SAndroid Build Coastguard Worker 
153*61046927SAndroid Build Coastguard Worker       if (entry->valid) {
154*61046927SAndroid Build Coastguard Worker          *out = entry->requirements;
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker          out->memory.memoryRequirements.size =
157*61046927SAndroid Build Coastguard Worker             vn_buffer_get_aligned_memory_requirement_size(
158*61046927SAndroid Build Coastguard Worker                create_info->size, &out->memory.memoryRequirements);
159*61046927SAndroid Build Coastguard Worker 
160*61046927SAndroid Build Coastguard Worker          p_atomic_inc(&cache->debug.cache_hit_count);
161*61046927SAndroid Build Coastguard Worker       } else {
162*61046927SAndroid Build Coastguard Worker          p_atomic_inc(&cache->debug.cache_miss_count);
163*61046927SAndroid Build Coastguard Worker       }
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker       return entry;
166*61046927SAndroid Build Coastguard Worker    }
167*61046927SAndroid Build Coastguard Worker 
168*61046927SAndroid Build Coastguard Worker    p_atomic_inc(&cache->debug.cache_skip_count);
169*61046927SAndroid Build Coastguard Worker 
170*61046927SAndroid Build Coastguard Worker    return NULL;
171*61046927SAndroid Build Coastguard Worker }
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker static void
vn_buffer_reqs_cache_entry_init(struct vn_buffer_reqs_cache * cache,struct vn_buffer_reqs_cache_entry * entry,VkMemoryRequirements2 * req)174*61046927SAndroid Build Coastguard Worker vn_buffer_reqs_cache_entry_init(struct vn_buffer_reqs_cache *cache,
175*61046927SAndroid Build Coastguard Worker                                 struct vn_buffer_reqs_cache_entry *entry,
176*61046927SAndroid Build Coastguard Worker                                 VkMemoryRequirements2 *req)
177*61046927SAndroid Build Coastguard Worker {
178*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&cache->mutex);
179*61046927SAndroid Build Coastguard Worker 
180*61046927SAndroid Build Coastguard Worker    /* Entry might have already been initialized by another thread
181*61046927SAndroid Build Coastguard Worker     * before the lock
182*61046927SAndroid Build Coastguard Worker     */
183*61046927SAndroid Build Coastguard Worker    if (entry->valid)
184*61046927SAndroid Build Coastguard Worker       goto unlock;
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker    entry->requirements.memory = *req;
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker    const VkMemoryDedicatedRequirements *dedicated_req =
189*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(req->pNext, MEMORY_DEDICATED_REQUIREMENTS);
190*61046927SAndroid Build Coastguard Worker    if (dedicated_req)
191*61046927SAndroid Build Coastguard Worker       entry->requirements.dedicated = *dedicated_req;
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker    entry->valid = true;
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker unlock:
196*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&cache->mutex);
197*61046927SAndroid Build Coastguard Worker 
198*61046927SAndroid Build Coastguard Worker    /* ensure invariance of the memory requirement size */
199*61046927SAndroid Build Coastguard Worker    req->memoryRequirements.size =
200*61046927SAndroid Build Coastguard Worker       vn_buffer_get_aligned_memory_requirement_size(
201*61046927SAndroid Build Coastguard Worker          req->memoryRequirements.size,
202*61046927SAndroid Build Coastguard Worker          &entry->requirements.memory.memoryRequirements);
203*61046927SAndroid Build Coastguard Worker }
204*61046927SAndroid Build Coastguard Worker 
205*61046927SAndroid Build Coastguard Worker static void
vn_copy_cached_memory_requirements(const struct vn_buffer_memory_requirements * cached,VkMemoryRequirements2 * out_mem_req)206*61046927SAndroid Build Coastguard Worker vn_copy_cached_memory_requirements(
207*61046927SAndroid Build Coastguard Worker    const struct vn_buffer_memory_requirements *cached,
208*61046927SAndroid Build Coastguard Worker    VkMemoryRequirements2 *out_mem_req)
209*61046927SAndroid Build Coastguard Worker {
210*61046927SAndroid Build Coastguard Worker    union {
211*61046927SAndroid Build Coastguard Worker       VkBaseOutStructure *pnext;
212*61046927SAndroid Build Coastguard Worker       VkMemoryRequirements2 *two;
213*61046927SAndroid Build Coastguard Worker       VkMemoryDedicatedRequirements *dedicated;
214*61046927SAndroid Build Coastguard Worker    } u = { .two = out_mem_req };
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker    while (u.pnext) {
217*61046927SAndroid Build Coastguard Worker       switch (u.pnext->sType) {
218*61046927SAndroid Build Coastguard Worker       case VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2:
219*61046927SAndroid Build Coastguard Worker          u.two->memoryRequirements = cached->memory.memoryRequirements;
220*61046927SAndroid Build Coastguard Worker          break;
221*61046927SAndroid Build Coastguard Worker       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS:
222*61046927SAndroid Build Coastguard Worker          u.dedicated->prefersDedicatedAllocation =
223*61046927SAndroid Build Coastguard Worker             cached->dedicated.prefersDedicatedAllocation;
224*61046927SAndroid Build Coastguard Worker          u.dedicated->requiresDedicatedAllocation =
225*61046927SAndroid Build Coastguard Worker             cached->dedicated.requiresDedicatedAllocation;
226*61046927SAndroid Build Coastguard Worker          break;
227*61046927SAndroid Build Coastguard Worker       default:
228*61046927SAndroid Build Coastguard Worker          break;
229*61046927SAndroid Build Coastguard Worker       }
230*61046927SAndroid Build Coastguard Worker       u.pnext = u.pnext->pNext;
231*61046927SAndroid Build Coastguard Worker    }
232*61046927SAndroid Build Coastguard Worker }
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker static VkResult
vn_buffer_init(struct vn_device * dev,const VkBufferCreateInfo * create_info,struct vn_buffer * buf)235*61046927SAndroid Build Coastguard Worker vn_buffer_init(struct vn_device *dev,
236*61046927SAndroid Build Coastguard Worker                const VkBufferCreateInfo *create_info,
237*61046927SAndroid Build Coastguard Worker                struct vn_buffer *buf)
238*61046927SAndroid Build Coastguard Worker {
239*61046927SAndroid Build Coastguard Worker    VkDevice dev_handle = vn_device_to_handle(dev);
240*61046927SAndroid Build Coastguard Worker    VkBuffer buf_handle = vn_buffer_to_handle(buf);
241*61046927SAndroid Build Coastguard Worker    struct vn_buffer_reqs_cache *cache = &dev->buffer_reqs_cache;
242*61046927SAndroid Build Coastguard Worker    VkResult result;
243*61046927SAndroid Build Coastguard Worker 
244*61046927SAndroid Build Coastguard Worker    /* If cacheable and mem requirements found in cache, make async call */
245*61046927SAndroid Build Coastguard Worker    struct vn_buffer_reqs_cache_entry *entry =
246*61046927SAndroid Build Coastguard Worker       vn_buffer_get_cached_memory_requirements(cache, create_info,
247*61046927SAndroid Build Coastguard Worker                                                &buf->requirements);
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker    /* Check size instead of entry->valid to be lock free */
250*61046927SAndroid Build Coastguard Worker    if (buf->requirements.memory.memoryRequirements.size) {
251*61046927SAndroid Build Coastguard Worker       vn_async_vkCreateBuffer(dev->primary_ring, dev_handle, create_info,
252*61046927SAndroid Build Coastguard Worker                               NULL, &buf_handle);
253*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
254*61046927SAndroid Build Coastguard Worker    }
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker    /* If cache miss or not cacheable, make synchronous call */
257*61046927SAndroid Build Coastguard Worker    result = vn_call_vkCreateBuffer(dev->primary_ring, dev_handle, create_info,
258*61046927SAndroid Build Coastguard Worker                                    NULL, &buf_handle);
259*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
260*61046927SAndroid Build Coastguard Worker       return result;
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker    buf->requirements.memory.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
263*61046927SAndroid Build Coastguard Worker    buf->requirements.memory.pNext = &buf->requirements.dedicated;
264*61046927SAndroid Build Coastguard Worker    buf->requirements.dedicated.sType =
265*61046927SAndroid Build Coastguard Worker       VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
266*61046927SAndroid Build Coastguard Worker    buf->requirements.dedicated.pNext = NULL;
267*61046927SAndroid Build Coastguard Worker 
268*61046927SAndroid Build Coastguard Worker    vn_call_vkGetBufferMemoryRequirements2(
269*61046927SAndroid Build Coastguard Worker       dev->primary_ring, dev_handle,
270*61046927SAndroid Build Coastguard Worker       &(VkBufferMemoryRequirementsInfo2){
271*61046927SAndroid Build Coastguard Worker          .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
272*61046927SAndroid Build Coastguard Worker          .buffer = buf_handle,
273*61046927SAndroid Build Coastguard Worker       },
274*61046927SAndroid Build Coastguard Worker       &buf->requirements.memory);
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker    /* If cacheable, store mem requirements from the synchronous call */
277*61046927SAndroid Build Coastguard Worker    if (entry) {
278*61046927SAndroid Build Coastguard Worker       vn_buffer_reqs_cache_entry_init(cache, entry,
279*61046927SAndroid Build Coastguard Worker                                       &buf->requirements.memory);
280*61046927SAndroid Build Coastguard Worker    }
281*61046927SAndroid Build Coastguard Worker 
282*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
283*61046927SAndroid Build Coastguard Worker }
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker VkResult
vn_buffer_create(struct vn_device * dev,const VkBufferCreateInfo * create_info,const VkAllocationCallbacks * alloc,struct vn_buffer ** out_buf)286*61046927SAndroid Build Coastguard Worker vn_buffer_create(struct vn_device *dev,
287*61046927SAndroid Build Coastguard Worker                  const VkBufferCreateInfo *create_info,
288*61046927SAndroid Build Coastguard Worker                  const VkAllocationCallbacks *alloc,
289*61046927SAndroid Build Coastguard Worker                  struct vn_buffer **out_buf)
290*61046927SAndroid Build Coastguard Worker {
291*61046927SAndroid Build Coastguard Worker    struct vn_buffer *buf = NULL;
292*61046927SAndroid Build Coastguard Worker    VkResult result;
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker    buf = vk_zalloc(alloc, sizeof(*buf), VN_DEFAULT_ALIGN,
295*61046927SAndroid Build Coastguard Worker                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
296*61046927SAndroid Build Coastguard Worker    if (!buf)
297*61046927SAndroid Build Coastguard Worker       return VK_ERROR_OUT_OF_HOST_MEMORY;
298*61046927SAndroid Build Coastguard Worker 
299*61046927SAndroid Build Coastguard Worker    vn_object_base_init(&buf->base, VK_OBJECT_TYPE_BUFFER, &dev->base);
300*61046927SAndroid Build Coastguard Worker 
301*61046927SAndroid Build Coastguard Worker    result = vn_buffer_init(dev, create_info, buf);
302*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
303*61046927SAndroid Build Coastguard Worker       vn_object_base_fini(&buf->base);
304*61046927SAndroid Build Coastguard Worker       vk_free(alloc, buf);
305*61046927SAndroid Build Coastguard Worker       return result;
306*61046927SAndroid Build Coastguard Worker    }
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker    *out_buf = buf;
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
311*61046927SAndroid Build Coastguard Worker }
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker struct vn_buffer_create_info {
314*61046927SAndroid Build Coastguard Worker    VkBufferCreateInfo create;
315*61046927SAndroid Build Coastguard Worker    VkExternalMemoryBufferCreateInfo external;
316*61046927SAndroid Build Coastguard Worker    VkBufferOpaqueCaptureAddressCreateInfo capture;
317*61046927SAndroid Build Coastguard Worker };
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker static const VkBufferCreateInfo *
vn_buffer_fix_create_info(const VkBufferCreateInfo * create_info,const VkExternalMemoryHandleTypeFlagBits renderer_handle_type,struct vn_buffer_create_info * local_info)320*61046927SAndroid Build Coastguard Worker vn_buffer_fix_create_info(
321*61046927SAndroid Build Coastguard Worker    const VkBufferCreateInfo *create_info,
322*61046927SAndroid Build Coastguard Worker    const VkExternalMemoryHandleTypeFlagBits renderer_handle_type,
323*61046927SAndroid Build Coastguard Worker    struct vn_buffer_create_info *local_info)
324*61046927SAndroid Build Coastguard Worker {
325*61046927SAndroid Build Coastguard Worker    local_info->create = *create_info;
326*61046927SAndroid Build Coastguard Worker    VkBaseOutStructure *cur = (void *)&local_info->create;
327*61046927SAndroid Build Coastguard Worker 
328*61046927SAndroid Build Coastguard Worker    vk_foreach_struct_const(src, create_info->pNext) {
329*61046927SAndroid Build Coastguard Worker       void *next = NULL;
330*61046927SAndroid Build Coastguard Worker       switch (src->sType) {
331*61046927SAndroid Build Coastguard Worker       case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO:
332*61046927SAndroid Build Coastguard Worker          memcpy(&local_info->external, src, sizeof(local_info->external));
333*61046927SAndroid Build Coastguard Worker          local_info->external.handleTypes = renderer_handle_type;
334*61046927SAndroid Build Coastguard Worker          next = &local_info->external;
335*61046927SAndroid Build Coastguard Worker          break;
336*61046927SAndroid Build Coastguard Worker       case VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO:
337*61046927SAndroid Build Coastguard Worker          memcpy(&local_info->capture, src, sizeof(local_info->capture));
338*61046927SAndroid Build Coastguard Worker          next = &local_info->capture;
339*61046927SAndroid Build Coastguard Worker          break;
340*61046927SAndroid Build Coastguard Worker       default:
341*61046927SAndroid Build Coastguard Worker          break;
342*61046927SAndroid Build Coastguard Worker       }
343*61046927SAndroid Build Coastguard Worker 
344*61046927SAndroid Build Coastguard Worker       if (next) {
345*61046927SAndroid Build Coastguard Worker          cur->pNext = next;
346*61046927SAndroid Build Coastguard Worker          cur = next;
347*61046927SAndroid Build Coastguard Worker       }
348*61046927SAndroid Build Coastguard Worker    }
349*61046927SAndroid Build Coastguard Worker 
350*61046927SAndroid Build Coastguard Worker    cur->pNext = NULL;
351*61046927SAndroid Build Coastguard Worker 
352*61046927SAndroid Build Coastguard Worker    return &local_info->create;
353*61046927SAndroid Build Coastguard Worker }
354*61046927SAndroid Build Coastguard Worker 
355*61046927SAndroid Build Coastguard Worker VkResult
vn_CreateBuffer(VkDevice device,const VkBufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBuffer * pBuffer)356*61046927SAndroid Build Coastguard Worker vn_CreateBuffer(VkDevice device,
357*61046927SAndroid Build Coastguard Worker                 const VkBufferCreateInfo *pCreateInfo,
358*61046927SAndroid Build Coastguard Worker                 const VkAllocationCallbacks *pAllocator,
359*61046927SAndroid Build Coastguard Worker                 VkBuffer *pBuffer)
360*61046927SAndroid Build Coastguard Worker {
361*61046927SAndroid Build Coastguard Worker    struct vn_device *dev = vn_device_from_handle(device);
362*61046927SAndroid Build Coastguard Worker    const VkAllocationCallbacks *alloc =
363*61046927SAndroid Build Coastguard Worker       pAllocator ? pAllocator : &dev->base.base.alloc;
364*61046927SAndroid Build Coastguard Worker    const VkExternalMemoryHandleTypeFlagBits renderer_handle_type =
365*61046927SAndroid Build Coastguard Worker       dev->physical_device->external_memory.renderer_handle_type;
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker    struct vn_buffer_create_info local_info;
368*61046927SAndroid Build Coastguard Worker    const VkExternalMemoryBufferCreateInfo *external_info =
369*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext,
370*61046927SAndroid Build Coastguard Worker                            EXTERNAL_MEMORY_BUFFER_CREATE_INFO);
371*61046927SAndroid Build Coastguard Worker    if (external_info && external_info->handleTypes &&
372*61046927SAndroid Build Coastguard Worker        external_info->handleTypes != renderer_handle_type) {
373*61046927SAndroid Build Coastguard Worker       pCreateInfo = vn_buffer_fix_create_info(
374*61046927SAndroid Build Coastguard Worker          pCreateInfo, renderer_handle_type, &local_info);
375*61046927SAndroid Build Coastguard Worker    }
376*61046927SAndroid Build Coastguard Worker 
377*61046927SAndroid Build Coastguard Worker    struct vn_buffer *buf;
378*61046927SAndroid Build Coastguard Worker    VkResult result = vn_buffer_create(dev, pCreateInfo, alloc, &buf);
379*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
380*61046927SAndroid Build Coastguard Worker       return vn_error(dev->instance, result);
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker    if (external_info &&
383*61046927SAndroid Build Coastguard Worker        external_info->handleTypes ==
384*61046927SAndroid Build Coastguard Worker           VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) {
385*61046927SAndroid Build Coastguard Worker       /* AHB backed buffer layers on top of renderer external memory, so here
386*61046927SAndroid Build Coastguard Worker        * we combine the queried type bits from both buffer memory requirement
387*61046927SAndroid Build Coastguard Worker        * and renderer external memory properties.
388*61046927SAndroid Build Coastguard Worker        */
389*61046927SAndroid Build Coastguard Worker       buf->requirements.memory.memoryRequirements.memoryTypeBits &=
390*61046927SAndroid Build Coastguard Worker          vn_buffer_get_ahb_memory_type_bits(dev);
391*61046927SAndroid Build Coastguard Worker 
392*61046927SAndroid Build Coastguard Worker       assert(buf->requirements.memory.memoryRequirements.memoryTypeBits);
393*61046927SAndroid Build Coastguard Worker    }
394*61046927SAndroid Build Coastguard Worker 
395*61046927SAndroid Build Coastguard Worker    *pBuffer = vn_buffer_to_handle(buf);
396*61046927SAndroid Build Coastguard Worker 
397*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
398*61046927SAndroid Build Coastguard Worker }
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker void
vn_DestroyBuffer(VkDevice device,VkBuffer buffer,const VkAllocationCallbacks * pAllocator)401*61046927SAndroid Build Coastguard Worker vn_DestroyBuffer(VkDevice device,
402*61046927SAndroid Build Coastguard Worker                  VkBuffer buffer,
403*61046927SAndroid Build Coastguard Worker                  const VkAllocationCallbacks *pAllocator)
404*61046927SAndroid Build Coastguard Worker {
405*61046927SAndroid Build Coastguard Worker    struct vn_device *dev = vn_device_from_handle(device);
406*61046927SAndroid Build Coastguard Worker    struct vn_buffer *buf = vn_buffer_from_handle(buffer);
407*61046927SAndroid Build Coastguard Worker    const VkAllocationCallbacks *alloc =
408*61046927SAndroid Build Coastguard Worker       pAllocator ? pAllocator : &dev->base.base.alloc;
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker    if (!buf)
411*61046927SAndroid Build Coastguard Worker       return;
412*61046927SAndroid Build Coastguard Worker 
413*61046927SAndroid Build Coastguard Worker    vn_async_vkDestroyBuffer(dev->primary_ring, device, buffer, NULL);
414*61046927SAndroid Build Coastguard Worker 
415*61046927SAndroid Build Coastguard Worker    vn_object_base_fini(&buf->base);
416*61046927SAndroid Build Coastguard Worker    vk_free(alloc, buf);
417*61046927SAndroid Build Coastguard Worker }
418*61046927SAndroid Build Coastguard Worker 
419*61046927SAndroid Build Coastguard Worker VkDeviceAddress
vn_GetBufferDeviceAddress(VkDevice device,const VkBufferDeviceAddressInfo * pInfo)420*61046927SAndroid Build Coastguard Worker vn_GetBufferDeviceAddress(VkDevice device,
421*61046927SAndroid Build Coastguard Worker                           const VkBufferDeviceAddressInfo *pInfo)
422*61046927SAndroid Build Coastguard Worker {
423*61046927SAndroid Build Coastguard Worker    struct vn_device *dev = vn_device_from_handle(device);
424*61046927SAndroid Build Coastguard Worker 
425*61046927SAndroid Build Coastguard Worker    return vn_call_vkGetBufferDeviceAddress(dev->primary_ring, device, pInfo);
426*61046927SAndroid Build Coastguard Worker }
427*61046927SAndroid Build Coastguard Worker 
428*61046927SAndroid Build Coastguard Worker uint64_t
vn_GetBufferOpaqueCaptureAddress(VkDevice device,const VkBufferDeviceAddressInfo * pInfo)429*61046927SAndroid Build Coastguard Worker vn_GetBufferOpaqueCaptureAddress(VkDevice device,
430*61046927SAndroid Build Coastguard Worker                                  const VkBufferDeviceAddressInfo *pInfo)
431*61046927SAndroid Build Coastguard Worker {
432*61046927SAndroid Build Coastguard Worker    struct vn_device *dev = vn_device_from_handle(device);
433*61046927SAndroid Build Coastguard Worker 
434*61046927SAndroid Build Coastguard Worker    return vn_call_vkGetBufferOpaqueCaptureAddress(dev->primary_ring, device,
435*61046927SAndroid Build Coastguard Worker                                                   pInfo);
436*61046927SAndroid Build Coastguard Worker }
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker void
vn_GetBufferMemoryRequirements2(VkDevice device,const VkBufferMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)439*61046927SAndroid Build Coastguard Worker vn_GetBufferMemoryRequirements2(VkDevice device,
440*61046927SAndroid Build Coastguard Worker                                 const VkBufferMemoryRequirementsInfo2 *pInfo,
441*61046927SAndroid Build Coastguard Worker                                 VkMemoryRequirements2 *pMemoryRequirements)
442*61046927SAndroid Build Coastguard Worker {
443*61046927SAndroid Build Coastguard Worker    const struct vn_buffer *buf = vn_buffer_from_handle(pInfo->buffer);
444*61046927SAndroid Build Coastguard Worker 
445*61046927SAndroid Build Coastguard Worker    vn_copy_cached_memory_requirements(&buf->requirements,
446*61046927SAndroid Build Coastguard Worker                                       pMemoryRequirements);
447*61046927SAndroid Build Coastguard Worker }
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker VkResult
vn_BindBufferMemory2(VkDevice device,uint32_t bindInfoCount,const VkBindBufferMemoryInfo * pBindInfos)450*61046927SAndroid Build Coastguard Worker vn_BindBufferMemory2(VkDevice device,
451*61046927SAndroid Build Coastguard Worker                      uint32_t bindInfoCount,
452*61046927SAndroid Build Coastguard Worker                      const VkBindBufferMemoryInfo *pBindInfos)
453*61046927SAndroid Build Coastguard Worker {
454*61046927SAndroid Build Coastguard Worker    struct vn_device *dev = vn_device_from_handle(device);
455*61046927SAndroid Build Coastguard Worker    vn_async_vkBindBufferMemory2(dev->primary_ring, device, bindInfoCount,
456*61046927SAndroid Build Coastguard Worker                                 pBindInfos);
457*61046927SAndroid Build Coastguard Worker 
458*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
459*61046927SAndroid Build Coastguard Worker }
460*61046927SAndroid Build Coastguard Worker 
461*61046927SAndroid Build Coastguard Worker /* buffer view commands */
462*61046927SAndroid Build Coastguard Worker 
463*61046927SAndroid Build Coastguard Worker VkResult
vn_CreateBufferView(VkDevice device,const VkBufferViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBufferView * pView)464*61046927SAndroid Build Coastguard Worker vn_CreateBufferView(VkDevice device,
465*61046927SAndroid Build Coastguard Worker                     const VkBufferViewCreateInfo *pCreateInfo,
466*61046927SAndroid Build Coastguard Worker                     const VkAllocationCallbacks *pAllocator,
467*61046927SAndroid Build Coastguard Worker                     VkBufferView *pView)
468*61046927SAndroid Build Coastguard Worker {
469*61046927SAndroid Build Coastguard Worker    struct vn_device *dev = vn_device_from_handle(device);
470*61046927SAndroid Build Coastguard Worker    const VkAllocationCallbacks *alloc =
471*61046927SAndroid Build Coastguard Worker       pAllocator ? pAllocator : &dev->base.base.alloc;
472*61046927SAndroid Build Coastguard Worker 
473*61046927SAndroid Build Coastguard Worker    struct vn_buffer_view *view =
474*61046927SAndroid Build Coastguard Worker       vk_zalloc(alloc, sizeof(*view), VN_DEFAULT_ALIGN,
475*61046927SAndroid Build Coastguard Worker                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
476*61046927SAndroid Build Coastguard Worker    if (!view)
477*61046927SAndroid Build Coastguard Worker       return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
478*61046927SAndroid Build Coastguard Worker 
479*61046927SAndroid Build Coastguard Worker    vn_object_base_init(&view->base, VK_OBJECT_TYPE_BUFFER_VIEW, &dev->base);
480*61046927SAndroid Build Coastguard Worker 
481*61046927SAndroid Build Coastguard Worker    VkBufferView view_handle = vn_buffer_view_to_handle(view);
482*61046927SAndroid Build Coastguard Worker    vn_async_vkCreateBufferView(dev->primary_ring, device, pCreateInfo, NULL,
483*61046927SAndroid Build Coastguard Worker                                &view_handle);
484*61046927SAndroid Build Coastguard Worker 
485*61046927SAndroid Build Coastguard Worker    *pView = view_handle;
486*61046927SAndroid Build Coastguard Worker 
487*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
488*61046927SAndroid Build Coastguard Worker }
489*61046927SAndroid Build Coastguard Worker 
490*61046927SAndroid Build Coastguard Worker void
vn_DestroyBufferView(VkDevice device,VkBufferView bufferView,const VkAllocationCallbacks * pAllocator)491*61046927SAndroid Build Coastguard Worker vn_DestroyBufferView(VkDevice device,
492*61046927SAndroid Build Coastguard Worker                      VkBufferView bufferView,
493*61046927SAndroid Build Coastguard Worker                      const VkAllocationCallbacks *pAllocator)
494*61046927SAndroid Build Coastguard Worker {
495*61046927SAndroid Build Coastguard Worker    struct vn_device *dev = vn_device_from_handle(device);
496*61046927SAndroid Build Coastguard Worker    struct vn_buffer_view *view = vn_buffer_view_from_handle(bufferView);
497*61046927SAndroid Build Coastguard Worker    const VkAllocationCallbacks *alloc =
498*61046927SAndroid Build Coastguard Worker       pAllocator ? pAllocator : &dev->base.base.alloc;
499*61046927SAndroid Build Coastguard Worker 
500*61046927SAndroid Build Coastguard Worker    if (!view)
501*61046927SAndroid Build Coastguard Worker       return;
502*61046927SAndroid Build Coastguard Worker 
503*61046927SAndroid Build Coastguard Worker    vn_async_vkDestroyBufferView(dev->primary_ring, device, bufferView, NULL);
504*61046927SAndroid Build Coastguard Worker 
505*61046927SAndroid Build Coastguard Worker    vn_object_base_fini(&view->base);
506*61046927SAndroid Build Coastguard Worker    vk_free(alloc, view);
507*61046927SAndroid Build Coastguard Worker }
508*61046927SAndroid Build Coastguard Worker 
509*61046927SAndroid Build Coastguard Worker void
vn_GetDeviceBufferMemoryRequirements(VkDevice device,const VkDeviceBufferMemoryRequirements * pInfo,VkMemoryRequirements2 * pMemoryRequirements)510*61046927SAndroid Build Coastguard Worker vn_GetDeviceBufferMemoryRequirements(
511*61046927SAndroid Build Coastguard Worker    VkDevice device,
512*61046927SAndroid Build Coastguard Worker    const VkDeviceBufferMemoryRequirements *pInfo,
513*61046927SAndroid Build Coastguard Worker    VkMemoryRequirements2 *pMemoryRequirements)
514*61046927SAndroid Build Coastguard Worker {
515*61046927SAndroid Build Coastguard Worker    struct vn_device *dev = vn_device_from_handle(device);
516*61046927SAndroid Build Coastguard Worker    struct vn_buffer_reqs_cache *cache = &dev->buffer_reqs_cache;
517*61046927SAndroid Build Coastguard Worker    struct vn_buffer_memory_requirements reqs = { 0 };
518*61046927SAndroid Build Coastguard Worker 
519*61046927SAndroid Build Coastguard Worker    /* If cacheable and mem requirements found in cache, skip host call */
520*61046927SAndroid Build Coastguard Worker    struct vn_buffer_reqs_cache_entry *entry =
521*61046927SAndroid Build Coastguard Worker       vn_buffer_get_cached_memory_requirements(cache, pInfo->pCreateInfo,
522*61046927SAndroid Build Coastguard Worker                                                &reqs);
523*61046927SAndroid Build Coastguard Worker 
524*61046927SAndroid Build Coastguard Worker    /* Check size instead of entry->valid to be lock free */
525*61046927SAndroid Build Coastguard Worker    if (reqs.memory.memoryRequirements.size) {
526*61046927SAndroid Build Coastguard Worker       vn_copy_cached_memory_requirements(&reqs, pMemoryRequirements);
527*61046927SAndroid Build Coastguard Worker       return;
528*61046927SAndroid Build Coastguard Worker    }
529*61046927SAndroid Build Coastguard Worker 
530*61046927SAndroid Build Coastguard Worker    /* Make the host call if not found in cache or not cacheable */
531*61046927SAndroid Build Coastguard Worker    vn_call_vkGetDeviceBufferMemoryRequirements(dev->primary_ring, device,
532*61046927SAndroid Build Coastguard Worker                                                pInfo, pMemoryRequirements);
533*61046927SAndroid Build Coastguard Worker 
534*61046927SAndroid Build Coastguard Worker    /* If cacheable, store mem requirements from the host call */
535*61046927SAndroid Build Coastguard Worker    if (entry)
536*61046927SAndroid Build Coastguard Worker       vn_buffer_reqs_cache_entry_init(cache, entry, pMemoryRequirements);
537*61046927SAndroid Build Coastguard Worker }
538