vulkan: Split out command pool

This way we can pass the command pool around.
And that allows us to allocate and submitcustom buffers.
And that is necessary to make staging images work.
This commit is contained in:
Benjamin Otte 2016-12-16 06:10:24 +01:00
parent ba7ac637bc
commit 85559d1fd9
10 changed files with 210 additions and 117 deletions

View File

@ -25,6 +25,7 @@ noinst_LTLIBRARIES =
if HAVE_VULKAN
gsk_private_vulan_source_h = \
gskvulkanbufferprivate.h \
gskvulkancommandpoolprivate.h \
gskvulkanimageprivate.h \
gskvulkanmemoryprivate.h \
gskvulkanpipelineprivate.h \
@ -35,6 +36,7 @@ gsk_private_vulan_source_h = \
gskvulkanshaderprivate.h
gsk_private_vulkan_source_c = \
gskvulkanbuffer.c \
gskvulkancommandpool.c \
gskvulkanimage.c \
gskvulkanmemory.c \
gskvulkanpipeline.c \

104
gsk/gskvulkancommandpool.c Normal file
View File

@ -0,0 +1,104 @@
#include "config.h"
#include "gskvulkancommandpoolprivate.h"
#include "gskvulkanpipelineprivate.h"
struct _GskVulkanCommandPool
{
GdkVulkanContext *vulkan;
VkCommandPool vk_command_pool;
};
GskVulkanCommandPool *
gsk_vulkan_command_pool_new (GdkVulkanContext *context)
{
GskVulkanCommandPool *self;
self = g_slice_new0 (GskVulkanCommandPool);
self->vulkan = g_object_ref (context);
GSK_VK_CHECK (vkCreateCommandPool, gdk_vulkan_context_get_device (context),
&(const VkCommandPoolCreateInfo) {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.queueFamilyIndex = gdk_vulkan_context_get_queue_family_index (self->vulkan),
.flags = 0
},
NULL,
&self->vk_command_pool);
return self;
}
void
gsk_vulkan_command_pool_free (GskVulkanCommandPool *self)
{
vkDestroyCommandPool (gdk_vulkan_context_get_device (self->vulkan),
self->vk_command_pool,
NULL);
g_slice_free (GskVulkanCommandPool, self);
}
void
gsk_vulkan_command_pool_reset (GskVulkanCommandPool *self)
{
GSK_VK_CHECK (vkResetCommandPool, gdk_vulkan_context_get_device (self->vulkan),
self->vk_command_pool,
0);
}
VkCommandBuffer
gsk_vulkan_command_pool_get_buffer (GskVulkanCommandPool *self)
{
VkCommandBuffer command_buffer;
GSK_VK_CHECK (vkAllocateCommandBuffers, gdk_vulkan_context_get_device (self->vulkan),
&(VkCommandBufferAllocateInfo) {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = self->vk_command_pool,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
},
&command_buffer);
GSK_VK_CHECK (vkBeginCommandBuffer, command_buffer,
&(VkCommandBufferBeginInfo) {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = 0
});
return command_buffer;
}
void
gsk_vulkan_command_pool_submit_buffer (GskVulkanCommandPool *self,
VkCommandBuffer command_buffer,
VkFence fence)
{
GSK_VK_CHECK (vkEndCommandBuffer, command_buffer);
GSK_VK_CHECK (vkQueueSubmit, gdk_vulkan_context_get_queue (self->vulkan),
1,
&(VkSubmitInfo) {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.waitSemaphoreCount = 1,
.pWaitSemaphores = (VkSemaphore[1]) {
gdk_vulkan_context_get_draw_semaphore (self->vulkan)
},
.pWaitDstStageMask = (VkPipelineStageFlags []) {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
},
.commandBufferCount = 1,
.pCommandBuffers = (VkCommandBuffer[1]) {
command_buffer
},
.signalSemaphoreCount = 1,
.pSignalSemaphores = (VkSemaphore[1]) {
gdk_vulkan_context_get_draw_semaphore (self->vulkan)
}
},
fence);
}

View File

@ -0,0 +1,22 @@
#ifndef __GSK_VULKAN_COMMAND_POOL_PRIVATE_H__
#define __GSK_VULKAN_COMMAND_POOL_PRIVATE_H__
#include <gdk/gdk.h>
G_BEGIN_DECLS
typedef struct _GskVulkanCommandPool GskVulkanCommandPool;
GskVulkanCommandPool * gsk_vulkan_command_pool_new (GdkVulkanContext *context);
void gsk_vulkan_command_pool_free (GskVulkanCommandPool *self);
void gsk_vulkan_command_pool_reset (GskVulkanCommandPool *self);
VkCommandBuffer gsk_vulkan_command_pool_get_buffer (GskVulkanCommandPool *self);
void gsk_vulkan_command_pool_submit_buffer (GskVulkanCommandPool *self,
VkCommandBuffer buffer,
VkFence fence);
G_END_DECLS
#endif /* __GSK_VULKAN_COMMAND_POOL_PRIVATE_H__ */

View File

@ -139,15 +139,16 @@ gsk_vulkan_image_ensure_view (GskVulkanImage *self,
}
GskVulkanImage *
gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext *context,
VkCommandBuffer command_buffer,
guchar *data,
gsize width,
gsize height,
gsize stride)
gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext *context,
GskVulkanCommandPool *command_pool,
guchar *data,
gsize width,
gsize height,
gsize stride)
{
GskVulkanImage *self;
GskVulkanBuffer *staging;
VkCommandBuffer command_buffer;
guchar *mem;
staging = gsk_vulkan_buffer_new_staging (context, width * height * 4);
@ -174,6 +175,8 @@ gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext *context,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
command_buffer = gsk_vulkan_command_pool_get_buffer (command_pool);
vkCmdPipelineBarrier (command_buffer,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
@ -249,6 +252,8 @@ gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext *context,
}
});
gsk_vulkan_command_pool_submit_buffer (command_pool, command_buffer, VK_NULL_HANDLE);
/* XXX: Is this okay or do we need to keep the staging image around until the commands execute */
gsk_vulkan_buffer_free (staging);
@ -258,14 +263,15 @@ gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext *context,
}
GskVulkanImage *
gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext *context,
VkCommandBuffer command_buffer,
guchar *data,
gsize width,
gsize height,
gsize stride)
gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext *context,
GskVulkanCommandPool *command_pool,
guchar *data,
gsize width,
gsize height,
gsize stride)
{
GskVulkanImage *self, *staging;
VkCommandBuffer command_buffer;
staging = gsk_vulkan_image_new (context,
width,
@ -283,6 +289,8 @@ gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext *context,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
command_buffer = gsk_vulkan_command_pool_get_buffer (command_pool);
vkCmdPipelineBarrier (command_buffer,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
@ -380,6 +388,8 @@ gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext *context,
}
});
gsk_vulkan_command_pool_submit_buffer (command_pool, command_buffer, VK_NULL_HANDLE);
/* XXX: Is this okay or do we need to keep the staging image around until the commands execute */
g_object_unref (staging);
@ -389,15 +399,18 @@ gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext *context,
}
GskVulkanImage *
gsk_vulkan_image_new_from_data_directly (GdkVulkanContext *context,
VkCommandBuffer command_buffer,
guchar *data,
gsize width,
gsize height,
gsize stride)
gsk_vulkan_image_new_from_data_directly (GdkVulkanContext *context,
GskVulkanCommandPool *command_pool,
guchar *data,
gsize width,
gsize height,
gsize stride)
{
VkCommandBuffer command_buffer;
GskVulkanImage *self;
command_buffer = gsk_vulkan_command_pool_get_buffer (command_pool);
self = gsk_vulkan_image_new (context,
width,
height,
@ -433,25 +446,27 @@ gsk_vulkan_image_new_from_data_directly (GdkVulkanContext *context,
}
});
gsk_vulkan_command_pool_submit_buffer (command_pool, command_buffer, VK_NULL_HANDLE);
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_SRGB);
return 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 (GdkVulkanContext *context,
GskVulkanCommandPool *command_pool,
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 (context, command_buffer, data, width, height, stride);
return gsk_vulkan_image_new_from_data_via_staging_buffer (context, command_pool, data, width, height, stride);
if (GSK_RENDER_MODE_CHECK (STAGING_IMAGE))
return gsk_vulkan_image_new_from_data_via_staging_image (context, command_buffer, data, width, height, stride);
return gsk_vulkan_image_new_from_data_via_staging_image (context, command_pool, data, width, height, stride);
else
return gsk_vulkan_image_new_from_data_directly (context, command_buffer, data, width, height, stride);
return gsk_vulkan_image_new_from_data_directly (context, command_pool, data, width, height, stride);
}
GskVulkanImage *

View File

@ -3,6 +3,8 @@
#include <gdk/gdk.h>
#include "gsk/gskvulkancommandpoolprivate.h"
G_BEGIN_DECLS
#define GSK_TYPE_VULKAN_IMAGE (gsk_vulkan_image_get_type ())
@ -15,7 +17,7 @@ GskVulkanImage * gsk_vulkan_image_new_for_swapchain (GdkVulk
gsize width,
gsize height);
GskVulkanImage * gsk_vulkan_image_new_from_data (GdkVulkanContext *context,
VkCommandBuffer command_buffer,
GskVulkanCommandPool *pool,
guchar *data,
gsize width,
gsize height,

View File

@ -4,6 +4,7 @@
#include "gskrendererprivate.h"
#include "gskvulkanbufferprivate.h"
#include "gskvulkancommandpoolprivate.h"
#include "gskvulkanpipelineprivate.h"
#include "gskvulkanrenderpassprivate.h"
@ -24,7 +25,7 @@ struct _GskVulkanRender
VkRect2D scissor;
GHashTable *framebuffers;
VkCommandPool command_pool;
GskVulkanCommandPool *command_pool;
VkFence fence;
VkRenderPass render_pass;
GskVulkanPipelineLayout *layout;
@ -36,8 +37,6 @@ struct _GskVulkanRender
gsize n_descriptor_sets;
GskVulkanPipeline *pipelines[GSK_VULKAN_N_PIPELINES];
VkCommandBuffer command_buffer;
GskVulkanImage *target;
GSList *render_passes;
@ -87,15 +86,7 @@ gsk_vulkan_render_new (GskRenderer *renderer,
device = gdk_vulkan_context_get_device (self->vulkan);
GSK_VK_CHECK (vkCreateCommandPool, device,
&(const VkCommandPoolCreateInfo) {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.queueFamilyIndex = gdk_vulkan_context_get_queue_family_index (self->vulkan),
.flags = 0
},
NULL,
&self->command_pool);
self->command_pool = gsk_vulkan_command_pool_new (self->vulkan);
GSK_VK_CHECK (vkCreateFence, device,
&(VkFenceCreateInfo) {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
@ -244,7 +235,7 @@ gsk_vulkan_render_upload (GskVulkanRender *self)
for (l = self->render_passes; l; l = l->next)
{
gsk_vulkan_render_pass_upload (l->data, self, self->command_buffer);
gsk_vulkan_render_pass_upload (l->data, self, self->command_pool);
}
}
@ -437,13 +428,16 @@ gsk_vulkan_render_draw (GskVulkanRender *self,
VkSampler sampler)
{
GskVulkanBuffer *buffer;
VkCommandBuffer command_buffer;
GSList *l;
gsk_vulkan_render_prepare_descriptor_sets (self, sampler);
command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
buffer = gsk_vulkan_render_collect_vertices (self);
vkCmdSetViewport (self->command_buffer,
vkCmdSetViewport (command_buffer,
0,
1,
&(VkViewport) {
@ -455,12 +449,12 @@ gsk_vulkan_render_draw (GskVulkanRender *self,
.maxDepth = 1
});
vkCmdSetScissor (self->command_buffer,
vkCmdSetScissor (command_buffer,
0,
1,
&self->scissor);
vkCmdBeginRenderPass (self->command_buffer,
vkCmdBeginRenderPass (command_buffer,
&(VkRenderPassBeginInfo) {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderPass = self->render_pass,
@ -476,7 +470,7 @@ gsk_vulkan_render_draw (GskVulkanRender *self,
},
VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindVertexBuffers (self->command_buffer,
vkCmdBindVertexBuffers (command_buffer,
0,
1,
(VkBuffer[1]) {
@ -486,38 +480,14 @@ gsk_vulkan_render_draw (GskVulkanRender *self,
for (l = self->render_passes; l; l = l->next)
{
gsk_vulkan_render_pass_draw (l->data, self, self->layout, self->command_buffer);
gsk_vulkan_render_pass_draw (l->data, self, self->layout, command_buffer);
}
vkCmdEndRenderPass (self->command_buffer);
vkCmdEndRenderPass (command_buffer);
gsk_vulkan_command_pool_submit_buffer (self->command_pool, command_buffer, self->fence);
gsk_vulkan_buffer_free (buffer);
}
void
gsk_vulkan_render_submit (GskVulkanRender *self)
{
GSK_VK_CHECK (vkEndCommandBuffer, self->command_buffer);
GSK_VK_CHECK (vkQueueSubmit, gdk_vulkan_context_get_queue (self->vulkan),
1,
&(VkSubmitInfo) {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.waitSemaphoreCount = 1,
.pWaitSemaphores = (VkSemaphore[1]) {
gdk_vulkan_context_get_draw_semaphore (self->vulkan)
},
.pWaitDstStageMask = (VkPipelineStageFlags []) {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
},
.commandBufferCount = 1,
.pCommandBuffers = &self->command_buffer,
.signalSemaphoreCount = 1,
.pSignalSemaphores = (VkSemaphore[1]) {
gdk_vulkan_context_get_draw_semaphore (self->vulkan)
}
},
self->fence);
if (GSK_RENDER_MODE_CHECK (SYNC))
{
@ -544,9 +514,8 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self)
GSK_VK_CHECK (vkResetFences, device,
1,
&self->fence);
GSK_VK_CHECK (vkResetCommandPool, device,
self->command_pool,
0);
gsk_vulkan_command_pool_reset (self->command_pool);
g_hash_table_remove_all (self->descriptor_set_indexes);
@ -602,9 +571,8 @@ gsk_vulkan_render_free (GskVulkanRender *self)
vkDestroyFence (device,
self->fence,
NULL);
vkDestroyCommandPool (device,
self->command_pool,
NULL);
gsk_vulkan_command_pool_free (self->command_pool);
g_slice_free (GskVulkanRender, self);
}
@ -619,30 +587,11 @@ void
gsk_vulkan_render_reset (GskVulkanRender *self,
GskVulkanImage *target)
{
VkDevice device;
gsk_vulkan_render_cleanup (self);
self->target = g_object_ref (target);
gsk_vulkan_render_compute_mvp (self);
device = gdk_vulkan_context_get_device (self->vulkan);
GSK_VK_CHECK (vkAllocateCommandBuffers, device,
&(VkCommandBufferAllocateInfo) {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = self->command_pool,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
},
&self->command_buffer);
GSK_VK_CHECK (vkBeginCommandBuffer, self->command_buffer,
&(VkCommandBufferBeginInfo) {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = 0
});
}
GskRenderer *

View File

@ -196,8 +196,6 @@ gsk_vulkan_renderer_render (GskRenderer *renderer,
gsk_vulkan_render_draw (render, self->sampler);
gsk_vulkan_render_submit (render);
#ifdef G_ENABLE_DEBUG
cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time);
gsk_profiler_timer_set (profiler, self->profile_timers.cpu_time, cpu_time);
@ -271,9 +269,9 @@ gsk_vulkan_renderer_clear_texture (gpointer p)
}
GskVulkanImage *
gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
GskTexture *texture,
VkCommandBuffer command_buffer)
gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
GskTexture *texture,
GskVulkanCommandPool *command_pool)
{
GskVulkanTextureData *data;
cairo_surface_t *surface;
@ -285,7 +283,7 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
surface = gsk_texture_download (texture);
image = gsk_vulkan_image_new_from_data (self->vulkan,
command_buffer,
command_pool,
cairo_image_surface_get_data (surface),
cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),

View File

@ -23,7 +23,7 @@ GType gsk_vulkan_renderer_get_type (void) G_GNUC_CONST;
GskVulkanImage * gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
GskTexture *texture,
VkCommandBuffer command_buffer);
GskVulkanCommandPool *command_pool);
G_END_DECLS

View File

@ -173,10 +173,10 @@ gsk_vulkan_render_pass_add (GskVulkanRenderPass *self,
}
static void
gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self,
GskVulkanOpRender *op,
GskVulkanRender *render,
VkCommandBuffer command_buffer)
gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self,
GskVulkanOpRender *op,
GskVulkanRender *render,
GskVulkanCommandPool *command_pool)
{
graphene_rect_t bounds;
cairo_surface_t *surface;
@ -195,7 +195,7 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self,
cairo_destroy (cr);
op->source = gsk_vulkan_image_new_from_data (self->vulkan,
command_buffer,
command_pool,
cairo_image_surface_get_data (surface),
cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
@ -207,9 +207,9 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self,
}
void
gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
GskVulkanRender *render,
VkCommandBuffer command_buffer)
gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
GskVulkanRender *render,
GskVulkanCommandPool *command_pool)
{
GskVulkanOp *op;
guint i;
@ -221,14 +221,14 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
switch (op->type)
{
case GSK_VULKAN_OP_FALLBACK:
gsk_vulkan_render_pass_upload_fallback (self, &op->render, render, command_buffer);
gsk_vulkan_render_pass_upload_fallback (self, &op->render, render, command_pool);
break;
case GSK_VULKAN_OP_SURFACE:
{
cairo_surface_t *surface = gsk_cairo_node_get_surface (op->render.node);
op->render.source = gsk_vulkan_image_new_from_data (self->vulkan,
command_buffer,
command_pool,
cairo_image_surface_get_data (surface),
cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
@ -241,7 +241,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
{
op->render.source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
gsk_texture_node_get_texture (op->render.node),
command_buffer);
command_pool);
gsk_vulkan_render_add_cleanup_image (render, op->render.source);
}
break;

View File

@ -4,6 +4,7 @@
#include <gdk/gdk.h>
#include <gsk/gskrendernode.h>
#include "gsk/gskvulkancommandpoolprivate.h"
#include "gsk/gskvulkanrenderprivate.h"
G_BEGIN_DECLS
@ -20,7 +21,7 @@ void gsk_vulkan_render_pass_add (GskVulk
void gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
GskVulkanRender *render,
VkCommandBuffer command_buffer);
GskVulkanCommandPool *command_pool);
gsize gsk_vulkan_render_pass_count_vertices (GskVulkanRenderPass *self);
gsize gsk_vulkan_render_pass_collect_vertices (GskVulkanRenderPass *self,