The open source OpenXR runtime
1// Copyright 2019-2023, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Sub allocation functions.
6 * @author Jakob Bornecrantz <jakob@collabora.com>
7 * @ingroup comp_render
8 */
9
10#include "vk/vk_mini_helpers.h"
11#include "render/render_interface.h"
12
13
14// Align a size with a power of two value.
15static VkDeviceSize
16align_padding_pot(VkDeviceSize size, VkDeviceSize alignment)
17{
18 return (size + alignment - 1) & ~(alignment - 1);
19}
20
21
22/*
23 *
24 * 'Exported' functions.
25 *
26 */
27
28void
29render_sub_alloc_tracker_init(struct render_sub_alloc_tracker *rsat, struct render_buffer *buffer)
30{
31 rsat->buffer = buffer->buffer;
32 rsat->used = 0;
33 rsat->total_size = buffer->size;
34 rsat->mapped = buffer->mapped;
35}
36
37XRT_CHECK_RESULT VkResult
38render_sub_alloc_ubo_alloc_and_get_ptr(struct vk_bundle *vk,
39 struct render_sub_alloc_tracker *rsat,
40 VkDeviceSize size,
41 void **out_ptr,
42 struct render_sub_alloc *out_rsa)
43{
44 assert(rsat->total_size >= rsat->used);
45 VkDeviceSize space_left = rsat->total_size - rsat->used;
46
47 if (space_left < size) {
48 VK_ERROR(vk, "Can not fit %u in left %u of total %u", (uint32_t)size, (uint32_t)space_left,
49 (uint32_t)rsat->total_size);
50 return VK_ERROR_OUT_OF_DEVICE_MEMORY;
51 }
52
53 // Make sure we align from start of memory.
54 VkDeviceSize padded_used = align_padding_pot(rsat->used + size, RENDER_ALWAYS_SAFE_UBO_ALIGNMENT);
55
56 // Save the current used as offset.
57 VkDeviceSize offset = rsat->used;
58
59 // Ensure used never gets larger then total_size.
60 if (padded_used > rsat->total_size) {
61 rsat->used = rsat->total_size;
62 } else {
63 rsat->used = padded_used;
64 }
65
66 void *ptr = rsat->mapped == NULL ? NULL : (void *)((uint8_t *)rsat->mapped + offset);
67
68
69 /*
70 * All done.
71 */
72
73 *out_ptr = ptr;
74 *out_rsa = (struct render_sub_alloc){
75 .buffer = rsat->buffer,
76 .size = size,
77 .offset = offset,
78 };
79
80 return VK_SUCCESS;
81}
82
83XRT_CHECK_RESULT VkResult
84render_sub_alloc_ubo_alloc_and_write(struct vk_bundle *vk,
85 struct render_sub_alloc_tracker *rsat,
86 const void *src,
87 VkDeviceSize size,
88 struct render_sub_alloc *out_rsa)
89{
90 VkResult ret;
91
92 if (rsat->mapped == NULL) {
93 VK_ERROR(vk, "Sub allocation not mapped");
94 return VK_ERROR_OUT_OF_DEVICE_MEMORY;
95 }
96
97 void *dst;
98 ret = render_sub_alloc_ubo_alloc_and_get_ptr(vk, rsat, size, &dst, out_rsa);
99 VK_CHK_AND_RET(ret, "render_sub_alloc_ubo_alloc_and_get_ptr");
100
101 memcpy(dst, src, size);
102
103 return VK_SUCCESS;
104}