Compare commits

...

6 Commits

Author SHA1 Message Date
Matthias Clasen
5a2cd3e582 vulkan: Move code around
Move most of the render-pass-specific code to GskVulkanRenderPass.
2017-09-27 23:22:31 -04:00
Matthias Clasen
5059ae00bf gsk: Add a profile counter for vulkan render passes
This will be useful once we have multiple render passes.
2017-09-27 23:15:53 -04:00
Matthias Clasen
59b4dec216 Implement multiple render passes 2017-09-27 23:15:53 -04:00
Matthias Clasen
0823c6de2f Add an api to get the vertex data for a render pass 2017-09-27 20:55:14 -04:00
Matthias Clasen
ff111b3f4f Add semaphores to the command buffer submit api
This will be used in the future.
Update all callers to pass no semaphores.
2017-09-27 20:12:24 -04:00
Matthias Clasen
337f96541f Add an api to create intermediate textures 2017-09-27 18:14:16 -04:00
10 changed files with 398 additions and 176 deletions

View File

@@ -10,6 +10,9 @@ void gsk_ensure_resources (void);
int pango_glyph_string_num_glyphs (PangoGlyphString *glyphs);
typedef struct _GskVulkanRender GskVulkanRender;
typedef struct _GskVulkanRenderPass GskVulkanRenderPass;
G_END_DECLS
#endif /* __GSK_PRIVATE_H__ */

View File

@@ -75,33 +75,36 @@ gsk_vulkan_command_pool_get_buffer (GskVulkanCommandPool *self)
void
gsk_vulkan_command_pool_submit_buffer (GskVulkanCommandPool *self,
VkCommandBuffer command_buffer,
gsize wait_semaphore_count,
VkSemaphore *wait_semaphores,
gsize signal_semaphore_count,
VkSemaphore *signal_semaphores,
VkFence fence)
{
VkPipelineStageFlags *wait_semaphore_flags = NULL;
GSK_VK_CHECK (vkEndCommandBuffer, command_buffer);
if (wait_semaphore_count > 0)
{
wait_semaphore_flags = alloca (sizeof (VkPipelineStageFlags) * wait_semaphore_count);
for (int i = 0; i < wait_semaphore_count; i++)
wait_semaphore_flags[i] = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
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,
},
.waitSemaphoreCount = wait_semaphore_count,
.pWaitSemaphores = wait_semaphores,
.pWaitDstStageMask = wait_semaphore_flags,
.commandBufferCount = 1,
.pCommandBuffers = (VkCommandBuffer[1]) {
command_buffer
},
/*
.signalSemaphoreCount = 1,
.pSignalSemaphores = (VkSemaphore[1]) {
gdk_vulkan_context_get_draw_semaphore (self->vulkan)
}
*/
.signalSemaphoreCount = signal_semaphore_count,
.pSignalSemaphores = signal_semaphores,
},
fence);
}

View File

@@ -15,6 +15,10 @@ void gsk_vulkan_command_pool_reset (GskVulk
VkCommandBuffer gsk_vulkan_command_pool_get_buffer (GskVulkanCommandPool *self);
void gsk_vulkan_command_pool_submit_buffer (GskVulkanCommandPool *self,
VkCommandBuffer buffer,
gsize wait_semaphore_count,
VkSemaphore *wait_semaphores,
gsize signal_semaphores_count,
VkSemaphore *signal_semaphores,
VkFence fence);
G_END_DECLS

View File

@@ -148,13 +148,13 @@ gsk_vulkan_uploader_upload (GskVulkanUploader *self)
command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
vkCmdPipelineBarrier (command_buffer,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
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, VK_NULL_HANDLE);
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);
}
@@ -176,7 +176,7 @@ gsk_vulkan_uploader_upload (GskVulkanUploader *self)
if (self->copy_buffer != VK_NULL_HANDLE)
{
gsk_vulkan_command_pool_submit_buffer (self->command_pool, 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;
}
}
@@ -604,6 +604,29 @@ gsk_vulkan_image_new_for_atlas (GdkVulkanContext *context,
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)
@@ -615,14 +638,14 @@ gsk_vulkan_image_download (GskVulkanImage *self,
gsk_vulkan_uploader_add_image_barrier (uploader,
FALSE,
self,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
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_DST_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
gsk_vulkan_buffer_get_buffer (buffer),
1,
(VkBufferImageCopy[1]) {

View File

@@ -51,6 +51,9 @@ GskVulkanImage * gsk_vulkan_image_new_for_framebuffer (GdkVulk
GskVulkanImage * gsk_vulkan_image_new_for_atlas (GdkVulkanContext *context,
gsize width,
gsize height);
GskVulkanImage * gsk_vulkan_image_new_for_texture (GdkVulkanContext *context,
gsize width,
gsize height);
GskTexture * gsk_vulkan_image_download (GskVulkanImage *self,
GskVulkanUploader *uploader);

View File

@@ -34,7 +34,6 @@ struct _GskVulkanRender
GskRenderer *renderer;
GdkVulkanContext *vulkan;
graphene_matrix_t mvp;
int scale_factor;
VkRect2D viewport;
cairo_region_t *clip;
@@ -46,7 +45,6 @@ struct _GskVulkanRender
VkDescriptorSetLayout descriptor_set_layout;
VkPipelineLayout pipeline_layout[3]; /* indexed by number of textures */
GskVulkanUploader *uploader;
GskVulkanBuffer *vertex_buffer;
GHashTable *descriptor_set_indexes;
VkDescriptorPool descriptor_pool;
@@ -57,8 +55,10 @@ struct _GskVulkanRender
GskVulkanImage *target;
GSList *render_passes;
GList *render_passes;
GSList *cleanup_images;
GQuark render_pass_counter;
};
static void
@@ -67,7 +67,6 @@ gsk_vulkan_render_setup (GskVulkanRender *self,
const graphene_rect_t *rect)
{
GdkWindow *window = gsk_renderer_get_window (self->renderer);
graphene_matrix_t modelview, projection;
self->target = g_object_ref (target);
@@ -88,15 +87,6 @@ gsk_vulkan_render_setup (GskVulkanRender *self,
self->viewport.extent.height = gdk_window_get_height (window) * self->scale_factor;
self->clip = gdk_drawing_context_get_clip (gsk_renderer_get_drawing_context (self->renderer));
}
graphene_matrix_init_scale (&modelview, self->scale_factor, self->scale_factor, 1.0);
graphene_matrix_init_ortho (&projection,
self->viewport.offset.x, self->viewport.offset.x + self->viewport.extent.width,
self->viewport.offset.y, self->viewport.offset.y + self->viewport.extent.height,
ORTHO_NEAR_PLANE,
ORTHO_FAR_PLANE);
graphene_matrix_multiply (&modelview, &projection, &self->mvp);
}
GskVulkanRender *
@@ -219,6 +209,10 @@ gsk_vulkan_render_new (GskRenderer *renderer,
self->uploader = gsk_vulkan_uploader_new (self->vulkan, self->command_pool);
#ifdef G_ENABLE_DEBUG
self->render_pass_counter = g_quark_from_static_string ("render-passes");
#endif
return self;
}
@@ -243,7 +237,7 @@ gsk_vulkan_render_remove_framebuffer_from_image (gpointer data,
g_slice_free (HashFramebufferEntry, fb);
}
static VkFramebuffer
VkFramebuffer
gsk_vulkan_render_get_framebuffer (GskVulkanRender *self,
GskVulkanImage *image)
{
@@ -285,72 +279,78 @@ void
gsk_vulkan_render_add_node (GskVulkanRender *self,
GskRenderNode *node)
{
GskVulkanRenderPass *pass = gsk_vulkan_render_pass_new (self->vulkan);
GskVulkanRenderPass *pass;
self->render_passes = g_slist_prepend (self->render_passes, pass);
pass = gsk_vulkan_render_pass_new (self->vulkan,
self->target,
self->scale_factor,
&GRAPHENE_RECT_INIT (
self->viewport.offset.x, self->viewport.offset.y,
self->viewport.extent.width, self->viewport.extent.height
),
self->clip,
VK_NULL_HANDLE);
gsk_vulkan_render_pass_add (pass,
self,
&self->mvp,
&GRAPHENE_RECT_INIT (
self->viewport.offset.x, self->viewport.offset.y,
self->viewport.extent.width, self->viewport.extent.height
),
node);
self->render_passes = g_list_prepend (self->render_passes, pass);
#ifdef G_ENABLE_DEBUG
gsk_profiler_counter_inc (gsk_renderer_get_profiler (self->renderer), self->render_pass_counter);
#endif
gsk_vulkan_render_pass_add (pass, self, node);
}
void
gsk_vulkan_render_add_node_for_texture (GskVulkanRender *self,
GskRenderNode *node,
const graphene_rect_t *bounds,
GskVulkanImage *target,
VkSemaphore semaphore)
{
GskVulkanRenderPass *pass;
pass = gsk_vulkan_render_pass_new (self->vulkan,
target,
1,
&GRAPHENE_RECT_INIT (
0, 0,
gsk_vulkan_image_get_width (target),
gsk_vulkan_image_get_height (target)
),
cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
0, 0,
gsk_vulkan_image_get_width (target),
gsk_vulkan_image_get_height (target)
}),
semaphore);
self->render_passes = g_list_prepend (self->render_passes, pass);
#ifdef G_ENABLE_DEBUG
gsk_profiler_counter_inc (gsk_renderer_get_profiler (self->renderer), self->render_pass_counter);
#endif
gsk_vulkan_render_pass_add (pass, self, node);
}
void
gsk_vulkan_render_upload (GskVulkanRender *self)
{
GSList *l;
GList *l;
for (l = self->render_passes; l; l = l->next)
/* gsk_vulkan_render_pass_upload may call gsk_vulkan_render_add_node_for_texture,
* prepending new render passes to the list. Therefore, we walk the list from
* the end.
*/
for (l = g_list_last (self->render_passes); l; l = l->prev)
{
gsk_vulkan_render_pass_upload (l->data, self, self->uploader);
GskVulkanRenderPass *pass = l->data;
gsk_vulkan_render_pass_upload (pass, self, self->uploader);
}
gsk_vulkan_uploader_upload (self->uploader);
}
static gsize
gsk_vulkan_renderer_count_vertex_data (GskVulkanRender *self)
{
gsize n_bytes;
GSList *l;
n_bytes = 0;
for (l = self->render_passes; l; l = l->next)
{
n_bytes += gsk_vulkan_render_pass_count_vertex_data (l->data);
}
return n_bytes;
}
static GskVulkanBuffer *
gsk_vulkan_render_collect_vertex_data (GskVulkanRender *self)
{
GskVulkanBuffer *buffer;
guchar *data;
GSList *l;
gsize offset, n_bytes;
offset = 0;
n_bytes = gsk_vulkan_renderer_count_vertex_data (self);
buffer = gsk_vulkan_buffer_new (self->vulkan, n_bytes);
data = gsk_vulkan_buffer_map (buffer);
for (l = self->render_passes; l; l = l->next)
{
offset += gsk_vulkan_render_pass_collect_vertex_data (l->data, self, data, offset, n_bytes - offset);
g_assert (offset <= n_bytes);
}
gsk_vulkan_buffer_unmap (buffer);
return buffer;
}
GskVulkanPipeline *
gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
GskVulkanPipelineType type)
@@ -424,6 +424,8 @@ gsk_vulkan_render_reserve_descriptor_set (GskVulkanRender *self,
{
gpointer id_plus_one;
g_assert (source != NULL);
id_plus_one = g_hash_table_lookup (self->descriptor_set_indexes, source);
if (id_plus_one)
return GPOINTER_TO_SIZE (id_plus_one) - 1;
@@ -441,14 +443,15 @@ gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self,
GHashTableIter iter;
gpointer key, value;
VkDevice device;
GSList *l;
GList *l;
guint i, needed_sets;
device = gdk_vulkan_context_get_device (self->vulkan);
for (l = self->render_passes; l; l = l->next)
{
gsk_vulkan_render_pass_reserve_descriptor_sets (l->data, self);
GskVulkanRenderPass *pass = l->data;
gsk_vulkan_render_pass_reserve_descriptor_sets (pass, self);
}
needed_sets = g_hash_table_size (self->descriptor_set_indexes);
@@ -534,75 +537,42 @@ void
gsk_vulkan_render_draw (GskVulkanRender *self,
VkSampler sampler)
{
VkCommandBuffer command_buffer;
GSList *l;
guint i;
GList *l;
gsk_vulkan_render_prepare_descriptor_sets (self, sampler);
command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
self->vertex_buffer = gsk_vulkan_render_collect_vertex_data (self);
vkCmdSetViewport (command_buffer,
0,
1,
&(VkViewport) {
.x = 0,
.y = 0,
.width = self->viewport.extent.width,
.height = self->viewport.extent.height,
.minDepth = 0,
.maxDepth = 1
});
for (i = 0; i < cairo_region_num_rectangles (self->clip); i++)
for (l = self->render_passes; l; l = l->next)
{
cairo_rectangle_int_t rect;
GskVulkanRenderPass *pass = l->data;
VkCommandBuffer command_buffer;
gsize wait_semaphore_count;
gsize signal_semaphore_count;
VkSemaphore *wait_semaphores;
VkSemaphore *signal_semaphores;
cairo_region_get_rectangle (self->clip, i, &rect);
wait_semaphore_count = gsk_vulkan_render_pass_get_wait_semaphores (pass, &wait_semaphores);
signal_semaphore_count = gsk_vulkan_render_pass_get_signal_semaphores (pass, &signal_semaphores);
vkCmdSetScissor (command_buffer,
0,
1,
&(VkRect2D) {
{ rect.x * self->scale_factor, rect.y * self->scale_factor },
{ rect.width * self->scale_factor, rect.height * self->scale_factor }
});
command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
vkCmdBeginRenderPass (command_buffer,
&(VkRenderPassBeginInfo) {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderPass = self->render_pass,
.framebuffer = gsk_vulkan_render_get_framebuffer (self, self->target),
.renderArea = {
{ rect.x * self->scale_factor, rect.y * self->scale_factor },
{ rect.width * self->scale_factor, rect.height * self->scale_factor }
},
.clearValueCount = 1,
.pClearValues = (VkClearValue [1]) {
{ .color = { .float32 = { 0.f, 0.f, 0.f, 0.f } } }
}
},
VK_SUBPASS_CONTENTS_INLINE);
gsk_vulkan_render_pass_draw (pass, self, 3, self->pipeline_layout, command_buffer);
for (l = self->render_passes; l; l = l->next)
{
gsk_vulkan_render_pass_draw (l->data, self, self->vertex_buffer, 3, self->pipeline_layout, command_buffer);
}
vkCmdEndRenderPass (command_buffer);
gsk_vulkan_command_pool_submit_buffer (self->command_pool,
command_buffer,
wait_semaphore_count,
wait_semaphores,
signal_semaphore_count,
signal_semaphores,
l->next != NULL ? VK_NULL_HANDLE : self->fence);
}
gsk_vulkan_command_pool_submit_buffer (self->command_pool, command_buffer, self->fence);
if (GSK_RENDER_MODE_CHECK (SYNC))
{
GSK_VK_CHECK (vkWaitForFences, gdk_vulkan_context_get_device (self->vulkan),
1,
&self->fence,
VK_TRUE,
INT64_MAX);
1000000);
}
}
@@ -624,7 +594,7 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self)
1,
&self->fence,
VK_TRUE,
INT64_MAX);
1000000);
GSK_VK_CHECK (vkResetFences, device,
1,
@@ -634,14 +604,12 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self)
gsk_vulkan_command_pool_reset (self->command_pool);
g_clear_pointer (&self->vertex_buffer, gsk_vulkan_buffer_free);
g_hash_table_remove_all (self->descriptor_set_indexes);
GSK_VK_CHECK (vkResetDescriptorPool, device,
self->descriptor_pool,
0);
g_slist_free_full (self->render_passes, (GDestroyNotify) gsk_vulkan_render_pass_free);
g_list_free_full (self->render_passes, (GDestroyNotify) gsk_vulkan_render_pass_free);
self->render_passes = NULL;
g_slist_free_full (self->cleanup_images, g_object_unref);
self->cleanup_images = NULL;

View File

@@ -26,6 +26,7 @@ struct _GskVulkanTextureData {
#ifdef G_ENABLE_DEBUG
typedef struct {
GQuark frames;
GQuark render_passes;
GQuark fallback_pixels;
} ProfileCounters;
@@ -201,6 +202,7 @@ gsk_vulkan_renderer_render_texture (GskRenderer *renderer,
#ifdef G_ENABLE_DEBUG
profiler = gsk_renderer_get_profiler (renderer);
gsk_profiler_counter_set (profiler, self->profile_counters.fallback_pixels, 0);
gsk_profiler_counter_set (profiler, self->profile_counters.render_passes, 0);
gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
#endif
@@ -246,6 +248,8 @@ gsk_vulkan_renderer_render (GskRenderer *renderer,
#ifdef G_ENABLE_DEBUG
profiler = gsk_renderer_get_profiler (renderer);
gsk_profiler_counter_set (profiler, self->profile_counters.fallback_pixels, 0);
gsk_profiler_counter_set (profiler, self->profile_counters.render_passes, 0);
gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
#endif
@@ -306,6 +310,7 @@ gsk_vulkan_renderer_init (GskVulkanRenderer *self)
#ifdef G_ENABLE_DEBUG
self->profile_counters.frames = gsk_profiler_add_counter (profiler, "frames", "Frames", FALSE);
self->profile_counters.render_passes = gsk_profiler_add_counter (profiler, "render-passes", "Render passes", FALSE);
self->profile_counters.fallback_pixels = gsk_profiler_add_counter (profiler, "fallback-pixels", "Fallback pixels", TRUE);
self->profile_timers.cpu_time = gsk_profiler_add_timer (profiler, "cpu-time", "CPU time", FALSE, TRUE);

View File

@@ -27,6 +27,9 @@
#include <cairo-ft.h>
#define ORTHO_NEAR_PLANE -10000
#define ORTHO_FAR_PLANE 10000
typedef union _GskVulkanOp GskVulkanOp;
typedef struct _GskVulkanOpRender GskVulkanOpRender;
typedef struct _GskVulkanOpText GskVulkanOpText;
@@ -107,17 +110,92 @@ struct _GskVulkanRenderPass
GArray *render_ops;
GskVulkanImage *target;
int scale_factor;
graphene_rect_t viewport;
cairo_region_t *clip;
graphene_matrix_t mvp;
VkRenderPass render_pass;
VkSemaphore signal_semaphore;
GArray *wait_semaphores;
GskVulkanBuffer *vertex_data;
GQuark fallback_pixels;
};
GskVulkanRenderPass *
gsk_vulkan_render_pass_new (GdkVulkanContext *context)
gsk_vulkan_render_pass_new (GdkVulkanContext *context,
GskVulkanImage *target,
int scale_factor,
graphene_rect_t *viewport,
cairo_region_t *clip,
VkSemaphore signal_semaphore)
{
GskVulkanRenderPass *self;
graphene_matrix_t modelview, projection;
self = g_slice_new0 (GskVulkanRenderPass);
self->vulkan = g_object_ref (context);
self->render_ops = g_array_new (FALSE, FALSE, sizeof (GskVulkanOp));
self->target = g_object_ref (target);
self->scale_factor = scale_factor;
self->viewport = *viewport;
self->clip = cairo_region_copy (clip);
graphene_matrix_init_scale (&modelview, self->scale_factor, self->scale_factor, 1.0);
graphene_matrix_init_ortho (&projection,
self->viewport.origin.x, self->viewport.origin.x + self->viewport.size.width,
self->viewport.origin.y, self->viewport.origin.y + self->viewport.size.height,
ORTHO_NEAR_PLANE,
ORTHO_FAR_PLANE);
graphene_matrix_multiply (&modelview, &projection, &self->mvp);
GSK_VK_CHECK (vkCreateRenderPass, gdk_vulkan_context_get_device (self->vulkan),
&(VkRenderPassCreateInfo) {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
.attachmentCount = 1,
.pAttachments = (VkAttachmentDescription[]) {
{
.format = gdk_vulkan_context_get_image_format (self->vulkan),
.samples = VK_SAMPLE_COUNT_1_BIT,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
}
},
.subpassCount = 1,
.pSubpasses = (VkSubpassDescription []) {
{
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.inputAttachmentCount = 0,
.colorAttachmentCount = 1,
.pColorAttachments = (VkAttachmentReference []) {
{
.attachment = 0,
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
}
},
.pResolveAttachments = (VkAttachmentReference []) {
{
.attachment = VK_ATTACHMENT_UNUSED,
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
}
},
.pDepthStencilAttachment = NULL,
}
},
.dependencyCount = 0
},
NULL,
&self->render_pass);
self->signal_semaphore = signal_semaphore;
self->wait_semaphores = g_array_new (FALSE, FALSE, sizeof (VkSemaphore));
self->vertex_data = NULL;
#ifdef G_ENABLE_DEBUG
self->fallback_pixels = g_quark_from_static_string ("fallback-pixels");
#endif
@@ -130,6 +208,19 @@ gsk_vulkan_render_pass_free (GskVulkanRenderPass *self)
{
g_array_unref (self->render_ops);
g_object_unref (self->vulkan);
g_object_unref (self->target);
cairo_region_destroy (self->clip);
vkDestroyRenderPass (gdk_vulkan_context_get_device (self->vulkan),
self->render_pass,
NULL);
if (self->vertex_data)
gsk_vulkan_buffer_free (self->vertex_data);
if (self->signal_semaphore != VK_NULL_HANDLE)
vkDestroySemaphore (gdk_vulkan_context_get_device (self->vulkan),
self->signal_semaphore,
NULL);
g_array_unref (self->wait_semaphores);
g_slice_free (GskVulkanRenderPass, self);
}
@@ -530,14 +621,12 @@ fallback:
void
gsk_vulkan_render_pass_add (GskVulkanRenderPass *self,
GskVulkanRender *render,
const graphene_matrix_t *mvp,
const graphene_rect_t *viewport,
GskRenderNode *node)
{
GskVulkanOp op = { 0, };
op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS;
gsk_vulkan_push_constants_init (&op.constants.constants, mvp, viewport);
gsk_vulkan_push_constants_init (&op.constants.constants, &self->mvp, &self->viewport);
g_array_append_val (self->render_ops, op);
gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, node);
@@ -566,8 +655,28 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
surface = cairo_surface_reference (gsk_cairo_node_get_surface (node));
goto got_surface;
default:
break;
default: ;
{
VkSemaphore semaphore;
result = gsk_vulkan_image_new_for_texture (self->vulkan,
ceil (bounds->size.width),
ceil (bounds->size.height));
vkCreateSemaphore (gdk_vulkan_context_get_device (self->vulkan),
&(VkSemaphoreCreateInfo) {
VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
NULL,
0
},
NULL,
&semaphore);
g_array_append_val (self->wait_semaphores, semaphore);
gsk_vulkan_render_add_node_for_texture (render, node, bounds, result, semaphore);
return result;
}
}
}
@@ -756,7 +865,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
{
GskRenderNode *child = gsk_color_matrix_node_get_child (op->render.node);
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
child,
@@ -813,7 +922,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
}
}
gsize
static gsize
gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
{
GskVulkanOp *op;
@@ -892,6 +1001,7 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
default:
g_assert_not_reached ();
case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
continue;
}
@@ -900,7 +1010,7 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
return n_bytes;
}
gsize
static gsize
gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
GskVulkanRender *render,
guchar *data,
@@ -1124,6 +1234,41 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
return n_bytes;
}
static GskVulkanBuffer *
gsk_vulkan_render_pass_get_vertex_data (GskVulkanRenderPass *self,
GskVulkanRender *render)
{
if (self->vertex_data == NULL)
{
gsize n_bytes;
guchar *data;
n_bytes = gsk_vulkan_render_pass_count_vertex_data (self);
self->vertex_data = gsk_vulkan_buffer_new (self->vulkan, n_bytes);
data = gsk_vulkan_buffer_map (self->vertex_data);
gsk_vulkan_render_pass_collect_vertex_data (self, render, data, 0, n_bytes);
gsk_vulkan_buffer_unmap (self->vertex_data);
}
return self->vertex_data;
}
gsize
gsk_vulkan_render_pass_get_wait_semaphores (GskVulkanRenderPass *self,
VkSemaphore **semaphores)
{
*semaphores = (VkSemaphore *)self->wait_semaphores->data;
return self->wait_semaphores->len;
}
gsize
gsk_vulkan_render_pass_get_signal_semaphores (GskVulkanRenderPass *self,
VkSemaphore **semaphores)
{
*semaphores = (VkSemaphore *)&self->signal_semaphore;
return self->signal_semaphore != VK_NULL_HANDLE ? 1 : 0;
}
void
gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
GskVulkanRender *render)
@@ -1161,6 +1306,7 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
default:
g_assert_not_reached ();
case GSK_VULKAN_OP_COLOR:
case GSK_VULKAN_OP_LINEAR_GRADIENT:
case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
@@ -1172,18 +1318,20 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
}
}
void
gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
GskVulkanRender *render,
GskVulkanBuffer *vertex_buffer,
guint layout_count,
VkPipelineLayout *pipeline_layout,
VkCommandBuffer command_buffer)
static void
gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass *self,
GskVulkanRender *render,
guint layout_count,
VkPipelineLayout *pipeline_layout,
VkCommandBuffer command_buffer)
{
GskVulkanPipeline *current_pipeline = NULL;
gsize current_draw_index = 0;
GskVulkanOp *op;
guint i, step;
GskVulkanBuffer *vertex_buffer;
vertex_buffer = gsk_vulkan_render_pass_get_vertex_data (self, render);
for (i = 0; i < self->render_ops->len; i += step)
{
@@ -1536,3 +1684,60 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
}
}
}
void
gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
GskVulkanRender *render,
guint layout_count,
VkPipelineLayout *pipeline_layout,
VkCommandBuffer command_buffer)
{
guint i;
vkCmdSetViewport (command_buffer,
0,
1,
&(VkViewport) {
.x = 0,
.y = 0,
.width = self->viewport.size.width,
.height = self->viewport.size.height,
.minDepth = 0,
.maxDepth = 1
});
for (i = 0; i < cairo_region_num_rectangles (self->clip); i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (self->clip, i, &rect);
vkCmdSetScissor (command_buffer,
0,
1,
&(VkRect2D) {
{ rect.x * self->scale_factor, rect.y * self->scale_factor },
{ rect.width * self->scale_factor, rect.height * self->scale_factor }
});
vkCmdBeginRenderPass (command_buffer,
&(VkRenderPassBeginInfo) {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderPass = self->render_pass,
.framebuffer = gsk_vulkan_render_get_framebuffer (render, self->target),
.renderArea = {
{ rect.x * self->scale_factor, rect.y * self->scale_factor },
{ rect.width * self->scale_factor, rect.height * self->scale_factor }
},
.clearValueCount = 1,
.pClearValues = (VkClearValue [1]) {
{ .color = { .float32 = { 0.f, 0.f, 0.f, 0.f } } }
}
},
VK_SUBPASS_CONTENTS_INLINE);
gsk_vulkan_render_pass_draw_rect (self, render, 3, pipeline_layout, command_buffer);
vkCmdEndRenderPass (command_buffer);
}
}

View File

@@ -6,39 +6,38 @@
#include "gsk/gskvulkanbufferprivate.h"
#include "gsk/gskvulkanrenderprivate.h"
#include "gsk/gskprivate.h"
G_BEGIN_DECLS
typedef struct _GskVulkanRenderPass GskVulkanRenderPass;
GskVulkanRenderPass * gsk_vulkan_render_pass_new (GdkVulkanContext *context);
GskVulkanRenderPass * gsk_vulkan_render_pass_new (GdkVulkanContext *context,
GskVulkanImage *target,
int scale_factor,
graphene_rect_t *viewport,
cairo_region_t *clip,
VkSemaphore signal_semaphore);
void gsk_vulkan_render_pass_free (GskVulkanRenderPass *self);
void gsk_vulkan_render_pass_add (GskVulkanRenderPass *self,
GskVulkanRender *render,
const graphene_matrix_t*mvp,
const graphene_rect_t *viewport,
GskRenderNode *node);
void gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
GskVulkanRender *render,
GskVulkanUploader *uploader);
gsize gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self);
gsize gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
GskVulkanRender *render,
guchar *data,
gsize offset,
gsize total);
void gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
GskVulkanRender *render);
void gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
GskVulkanRender *render,
GskVulkanBuffer *vertex_buffer,
guint layout_count,
VkPipelineLayout *pipeline_layout,
VkCommandBuffer command_buffer);
gsize gsk_vulkan_render_pass_get_wait_semaphores (GskVulkanRenderPass *self,
VkSemaphore **semaphores);
gsize gsk_vulkan_render_pass_get_signal_semaphores (GskVulkanRenderPass *self,
VkSemaphore **semaphores);
G_END_DECLS

View File

@@ -6,6 +6,8 @@
#include "gsk/gskvulkanimageprivate.h"
#include "gsk/gskvulkanpipelineprivate.h"
#include "gsk/gskvulkanrenderpassprivate.h"
#include "gsk/gskprivate.h"
G_BEGIN_DECLS
@@ -50,8 +52,6 @@ typedef enum {
GSK_VULKAN_N_PIPELINES
} GskVulkanPipelineType;
typedef struct _GskVulkanRender GskVulkanRender;
GskVulkanRender * gsk_vulkan_render_new (GskRenderer *renderer,
GdkVulkanContext *context);
void gsk_vulkan_render_free (GskVulkanRender *self);
@@ -69,6 +69,13 @@ void gsk_vulkan_render_add_cleanup_image (GskVulk
void gsk_vulkan_render_add_node (GskVulkanRender *self,
GskRenderNode *node);
void gsk_vulkan_render_add_node_for_texture (GskVulkanRender *self,
GskRenderNode *node,
const graphene_rect_t *bounds,
GskVulkanImage *target,
VkSemaphore semaphore);
void gsk_vulkan_render_upload (GskVulkanRender *self);
GskVulkanPipeline * gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
@@ -83,6 +90,8 @@ void gsk_vulkan_render_draw (GskVulk
void gsk_vulkan_render_submit (GskVulkanRender *self);
GskTexture * gsk_vulkan_render_download_target (GskVulkanRender *self);
VkFramebuffer gsk_vulkan_render_get_framebuffer (GskVulkanRender *self,
GskVulkanImage *image);
G_END_DECLS