gtk/gsk/vulkan/gskvulkanbuffer.c
Benjamin Otte 70c9521cae vulkan: Put the vertex buffer into the render object
Renderpasses get recreated every frame, but we keep render objects
around. So if we keep the vertex buffer in the render object, we can
also keep it around and just reuse it.

Also, we only need one buffer for all the render passes, which is
another bonus.

The initial buffer size is chosen at 128kB. Maximized Nautilus,
gnome-text-editor with an open file and widget-factory take ~100kB when
doing a full redraw. Other apps are between 30-50kB usually.

So I chose a value that is not too big, but catches ~90% of cases.
2023-07-16 12:13:00 +02:00

123 lines
3.6 KiB
C

#include "config.h"
#include "gskvulkanbufferprivate.h"
#include "gskvulkanmemoryprivate.h"
#include "gskvulkanprivate.h"
struct _GskVulkanBuffer
{
GdkVulkanContext *vulkan;
gsize size;
VkBuffer vk_buffer;
GskVulkanMemory *memory;
};
static GskVulkanBuffer *
gsk_vulkan_buffer_new_internal (GdkVulkanContext *context,
gsize size,
VkBufferUsageFlags usage)
{
VkMemoryRequirements requirements;
GskVulkanBuffer *self;
self = g_new0 (GskVulkanBuffer, 1);
self->vulkan = g_object_ref (context);
self->size = size;
GSK_VK_CHECK (vkCreateBuffer, gdk_vulkan_context_get_device (context),
&(VkBufferCreateInfo) {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = size,
.flags = 0,
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
},
NULL,
&self->vk_buffer);
vkGetBufferMemoryRequirements (gdk_vulkan_context_get_device (context),
self->vk_buffer,
&requirements);
self->memory = gsk_vulkan_memory_new (context,
requirements.memoryTypeBits,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
requirements.size);
GSK_VK_CHECK (vkBindBufferMemory, gdk_vulkan_context_get_device (context),
self->vk_buffer,
gsk_vulkan_memory_get_device_memory (self->memory),
0);
return self;
}
GskVulkanBuffer *
gsk_vulkan_buffer_new (GdkVulkanContext *context,
gsize size)
{
return gsk_vulkan_buffer_new_internal (context, size,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
}
GskVulkanBuffer *
gsk_vulkan_buffer_new_storage (GdkVulkanContext *context,
gsize size)
{
return gsk_vulkan_buffer_new_internal (context, size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
}
GskVulkanBuffer *
gsk_vulkan_buffer_new_map (GdkVulkanContext *context,
gsize size,
GskVulkanMapMode mode)
{
return gsk_vulkan_buffer_new_internal (context,
size,
(mode & GSK_VULKAN_READ ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0) |
(mode & GSK_VULKAN_WRITE ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0));
}
void
gsk_vulkan_buffer_free (GskVulkanBuffer *self)
{
vkDestroyBuffer (gdk_vulkan_context_get_device (self->vulkan),
self->vk_buffer,
NULL);
gsk_vulkan_memory_free (self->memory);
g_object_unref (self->vulkan);
g_free (self);
}
VkBuffer
gsk_vulkan_buffer_get_buffer (GskVulkanBuffer *self)
{
return self->vk_buffer;
}
gsize
gsk_vulkan_buffer_get_size (GskVulkanBuffer *self)
{
return self->size;
}
guchar *
gsk_vulkan_buffer_map (GskVulkanBuffer *self)
{
return gsk_vulkan_memory_map (self->memory);
}
void
gsk_vulkan_buffer_unmap (GskVulkanBuffer *self)
{
gsk_vulkan_memory_unmap (self->memory);
}