gtk/gsk/gskvulkanimage.c
Matthias Clasen 85e4e0672a Add semaphores to the command buffer submit api
Allow to pass in semaphores to wait for before executing
and to signal after executing the command buffer. This
just exposes the capabilities of the underlying Vulkan
api. Update all callers to pass no semaphores, for now.

We will use this in the future.
2017-09-28 08:39:22 -04:00

821 lines
30 KiB
C

#include "config.h"
#include "gskvulkanimageprivate.h"
#include "gskvulkanbufferprivate.h"
#include "gskvulkanmemoryprivate.h"
#include "gskvulkanpipelineprivate.h"
#include <string.h>
struct _GskVulkanUploader
{
GdkVulkanContext *vulkan;
GskVulkanCommandPool *command_pool;
GArray *before_buffer_barriers;
GArray *before_image_barriers;
VkCommandBuffer copy_buffer;
GArray *after_buffer_barriers;
GArray *after_image_barriers;
GSList *staging_image_free_list;
GSList *staging_buffer_free_list;
};
struct _GskVulkanImage
{
GObject parent_instance;
GdkVulkanContext *vulkan;
gsize width;
gsize height;
VkImageUsageFlags vk_usage;
VkImage vk_image;
VkImageView vk_image_view;
VkImageLayout vk_image_layout;
VkAccessFlags vk_access;
GskVulkanMemory *memory;
};
G_DEFINE_TYPE (GskVulkanImage, gsk_vulkan_image, G_TYPE_OBJECT)
GskVulkanUploader *
gsk_vulkan_uploader_new (GdkVulkanContext *context,
GskVulkanCommandPool *command_pool)
{
GskVulkanUploader *self;
self = g_slice_new0 (GskVulkanUploader);
self->vulkan = g_object_ref (context);
self->command_pool = command_pool;
self->before_buffer_barriers = g_array_new (FALSE, FALSE, sizeof (VkBufferMemoryBarrier));
self->after_buffer_barriers = g_array_new (FALSE, FALSE, sizeof (VkBufferMemoryBarrier));
self->before_image_barriers = g_array_new (FALSE, FALSE, sizeof (VkImageMemoryBarrier));
self->after_image_barriers = g_array_new (FALSE, FALSE, sizeof (VkImageMemoryBarrier));
return self;
}
void
gsk_vulkan_uploader_free (GskVulkanUploader *self)
{
gsk_vulkan_uploader_reset (self);
g_array_unref (self->after_buffer_barriers);
g_array_unref (self->before_buffer_barriers);
g_array_unref (self->after_image_barriers);
g_array_unref (self->before_image_barriers);
g_object_unref (self->vulkan);
g_slice_free (GskVulkanUploader, self);
}
static void
gsk_vulkan_uploader_add_image_barrier (GskVulkanUploader *self,
gboolean after,
GskVulkanImage *image,
VkImageLayout new_layout,
VkAccessFlags new_access)
{
GArray *array;
VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = image->vk_access,
.dstAccessMask = new_access,
.oldLayout = image->vk_image_layout,
.newLayout = new_layout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image->vk_image,
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1
}
};
if (after)
array = self->after_image_barriers;
else
array = self->before_image_barriers;
g_array_append_val (array, barrier);
image->vk_image_layout = new_layout;
image->vk_access = new_access;
}
static void
gsk_vulkan_uploader_add_buffer_barrier (GskVulkanUploader *self,
gboolean after,
const VkBufferMemoryBarrier *barrier)
{
GArray *array;
if (after)
array = self->after_buffer_barriers;
else
array = self->before_buffer_barriers;
g_array_append_val (array, *barrier);
}
static VkCommandBuffer
gsk_vulkan_uploader_get_copy_buffer (GskVulkanUploader *self)
{
if (self->copy_buffer == VK_NULL_HANDLE)
self->copy_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
return self->copy_buffer;
}
void
gsk_vulkan_uploader_upload (GskVulkanUploader *self)
{
if (self->before_buffer_barriers->len > 0 || self->before_image_barriers->len > 0)
{
VkCommandBuffer command_buffer;
command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
vkCmdPipelineBarrier (command_buffer,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
0,
0, NULL,
self->before_buffer_barriers->len, (VkBufferMemoryBarrier *) self->before_buffer_barriers->data,
self->before_image_barriers->len, (VkImageMemoryBarrier *) self->before_image_barriers->data);
gsk_vulkan_command_pool_submit_buffer (self->command_pool, command_buffer, 0, NULL, 0, NULL, VK_NULL_HANDLE);
g_array_set_size (self->before_buffer_barriers, 0);
g_array_set_size (self->before_image_barriers, 0);
}
/* append these to existing buffer */
if (self->after_buffer_barriers->len > 0 || self->after_image_barriers->len > 0)
{
VkCommandBuffer command_buffer = gsk_vulkan_uploader_get_copy_buffer (self);
vkCmdPipelineBarrier (command_buffer,
VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
0,
0, NULL,
self->after_buffer_barriers->len, (VkBufferMemoryBarrier *) self->after_buffer_barriers->data,
self->after_image_barriers->len, (VkImageMemoryBarrier *) self->after_image_barriers->data);
g_array_set_size (self->after_buffer_barriers, 0);
g_array_set_size (self->after_image_barriers, 0);
}
if (self->copy_buffer != VK_NULL_HANDLE)
{
gsk_vulkan_command_pool_submit_buffer (self->command_pool, self->copy_buffer, 0, NULL, 0, NULL, VK_NULL_HANDLE);
self->copy_buffer = VK_NULL_HANDLE;
}
}
void
gsk_vulkan_uploader_reset (GskVulkanUploader *self)
{
g_array_set_size (self->before_image_barriers, 0);
self->copy_buffer = VK_NULL_HANDLE;
g_array_set_size (self->after_image_barriers, 0);
g_slist_free_full (self->staging_image_free_list, g_object_unref);
self->staging_image_free_list = NULL;
g_slist_free_full (self->staging_buffer_free_list, (GDestroyNotify) gsk_vulkan_buffer_free);
self->staging_buffer_free_list = NULL;
}
static GskVulkanImage *
gsk_vulkan_image_new (GdkVulkanContext *context,
gsize width,
gsize height,
VkImageTiling tiling,
VkImageUsageFlags usage,
VkImageLayout layout,
VkAccessFlags access,
VkMemoryPropertyFlags memory)
{
VkMemoryRequirements requirements;
GskVulkanImage *self;
self = g_object_new (GSK_TYPE_VULKAN_IMAGE, NULL);
self->vulkan = g_object_ref (context);
self->width = width;
self->height = height;
self->vk_usage = usage;
self->vk_image_layout = layout;
self->vk_access = access;
GSK_VK_CHECK (vkCreateImage, gdk_vulkan_context_get_device (context),
&(VkImageCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.flags = 0,
.imageType = VK_IMAGE_TYPE_2D,
.format = VK_FORMAT_B8G8R8A8_UNORM,
.extent = { width, height, 1 },
.mipLevels = 1,
.arrayLayers = 1,
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = tiling,
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.initialLayout = self->vk_image_layout,
},
NULL,
&self->vk_image);
vkGetImageMemoryRequirements (gdk_vulkan_context_get_device (context),
self->vk_image,
&requirements);
self->memory = gsk_vulkan_memory_new (context,
requirements.memoryTypeBits,
memory,
requirements.size);
GSK_VK_CHECK (vkBindImageMemory, gdk_vulkan_context_get_device (context),
self->vk_image,
gsk_vulkan_memory_get_device_memory (self->memory),
0);
return self;
}
static void
gsk_vulkan_image_upload_data (GskVulkanImage *self,
guchar *data,
gsize width,
gsize height,
gsize data_stride)
{
VkImageSubresource image_res;
VkSubresourceLayout image_layout;
gsize mem_stride;
guchar *mem;
image_res.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
image_res.mipLevel = 0;
image_res.arrayLayer = 0;
mem_stride = width * 4;
vkGetImageSubresourceLayout (gdk_vulkan_context_get_device (self->vulkan),
self->vk_image, &image_res, &image_layout);
mem = gsk_vulkan_memory_map (self->memory) + image_layout.offset;
if (image_layout.rowPitch == width * 4 && data_stride == mem_stride)
{
memcpy (mem, data, data_stride * height);
}
else
{
for (gsize i = 0; i < height; i++)
{
memcpy (mem + i * image_layout.rowPitch, data + i * data_stride, width * 4);
}
}
gsk_vulkan_memory_unmap (self->memory);
}
static void
gsk_vulkan_image_ensure_view (GskVulkanImage *self,
VkFormat format)
{
if (self->vk_image_view == VK_NULL_HANDLE)
GSK_VK_CHECK (vkCreateImageView, gdk_vulkan_context_get_device (self->vulkan),
&(VkImageViewCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.image = self->vk_image,
.viewType = VK_IMAGE_VIEW_TYPE_2D,
.format = format,
.components = {
.r = VK_COMPONENT_SWIZZLE_R,
.g = VK_COMPONENT_SWIZZLE_G,
.b = VK_COMPONENT_SWIZZLE_B,
.a = VK_COMPONENT_SWIZZLE_A,
},
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
},
NULL,
&self->vk_image_view);
}
static GskVulkanImage *
gsk_vulkan_image_new_from_data_via_staging_buffer (GskVulkanUploader *uploader,
guchar *data,
gsize width,
gsize height,
gsize stride)
{
GskVulkanImage *self;
GskVulkanBuffer *staging;
gsize buffer_size = width * height * 4;
guchar *mem;
staging = gsk_vulkan_buffer_new_staging (uploader->vulkan, buffer_size);
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_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(staging),
.offset = 0,
.size = buffer_size,
});
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_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 (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 = { 0, 0, 0 },
.imageExtent = {
.width = width,
.height = 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, staging);
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
return self;
}
static GskVulkanImage *
gsk_vulkan_image_new_from_data_via_staging_image (GskVulkanUploader *uploader,
guchar *data,
gsize width,
gsize height,
gsize stride)
{
GskVulkanImage *self, *staging;
staging = gsk_vulkan_image_new (uploader->vulkan,
width,
height,
VK_IMAGE_TILING_LINEAR,
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
VK_IMAGE_LAYOUT_PREINITIALIZED,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
gsk_vulkan_image_upload_data (staging, data, width, height, stride);
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_uploader_add_image_barrier (uploader,
FALSE,
staging,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_ACCESS_TRANSFER_READ_BIT);
gsk_vulkan_uploader_add_image_barrier (uploader,
FALSE,
self,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_ACCESS_TRANSFER_WRITE_BIT);
vkCmdCopyImage (gsk_vulkan_uploader_get_copy_buffer (uploader),
staging->vk_image,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
self->vk_image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&(VkImageCopy) {
.srcSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1
},
.srcOffset = { 0, 0, 0 },
.dstSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1
},
.dstOffset = { 0, 0, 0 },
.extent = {
.width = width,
.height = 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_image_free_list = g_slist_prepend (uploader->staging_image_free_list, staging);
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
return self;
}
static GskVulkanImage *
gsk_vulkan_image_new_from_data_directly (GskVulkanUploader *uploader,
guchar *data,
gsize width,
gsize height,
gsize stride)
{
GskVulkanImage *self;
self = gsk_vulkan_image_new (uploader->vulkan,
width,
height,
VK_IMAGE_TILING_LINEAR,
VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_LAYOUT_PREINITIALIZED,
VK_ACCESS_HOST_WRITE_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
gsk_vulkan_image_upload_data (self, data, width, height, stride);
gsk_vulkan_uploader_add_image_barrier (uploader,
TRUE,
self,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_ACCESS_SHADER_READ_BIT);
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
return self;
}
GskVulkanImage *
gsk_vulkan_image_new_from_data (GskVulkanUploader *uploader,
guchar *data,
gsize width,
gsize height,
gsize stride)
{
if (GSK_RENDER_MODE_CHECK (STAGING_BUFFER))
return gsk_vulkan_image_new_from_data_via_staging_buffer (uploader, data, width, height, stride);
if (GSK_RENDER_MODE_CHECK (STAGING_IMAGE))
return gsk_vulkan_image_new_from_data_via_staging_image (uploader, data, width, height, stride);
else
return gsk_vulkan_image_new_from_data_directly (uploader, data, width, height, stride);
}
GskVulkanImage *
gsk_vulkan_image_new_for_swapchain (GdkVulkanContext *context,
VkImage image,
VkFormat format,
gsize width,
gsize height)
{
GskVulkanImage *self;
self = g_object_new (GSK_TYPE_VULKAN_IMAGE, NULL);
self->vulkan = g_object_ref (context);
self->width = width;
self->height = height;
self->vk_image = image;
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
return self;
}
GskVulkanImage *
gsk_vulkan_image_new_for_framebuffer (GdkVulkanContext *context,
gsize width,
gsize height)
{
GskVulkanImage *self;
self = gsk_vulkan_image_new (context,
width,
height,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
return self;
}
GskVulkanImage *
gsk_vulkan_image_new_for_atlas (GdkVulkanContext *context,
gsize width,
gsize height)
{
GskVulkanImage *self;
self = gsk_vulkan_image_new (context,
width,
height,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
0,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
return self;
}
GskVulkanImage *
gsk_vulkan_image_new_for_texture (GdkVulkanContext *context,
gsize width,
gsize height)
{
GskVulkanImage *self;
self = gsk_vulkan_image_new (context,
width,
height,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
0,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
return self;
}
GskTexture *
gsk_vulkan_image_download (GskVulkanImage *self,
GskVulkanUploader *uploader)
{
GskVulkanBuffer *buffer;
GskTexture *texture;
guchar *mem;
gsk_vulkan_uploader_add_image_barrier (uploader,
FALSE,
self,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_ACCESS_TRANSFER_READ_BIT);
buffer = gsk_vulkan_buffer_new_download (self->vulkan, self->width * self->height * 4);
vkCmdCopyImageToBuffer (gsk_vulkan_uploader_get_copy_buffer (uploader),
self->vk_image,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
gsk_vulkan_buffer_get_buffer (buffer),
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_upload (uploader);
GSK_VK_CHECK (vkQueueWaitIdle, gdk_vulkan_context_get_queue (self->vulkan));
mem = gsk_vulkan_buffer_map (buffer);
texture = gsk_texture_new_for_data (mem, self->width, self->height, self->width * 4);
gsk_vulkan_buffer_unmap (buffer);
gsk_vulkan_buffer_free (buffer);
return texture;
}
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, size);
mem = gsk_vulkan_buffer_map (staging);
bufferImageCopy = alloca (sizeof (VkBufferImageCopy) * num_regions);
memset (bufferImageCopy, 0, sizeof (VkBufferImageCopy) * num_regions);
offset = 0;
for (int i = 0; i < num_regions; i++)
{
m = mem + offset;
if (regions[i].stride == regions[i].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);
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 (staging),
self->vk_image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
num_regions,
bufferImageCopy);
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, staging);
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
}
static void
gsk_vulkan_image_finalize (GObject *object)
{
GskVulkanImage *self = GSK_VULKAN_IMAGE (object);
if (self->vk_image_view != VK_NULL_HANDLE)
{
vkDestroyImageView (gdk_vulkan_context_get_device (self->vulkan),
self->vk_image_view,
NULL);
}
/* memory is NULL for for_swapchain() images, where we don't own
* the VkImage */
if (self->memory)
{
gsk_vulkan_memory_free (self->memory);
vkDestroyImage (gdk_vulkan_context_get_device (self->vulkan),
self->vk_image,
NULL);
}
g_object_unref (self->vulkan);
G_OBJECT_CLASS (gsk_vulkan_image_parent_class)->finalize (object);
}
static void
gsk_vulkan_image_class_init (GskVulkanImageClass *klass)
{
G_OBJECT_CLASS (klass)->finalize = gsk_vulkan_image_finalize;
}
static void
gsk_vulkan_image_init (GskVulkanImage *self)
{
}
gsize
gsk_vulkan_image_get_width (GskVulkanImage *self)
{
return self->width;
}
gsize
gsk_vulkan_image_get_height (GskVulkanImage *self)
{
return self->height;
}
VkImage
gsk_vulkan_image_get_image (GskVulkanImage *self)
{
return self->vk_image;
}
VkImageView
gsk_vulkan_image_get_image_view (GskVulkanImage *self)
{
return self->vk_image_view;
}