2020-10-05 22:30:31 +00:00
|
|
|
// Copyright 2019-2020, Collabora, Ltd.
|
|
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
|
|
/*!
|
|
|
|
* @file
|
|
|
|
* @brief Buffer functions.
|
|
|
|
* @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
|
|
|
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
2021-11-03 17:45:39 +00:00
|
|
|
* @ingroup comp_render
|
2020-10-05 22:30:31 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "main/comp_compositor.h"
|
|
|
|
|
|
|
|
#include "render/comp_render.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Common helpers.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VkResult
|
|
|
|
create_buffer(struct vk_bundle *vk,
|
|
|
|
VkBufferUsageFlags usage_flags,
|
|
|
|
VkMemoryPropertyFlags memory_property_flags,
|
|
|
|
VkDeviceSize size,
|
|
|
|
VkBuffer *out_buffer,
|
|
|
|
VkDeviceMemory *out_memory,
|
|
|
|
VkDeviceSize *out_alignment,
|
|
|
|
VkDeviceSize *out_allocation_size)
|
|
|
|
{
|
|
|
|
VkResult ret;
|
|
|
|
|
|
|
|
// Create the buffer handle.
|
|
|
|
VkBufferCreateInfo buffer_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
|
|
.size = size,
|
|
|
|
.usage = usage_flags,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkBuffer buffer = VK_NULL_HANDLE;
|
|
|
|
ret = vk->vkCreateBuffer(vk->device, //
|
|
|
|
&buffer_info, //
|
|
|
|
NULL, //
|
|
|
|
&buffer); //
|
|
|
|
if (ret != VK_SUCCESS) {
|
2021-01-14 14:13:48 +00:00
|
|
|
VK_ERROR(vk, "vkCreateBuffer failed: '%s'", vk_result_string(ret));
|
2020-10-05 22:30:31 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the memory backing up the buffer handle.
|
|
|
|
VkMemoryRequirements mem_reqs;
|
|
|
|
vk->vkGetBufferMemoryRequirements(vk->device, //
|
|
|
|
buffer, //
|
|
|
|
&mem_reqs); //
|
|
|
|
|
|
|
|
// Find a memory type index that fits the properties of the buffer.
|
|
|
|
uint32_t memory_type_index = 0;
|
2021-11-19 20:33:40 +00:00
|
|
|
if (!vk_get_memory_type(vk, //
|
|
|
|
mem_reqs.memoryTypeBits, //
|
|
|
|
memory_property_flags, //
|
|
|
|
&memory_type_index)) { //
|
|
|
|
VK_ERROR(vk, "vk_get_memory_type failed: 'false'\n\tFailed to find a matching memory type.");
|
|
|
|
ret = VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
|
|
|
goto err_buffer;
|
|
|
|
}
|
2020-10-05 22:30:31 +00:00
|
|
|
|
|
|
|
VkMemoryAllocateInfo mem_alloc = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
|
|
.allocationSize = mem_reqs.size,
|
|
|
|
.memoryTypeIndex = memory_type_index,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkDeviceMemory memory = VK_NULL_HANDLE;
|
|
|
|
ret = vk->vkAllocateMemory(vk->device, //
|
|
|
|
&mem_alloc, //
|
|
|
|
NULL, //
|
|
|
|
&memory); //
|
|
|
|
if (ret != VK_SUCCESS) {
|
2021-01-14 14:13:48 +00:00
|
|
|
VK_ERROR(vk, "vkAllocateMemory failed: '%s'", vk_result_string(ret));
|
2020-10-05 22:30:31 +00:00
|
|
|
goto err_buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Attach the memory to the buffer object
|
|
|
|
ret = vk->vkBindBufferMemory(vk->device, //
|
|
|
|
buffer, // buffer
|
|
|
|
memory, // memory
|
|
|
|
0); // memoryOffset
|
|
|
|
if (ret != VK_SUCCESS) {
|
2021-01-14 14:13:48 +00:00
|
|
|
VK_ERROR(vk, "vkBindBufferMemory failed: '%s'", vk_result_string(ret));
|
2020-10-05 22:30:31 +00:00
|
|
|
goto err_memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_memory = memory;
|
|
|
|
*out_buffer = buffer;
|
|
|
|
*out_alignment = mem_reqs.alignment;
|
|
|
|
*out_allocation_size = mem_alloc.allocationSize;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
|
|
|
|
err_memory:
|
|
|
|
vk->vkFreeMemory(vk->device, memory, NULL);
|
|
|
|
|
|
|
|
err_buffer:
|
|
|
|
vk->vkDestroyBuffer(vk->device, buffer, NULL);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* 'Exported' functions.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
comp_buffer_init(struct vk_bundle *vk,
|
|
|
|
struct comp_buffer *buffer,
|
|
|
|
VkBufferUsageFlags usage_flags,
|
|
|
|
VkMemoryPropertyFlags memory_property_flags,
|
|
|
|
VkDeviceSize size)
|
|
|
|
{
|
|
|
|
return create_buffer(vk, //
|
|
|
|
usage_flags, // usage_flags
|
|
|
|
memory_property_flags, // memory_property_flags
|
|
|
|
size, // size
|
|
|
|
&buffer->buffer, // out_buffer
|
|
|
|
&buffer->memory, // out_memory
|
|
|
|
&buffer->alignment, // out_alignment
|
|
|
|
&buffer->allocation_size); // out_allocation_size
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
comp_buffer_close(struct vk_bundle *vk, struct comp_buffer *buffer)
|
|
|
|
{
|
|
|
|
if (buffer->buffer != VK_NULL_HANDLE) {
|
|
|
|
vk->vkDestroyBuffer(vk->device, buffer->buffer, NULL);
|
|
|
|
}
|
|
|
|
if (buffer->memory != VK_NULL_HANDLE) {
|
|
|
|
vk->vkFreeMemory(vk->device, buffer->memory, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
U_ZERO(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
comp_buffer_map(struct vk_bundle *vk, struct comp_buffer *buffer)
|
|
|
|
{
|
|
|
|
return vk->vkMapMemory(vk->device, //
|
|
|
|
buffer->memory, // memory
|
|
|
|
0, // offset
|
|
|
|
VK_WHOLE_SIZE, // size
|
|
|
|
0, // flags
|
|
|
|
&buffer->mapped); // ppData
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
comp_buffer_unmap(struct vk_bundle *vk, struct comp_buffer *buffer)
|
|
|
|
{
|
|
|
|
if (buffer->mapped != NULL) {
|
|
|
|
vk->vkUnmapMemory(vk->device, buffer->memory);
|
|
|
|
buffer->mapped = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
2021-01-14 14:13:48 +00:00
|
|
|
comp_buffer_map_and_write(struct vk_bundle *vk, struct comp_buffer *buffer, void *data, VkDeviceSize size)
|
2020-10-05 22:30:31 +00:00
|
|
|
{
|
|
|
|
VkResult ret;
|
|
|
|
|
|
|
|
if (size > buffer->allocation_size) {
|
|
|
|
VK_ERROR(vk, "Trying to write more the buffer size!");
|
|
|
|
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buffer->mapped == NULL) {
|
|
|
|
ret = comp_buffer_map(vk, buffer);
|
|
|
|
if (ret != VK_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(buffer->mapped, data, size);
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
2021-01-14 14:13:48 +00:00
|
|
|
comp_buffer_write(struct vk_bundle *vk, struct comp_buffer *buffer, void *data, VkDeviceSize size)
|
2020-10-05 22:30:31 +00:00
|
|
|
{
|
|
|
|
if (size > buffer->allocation_size) {
|
|
|
|
VK_ERROR(vk, "Trying to write more the buffer size!");
|
|
|
|
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool mapped = buffer->mapped != NULL;
|
|
|
|
if (!mapped) {
|
|
|
|
VkResult ret = comp_buffer_map(vk, buffer);
|
|
|
|
if (ret != VK_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(buffer->mapped, data, size);
|
|
|
|
|
|
|
|
// Only unmap if we did the mapping.
|
|
|
|
if (!mapped) {
|
|
|
|
comp_buffer_unmap(vk, buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|