mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 06:00:22 +00:00
vulkan: Upload image data directly
Instead of using a staging iamge, we require the final image to be linearly allocated and have host-visible memory. This improves performance quite a bit. The old code is still there and can be enabled with a simple change to a #define in gskvulkanimage.h
This commit is contained in:
parent
3c4b952256
commit
13b53656ea
@ -65,27 +65,19 @@ gsk_vulkan_image_new (GdkVulkanContext *context,
|
||||
return self;
|
||||
}
|
||||
|
||||
static GskVulkanImage *
|
||||
gsk_vulkan_image_new_staging (GdkVulkanContext *context,
|
||||
guchar *data,
|
||||
gsize width,
|
||||
gsize height,
|
||||
gsize stride)
|
||||
static void
|
||||
gsk_vulkan_image_upload_data (GskVulkanImage *self,
|
||||
guchar *data,
|
||||
gsize width,
|
||||
gsize height,
|
||||
gsize data_stride)
|
||||
{
|
||||
VkMemoryRequirements requirements;
|
||||
GskVulkanImage *self;
|
||||
guchar *mem;
|
||||
gsize mem_stride;
|
||||
|
||||
self = gsk_vulkan_image_new (context,
|
||||
width,
|
||||
height,
|
||||
VK_IMAGE_TILING_LINEAR,
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
guchar *mem;
|
||||
|
||||
mem_stride = width * 4;
|
||||
vkGetImageMemoryRequirements (gdk_vulkan_context_get_device (context),
|
||||
vkGetImageMemoryRequirements (gdk_vulkan_context_get_device (self->vulkan),
|
||||
self->vk_image,
|
||||
&requirements);
|
||||
if (mem_stride % requirements.alignment != 0)
|
||||
@ -93,21 +85,19 @@ gsk_vulkan_image_new_staging (GdkVulkanContext *context,
|
||||
|
||||
mem = gsk_vulkan_memory_map (self->memory);
|
||||
|
||||
if (stride == width * 4 && stride == mem_stride)
|
||||
if (data_stride == width * 4 && data_stride == mem_stride)
|
||||
{
|
||||
memcpy (mem, data, width * height * 4);
|
||||
memcpy (mem, data, data_stride * height);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (gsize i = 0; i < height; i++)
|
||||
{
|
||||
memcpy (mem + i * mem_stride, data + i * stride, width * 4);
|
||||
memcpy (mem + i * mem_stride, data + i * data_stride, width * 4);
|
||||
}
|
||||
}
|
||||
|
||||
gsk_vulkan_memory_unmap (self->memory);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -138,16 +128,23 @@ gsk_vulkan_image_ensure_view (GskVulkanImage *self)
|
||||
}
|
||||
|
||||
GskVulkanImage *
|
||||
gsk_vulkan_image_new_from_data (GdkVulkanContext *context,
|
||||
VkCommandBuffer command_buffer,
|
||||
guchar *data,
|
||||
gsize width,
|
||||
gsize height,
|
||||
gsize stride)
|
||||
gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext *context,
|
||||
VkCommandBuffer command_buffer,
|
||||
guchar *data,
|
||||
gsize width,
|
||||
gsize height,
|
||||
gsize stride)
|
||||
{
|
||||
GskVulkanImage *self, *staging;
|
||||
|
||||
staging = gsk_vulkan_image_new_staging (context, data, width, height, stride);
|
||||
staging = gsk_vulkan_image_new (context,
|
||||
width,
|
||||
height,
|
||||
VK_IMAGE_TILING_LINEAR,
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
||||
|
||||
gsk_vulkan_image_upload_data (staging, data, width, height, stride);
|
||||
|
||||
self = gsk_vulkan_image_new (context,
|
||||
width,
|
||||
@ -253,6 +250,7 @@ gsk_vulkan_image_new_from_data (GdkVulkanContext *context,
|
||||
}
|
||||
});
|
||||
|
||||
/* XXX: Is this okay or do we need to keep the staging image around until the commands execute */
|
||||
gsk_vulkan_image_free (staging);
|
||||
|
||||
gsk_vulkan_image_ensure_view (self);
|
||||
@ -260,6 +258,76 @@ gsk_vulkan_image_new_from_data (GdkVulkanContext *context,
|
||||
return self;
|
||||
}
|
||||
|
||||
GskVulkanImage *
|
||||
gsk_vulkan_image_new_from_data_directly (GdkVulkanContext *context,
|
||||
VkCommandBuffer command_buffer,
|
||||
guchar *data,
|
||||
gsize width,
|
||||
gsize height,
|
||||
gsize stride)
|
||||
{
|
||||
GskVulkanImage *self;
|
||||
|
||||
self = gsk_vulkan_image_new (context,
|
||||
width,
|
||||
height,
|
||||
VK_IMAGE_TILING_LINEAR,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
||||
|
||||
gsk_vulkan_image_upload_data (self, data, width, height, stride);
|
||||
|
||||
vkCmdPipelineBarrier (command_buffer,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
0,
|
||||
0, NULL,
|
||||
0, NULL,
|
||||
1, (VkImageMemoryBarrier[1]) {
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = self->vk_image,
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
gsk_vulkan_image_ensure_view (self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
GskVulkanImage *
|
||||
gsk_vulkan_image_new_from_data (GdkVulkanContext *context,
|
||||
VkCommandBuffer command_buffer,
|
||||
guchar *data,
|
||||
gsize width,
|
||||
gsize height,
|
||||
gsize stride)
|
||||
{
|
||||
switch (GSK_VULKAN_UPLOAD_IMAGE_DEFAULT)
|
||||
{
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
/* fall through */
|
||||
case GSK_VULKAN_UPLOAD_DIRECTLY:
|
||||
return gsk_vulkan_image_new_from_data_directly (context, command_buffer, data, width, height, stride);
|
||||
case GSK_VULKAN_UPLOAD_VIA_STAGING_IMAGE:
|
||||
return gsk_vulkan_image_new_from_data_via_staging_image (context, command_buffer, data, width, height, stride);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_image_free (GskVulkanImage *self)
|
||||
{
|
||||
|
@ -5,6 +5,14 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Modify here for benchmarking */
|
||||
#define GSK_VULKAN_UPLOAD_IMAGE_DEFAULT GSK_VULKAN_UPLOAD_DIRECTLY
|
||||
|
||||
typedef enum {
|
||||
GSK_VULKAN_UPLOAD_DIRECTLY,
|
||||
GSK_VULKAN_UPLOAD_VIA_STAGING_IMAGE
|
||||
} GstkVulkanImageUpload;
|
||||
|
||||
typedef struct _GskVulkanImage GskVulkanImage;
|
||||
|
||||
GskVulkanImage * gsk_vulkan_image_new_from_data (GdkVulkanContext *context,
|
||||
|
Loading…
Reference in New Issue
Block a user