From: Benjamin Otte Date: Wed, 14 Jun 2023 00:08:17 +0000 (+0200) Subject: vulkan: Add a new way to upload data into images X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~1^2~144^2~7 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=0c72f19cb1c16bc6affb7e85ed17db94ad3a64df;p=gtk4.git vulkan: Add a new way to upload data into images As an alternative to gsk_vulkan_image_new_from_data() that takes a given data and creates an image from it, add a 3 step process: gsk_vulkan_image_new_for_upload() gsk_vulkan_image_map_memory() /* put data into memory */ gsk_vulkan_image_unmap_memory() The benefit of this approach is that it potentially avoids a copy; instead of creating a buffer to pass and writing the data into it before then memcpy()ing it into the image, the data can be written straight into image memory. So far, only the staging buffer upload is implemented. There are also no users, those come in the next commit(s). --- diff --git a/gsk/vulkan/gskvulkanimage.c b/gsk/vulkan/gskvulkanimage.c index f10ad5a1d1..4e5ab9fd7c 100644 --- a/gsk/vulkan/gskvulkanimage.c +++ b/gsk/vulkan/gskvulkanimage.c @@ -565,6 +565,102 @@ gsk_vulkan_image_new_from_data (GskVulkanUploader *uploader, return gsk_vulkan_image_new_from_data_directly (uploader, data, width, height, stride); } +GskVulkanImage * +gsk_vulkan_image_new_for_upload (GskVulkanUploader *uploader, + gsize width, + gsize height) +{ + GskVulkanImage *self; + + self = gsk_vulkan_image_new (uploader->vulkan, + width, + height, + VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM); + + return self; +} + +void +gsk_vulkan_image_map_memory (GskVulkanImage *self, + GskVulkanUploader *uploader, + GskVulkanImageMap *map) +{ + gsize buffer_size = self->width * self->height * 4; + + g_assert (self->vk_image_layout == VK_IMAGE_LAYOUT_UNDEFINED || + self->vk_image_layout == VK_IMAGE_LAYOUT_PREINITIALIZED); + + map->staging_buffer = gsk_vulkan_buffer_new_staging (uploader->vulkan, buffer_size); + map->data = gsk_vulkan_buffer_map (map->staging_buffer); + map->stride = self->width * 4; +} + +void +gsk_vulkan_image_unmap_memory (GskVulkanImage *self, + GskVulkanUploader *uploader, + GskVulkanImageMap *map) +{ + gsk_vulkan_buffer_unmap (map->staging_buffer); + + gsk_vulkan_uploader_add_buffer_barrier (uploader, + FALSE, + &(VkBufferMemoryBarrier) { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + .srcAccessMask = VK_ACCESS_HOST_WRITE_BIT, + .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = gsk_vulkan_buffer_get_buffer (map->staging_buffer), + .offset = 0, + .size = VK_WHOLE_SIZE, + }); + + gsk_vulkan_uploader_add_image_barrier (uploader, + FALSE, + self, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_ACCESS_TRANSFER_WRITE_BIT); + + vkCmdCopyBufferToImage (gsk_vulkan_uploader_get_copy_buffer (uploader), + gsk_vulkan_buffer_get_buffer (map->staging_buffer), + self->vk_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + (VkBufferImageCopy[1]) { + { + .bufferOffset = 0, + .imageSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1 + }, + .imageOffset = { 0, 0, 0 }, + .imageExtent = { + .width = self->width, + .height = self->height, + .depth = 1 + } + } + }); + + gsk_vulkan_uploader_add_image_barrier (uploader, + TRUE, + self, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_ACCESS_SHADER_READ_BIT); + + uploader->staging_buffer_free_list = g_slist_prepend (uploader->staging_buffer_free_list, + map->staging_buffer); +} + GskVulkanImage * gsk_vulkan_image_new_for_swapchain (GdkVulkanContext *context, VkImage image, diff --git a/gsk/vulkan/gskvulkanimageprivate.h b/gsk/vulkan/gskvulkanimageprivate.h index 07f988bc66..fb311409b2 100644 --- a/gsk/vulkan/gskvulkanimageprivate.h +++ b/gsk/vulkan/gskvulkanimageprivate.h @@ -58,6 +58,27 @@ GskVulkanImage * gsk_vulkan_image_new_for_offscreen (GdkVulk GdkTexture * gsk_vulkan_image_download (GskVulkanImage *self, GskVulkanUploader *uploader); +typedef struct _GskVulkanImageMap GskVulkanImageMap; + +struct _GskVulkanImageMap +{ + guchar *data; + gsize stride; + + /* private */ + gpointer staging_buffer; +}; + +GskVulkanImage * gsk_vulkan_image_new_for_upload (GskVulkanUploader *uploader, + gsize width, + gsize height); +void gsk_vulkan_image_map_memory (GskVulkanImage *self, + GskVulkanUploader *uploader, + GskVulkanImageMap *map); +void gsk_vulkan_image_unmap_memory (GskVulkanImage *self, + GskVulkanUploader *uploader, + GskVulkanImageMap *map); + gsize gsk_vulkan_image_get_width (GskVulkanImage *self); gsize gsk_vulkan_image_get_height (GskVulkanImage *self); VkImage gsk_vulkan_image_get_image (GskVulkanImage *self);