summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2017-09-20 10:00:48 -0400
committerMatthias Clasen <mclasen@redhat.com>2017-09-20 23:26:14 -0400
commit5ee5af9bc8b9c29e67d580b89d67fb5ac5a71f3e (patch)
tree69ddb3a41988610c6854bf25af3369a367ecc617
parent6dbec5e4fc644c9932e76b3845d898418ae3f619 (diff)
downloadgtk+-5ee5af9bc8b9c29e67d580b89d67fb5ac5a71f3e.tar.gz
vulkan: Add an upload_region api to GskVulkanImage
This will let us update larger textures incrementally. Sadly, it does not work yet.
-rw-r--r--gsk/gskvulkanimage.c98
-rw-r--r--gsk/gskvulkanimageprivate.h8
2 files changed, 106 insertions, 0 deletions
diff --git a/gsk/gskvulkanimage.c b/gsk/gskvulkanimage.c
index 11411fca0b..79f808bb70 100644
--- a/gsk/gskvulkanimage.c
+++ b/gsk/gskvulkanimage.c
@@ -649,6 +649,104 @@ gsk_vulkan_image_download (GskVulkanImage *self,
return texture;
}
+void
+gsk_vulkan_image_upload_region (GskVulkanImage *self,
+ GskVulkanUploader *uploader,
+ guchar *data,
+ gsize width,
+ gsize height,
+ gsize stride,
+ gsize x,
+ gsize y)
+{
+ GskVulkanBuffer *staging;
+ guchar *mem;
+
+ staging = gsk_vulkan_buffer_new_staging (uploader->vulkan, width * height * 4);
+ mem = gsk_vulkan_buffer_map (staging);
+
+ if (stride == width * 4)
+ {
+ memcpy (mem, data, stride * height);
+ }
+ else
+ {
+ for (gsize i = 0; i < height; i++)
+ {
+ memcpy (mem + i * width * 4, data + i * stride, width * 4);
+ }
+ }
+
+ gsk_vulkan_buffer_unmap (staging);
+
+ gsk_vulkan_uploader_add_image_barrier (uploader,
+ FALSE,
+ &(VkImageMemoryBarrier) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ .srcAccessMask = VK_ACCESS_HOST_WRITE_BIT,
+ .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+ .oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED,
+ .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_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
+ }
+ });
+
+ vkCmdCopyBufferToImage (gsk_vulkan_uploader_get_copy_buffer (uploader),
+ gsk_vulkan_buffer_get_buffer (staging),
+ 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 = { x, y, 0 },
+ .imageExtent = {
+ .width = width,
+ .height = height,
+ .depth = 1
+ }
+ }
+ });
+
+ gsk_vulkan_uploader_add_image_barrier (uploader,
+ TRUE,
+ &(VkImageMemoryBarrier) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+ .dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
+ .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ .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
+ }
+ });
+
+ uploader->staging_buffer_free_list = g_slist_prepend (uploader->staging_buffer_free_list, staging);
+
+ gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
+}
+
static void
gsk_vulkan_image_finalize (GObject *object)
{
diff --git a/gsk/gskvulkanimageprivate.h b/gsk/gskvulkanimageprivate.h
index feade292e8..4a8cb223f1 100644
--- a/gsk/gskvulkanimageprivate.h
+++ b/gsk/gskvulkanimageprivate.h
@@ -31,6 +31,14 @@ GskVulkanImage * gsk_vulkan_image_new_from_data (GskVulk
gsize width,
gsize height,
gsize stride);
+void gsk_vulkan_image_upload_region (GskVulkanImage *image,
+ GskVulkanUploader *uploader,
+ guchar *data,
+ gsize width,
+ gsize height,
+ gsize stride,
+ gsize x,
+ gsize y);
GskVulkanImage * gsk_vulkan_image_new_for_framebuffer (GdkVulkanContext *context,
gsize width,
gsize height);