summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2017-09-21 13:42:57 -0400
committerMatthias Clasen <mclasen@redhat.com>2017-09-21 13:42:57 -0400
commit64322a2c417dfed54e4948bf252864455a90b63e (patch)
tree5670de1eaea669b447f45c63da99f5a7853b8d5c
parent9a1460218c04c53a13197d65c80913c6df340c8c (diff)
downloadgtk+-64322a2c417dfed54e4948bf252864455a90b63e.tar.gz
vulkan: Add an api to update multiple image regions
Instead of doing multiple copy commands with a tiny buffer for each glyph, we can just batch them all together. This also avoids the issue of creating multiple barriers for the same image.
-rw-r--r--gsk/gskvulkanimage.c89
-rw-r--r--gsk/gskvulkanimageprivate.h14
2 files changed, 77 insertions, 26 deletions
diff --git a/gsk/gskvulkanimage.c b/gsk/gskvulkanimage.c
index 3e365516c5..5ab2ae6d6e 100644
--- a/gsk/gskvulkanimage.c
+++ b/gsk/gskvulkanimage.c
@@ -148,8 +148,12 @@ gsk_vulkan_uploader_upload (GskVulkanUploader *self)
command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
vkCmdPipelineBarrier (command_buffer,
+#if 0
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+#endif
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
0,
0, NULL,
self->before_buffer_barriers->len, (VkBufferMemoryBarrier *) self->before_buffer_barriers->data,
@@ -164,8 +168,12 @@ gsk_vulkan_uploader_upload (GskVulkanUploader *self)
{
VkCommandBuffer command_buffer = gsk_vulkan_uploader_get_copy_buffer (self);
vkCmdPipelineBarrier (command_buffer,
+#if 0
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+#endif
+ VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
+ VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
0,
0, NULL,
self->after_buffer_barriers->len, (VkBufferMemoryBarrier *) self->after_buffer_barriers->data,
@@ -664,22 +672,67 @@ gsk_vulkan_image_upload_region (GskVulkanImage *self,
gsize x,
gsize y)
{
+ gsk_vulkan_image_upload_regions (self, uploader, 1, (GskImageRegion[1]) {
+ {
+ .data = data,
+ .width = width,
+ .height = height,
+ .stride = stride,
+ .x = x,
+ .y = y
+ } });
+}
+
+void
+gsk_vulkan_image_upload_regions (GskVulkanImage *self,
+ GskVulkanUploader *uploader,
+ guint num_regions,
+ GskImageRegion *regions)
+{
GskVulkanBuffer *staging;
guchar *mem;
+ guchar *m;
+ gsize size;
+ gsize offset;
+ VkBufferImageCopy *bufferImageCopy;
+
+ size = 0;
+ for (int i = 0; i < num_regions; i++)
+ size += regions[i].width * regions[i].height * 4;
- staging = gsk_vulkan_buffer_new_staging (uploader->vulkan, width * height * 4);
+ staging = gsk_vulkan_buffer_new_staging (uploader->vulkan, size);
mem = gsk_vulkan_buffer_map (staging);
- if (stride == width * 4)
- {
- memcpy (mem, data, stride * height);
- }
- else
+ bufferImageCopy = alloca (sizeof (VkBufferImageCopy) * num_regions);
+ memset (bufferImageCopy, 0, sizeof (VkBufferImageCopy) * num_regions);
+
+ offset = 0;
+ for (int i = 0; i < num_regions; i++)
{
- for (gsize i = 0; i < height; i++)
+ m = mem + offset;
+ if (regions[i].stride == regions[i].width * 4)
{
- memcpy (mem + i * width * 4, data + i * stride, width * 4);
+ memcpy (m, regions[i].data, regions[i].stride * regions[i].height);
}
+ else
+ {
+ for (gsize r = 0; r < regions[i].height; i++)
+ memcpy (m + r * regions[i].width * 4, regions[i].data + r * regions[i].stride, regions[i].width * 4);
+ }
+
+ bufferImageCopy[i].bufferOffset = offset;
+ bufferImageCopy[i].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ bufferImageCopy[i].imageSubresource.mipLevel = 0;
+ bufferImageCopy[i].imageSubresource.baseArrayLayer = 0;
+ bufferImageCopy[i].imageSubresource.layerCount = 1;
+ bufferImageCopy[i].imageOffset.x = regions[i].x;
+ bufferImageCopy[i].imageOffset.y = regions[i].y;
+ bufferImageCopy[i].imageOffset.z = 0;
+ bufferImageCopy[i].imageExtent.width = regions[i].width;
+ bufferImageCopy[i].imageExtent.height = regions[i].height;
+ bufferImageCopy[i].imageExtent.depth = 1;
+
+ offset += regions[i].width * regions[i].height * 4;
}
gsk_vulkan_buffer_unmap (staging);
@@ -694,24 +747,8 @@ gsk_vulkan_image_upload_region (GskVulkanImage *self,
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
- }
- }
- });
+ num_regions,
+ bufferImageCopy);
gsk_vulkan_uploader_add_image_barrier (uploader,
TRUE,
diff --git a/gsk/gskvulkanimageprivate.h b/gsk/gskvulkanimageprivate.h
index 5f2cdf77c6..3aa0263417 100644
--- a/gsk/gskvulkanimageprivate.h
+++ b/gsk/gskvulkanimageprivate.h
@@ -39,6 +39,20 @@ void gsk_vulkan_image_upload_region (GskVulk
gsize stride,
gsize x,
gsize y);
+
+typedef struct {
+ guchar *data;
+ gsize width;
+ gsize height;
+ gsize stride;
+ gsize x;
+ gsize y;
+} GskImageRegion;
+
+void gsk_vulkan_image_upload_regions (GskVulkanImage *image,
+ GskVulkanUploader *uploader,
+ guint num_regions,
+ GskImageRegion *regions);
GskVulkanImage * gsk_vulkan_image_new_for_framebuffer (GdkVulkanContext *context,
gsize width,
gsize height);