The open source OpenXR runtime
at v21.0.0 213 lines 5.6 kB view raw
1// Copyright 2019-2020, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief Buffer functions. 6 * @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com> 7 * @author Jakob Bornecrantz <jakob@collabora.com> 8 * @ingroup comp_main 9 */ 10 11#include "main/comp_compositor.h" 12 13#include "render/comp_render.h" 14 15#include <stdio.h> 16 17 18/* 19 * 20 * Common helpers. 21 * 22 */ 23 24static VkResult 25create_buffer(struct vk_bundle *vk, 26 VkBufferUsageFlags usage_flags, 27 VkMemoryPropertyFlags memory_property_flags, 28 VkDeviceSize size, 29 VkBuffer *out_buffer, 30 VkDeviceMemory *out_memory, 31 VkDeviceSize *out_alignment, 32 VkDeviceSize *out_allocation_size) 33{ 34 VkResult ret; 35 36 // Create the buffer handle. 37 VkBufferCreateInfo buffer_info = { 38 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 39 .size = size, 40 .usage = usage_flags, 41 }; 42 43 VkBuffer buffer = VK_NULL_HANDLE; 44 ret = vk->vkCreateBuffer(vk->device, // 45 &buffer_info, // 46 NULL, // 47 &buffer); // 48 if (ret != VK_SUCCESS) { 49 VK_ERROR(vk, "vkCreateBuffer failed: '%s'", vk_result_string(ret)); 50 return ret; 51 } 52 53 // Create the memory backing up the buffer handle. 54 VkMemoryRequirements mem_reqs; 55 vk->vkGetBufferMemoryRequirements(vk->device, // 56 buffer, // 57 &mem_reqs); // 58 59 // Find a memory type index that fits the properties of the buffer. 60 uint32_t memory_type_index = 0; 61 vk_get_memory_type(vk, // 62 mem_reqs.memoryTypeBits, // 63 memory_property_flags, // 64 &memory_type_index); // 65 66 VkMemoryAllocateInfo mem_alloc = { 67 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 68 .allocationSize = mem_reqs.size, 69 .memoryTypeIndex = memory_type_index, 70 }; 71 72 VkDeviceMemory memory = VK_NULL_HANDLE; 73 ret = vk->vkAllocateMemory(vk->device, // 74 &mem_alloc, // 75 NULL, // 76 &memory); // 77 if (ret != VK_SUCCESS) { 78 VK_ERROR(vk, "vkAllocateMemory failed: '%s'", vk_result_string(ret)); 79 goto err_buffer; 80 } 81 82 83 // Attach the memory to the buffer object 84 ret = vk->vkBindBufferMemory(vk->device, // 85 buffer, // buffer 86 memory, // memory 87 0); // memoryOffset 88 if (ret != VK_SUCCESS) { 89 VK_ERROR(vk, "vkBindBufferMemory failed: '%s'", vk_result_string(ret)); 90 goto err_memory; 91 } 92 93 *out_memory = memory; 94 *out_buffer = buffer; 95 *out_alignment = mem_reqs.alignment; 96 *out_allocation_size = mem_alloc.allocationSize; 97 98 return VK_SUCCESS; 99 100 101err_memory: 102 vk->vkFreeMemory(vk->device, memory, NULL); 103 104err_buffer: 105 vk->vkDestroyBuffer(vk->device, buffer, NULL); 106 107 return ret; 108} 109 110 111/* 112 * 113 * 'Exported' functions. 114 * 115 */ 116 117VkResult 118comp_buffer_init(struct vk_bundle *vk, 119 struct comp_buffer *buffer, 120 VkBufferUsageFlags usage_flags, 121 VkMemoryPropertyFlags memory_property_flags, 122 VkDeviceSize size) 123{ 124 return create_buffer(vk, // 125 usage_flags, // usage_flags 126 memory_property_flags, // memory_property_flags 127 size, // size 128 &buffer->buffer, // out_buffer 129 &buffer->memory, // out_memory 130 &buffer->alignment, // out_alignment 131 &buffer->allocation_size); // out_allocation_size 132} 133 134void 135comp_buffer_close(struct vk_bundle *vk, struct comp_buffer *buffer) 136{ 137 if (buffer->buffer != VK_NULL_HANDLE) { 138 vk->vkDestroyBuffer(vk->device, buffer->buffer, NULL); 139 } 140 if (buffer->memory != VK_NULL_HANDLE) { 141 vk->vkFreeMemory(vk->device, buffer->memory, NULL); 142 } 143 144 U_ZERO(buffer); 145} 146 147VkResult 148comp_buffer_map(struct vk_bundle *vk, struct comp_buffer *buffer) 149{ 150 return vk->vkMapMemory(vk->device, // 151 buffer->memory, // memory 152 0, // offset 153 VK_WHOLE_SIZE, // size 154 0, // flags 155 &buffer->mapped); // ppData 156} 157 158void 159comp_buffer_unmap(struct vk_bundle *vk, struct comp_buffer *buffer) 160{ 161 if (buffer->mapped != NULL) { 162 vk->vkUnmapMemory(vk->device, buffer->memory); 163 buffer->mapped = NULL; 164 } 165} 166 167VkResult 168comp_buffer_map_and_write(struct vk_bundle *vk, struct comp_buffer *buffer, void *data, VkDeviceSize size) 169{ 170 VkResult ret; 171 172 if (size > buffer->allocation_size) { 173 VK_ERROR(vk, "Trying to write more the buffer size!"); 174 return VK_ERROR_OUT_OF_DEVICE_MEMORY; 175 } 176 177 if (buffer->mapped == NULL) { 178 ret = comp_buffer_map(vk, buffer); 179 if (ret != VK_SUCCESS) { 180 return ret; 181 } 182 } 183 184 memcpy(buffer->mapped, data, size); 185 186 return VK_SUCCESS; 187} 188 189VkResult 190comp_buffer_write(struct vk_bundle *vk, struct comp_buffer *buffer, void *data, VkDeviceSize size) 191{ 192 if (size > buffer->allocation_size) { 193 VK_ERROR(vk, "Trying to write more the buffer size!"); 194 return VK_ERROR_OUT_OF_DEVICE_MEMORY; 195 } 196 197 bool mapped = buffer->mapped != NULL; 198 if (!mapped) { 199 VkResult ret = comp_buffer_map(vk, buffer); 200 if (ret != VK_SUCCESS) { 201 return ret; 202 } 203 } 204 205 memcpy(buffer->mapped, data, size); 206 207 // Only unmap if we did the mapping. 208 if (!mapped) { 209 comp_buffer_unmap(vk, buffer); 210 } 211 212 return VK_SUCCESS; 213}