forked from AuroraMiddleware/gtk
vulkan: Implement multiple render passes
Whenever we need a node as a texture, we now start a new render pass that renders the node into a new intermediate texture, and set up a semaphore to make the current render pass wait for it. As part of this reorganization, much of the setup and drawing code moved from gskvulkanrender.c to gskvulkanrenderpass.c.
This commit is contained in:
parent
cbf897ab22
commit
d61a715909
@ -23,9 +23,6 @@
|
||||
#include "gskvulkantextpipelineprivate.h"
|
||||
#include "gskvulkanpushconstantsprivate.h"
|
||||
|
||||
#define ORTHO_NEAR_PLANE -10000
|
||||
#define ORTHO_FAR_PLANE 10000
|
||||
|
||||
#define DESCRIPTOR_POOL_MAXSETS 128
|
||||
#define DESCRIPTOR_POOL_MAXSETS_INCREASE 128
|
||||
|
||||
@ -34,7 +31,6 @@ struct _GskVulkanRender
|
||||
GskRenderer *renderer;
|
||||
GdkVulkanContext *vulkan;
|
||||
|
||||
graphene_matrix_t mvp;
|
||||
int scale_factor;
|
||||
VkRect2D viewport;
|
||||
cairo_region_t *clip;
|
||||
@ -46,7 +42,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,7 +52,7 @@ struct _GskVulkanRender
|
||||
|
||||
GskVulkanImage *target;
|
||||
|
||||
GSList *render_passes;
|
||||
GList *render_passes;
|
||||
GSList *cleanup_images;
|
||||
};
|
||||
|
||||
@ -67,7 +62,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 +82,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 *
|
||||
@ -243,7 +228,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 +270,71 @@ 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);
|
||||
|
||||
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;
|
||||
cairo_region_t *clip;
|
||||
|
||||
clip = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
|
||||
0, 0,
|
||||
gsk_vulkan_image_get_width (target),
|
||||
gsk_vulkan_image_get_height (target)
|
||||
});
|
||||
|
||||
pass = gsk_vulkan_render_pass_new (self->vulkan,
|
||||
target,
|
||||
1,
|
||||
bounds,
|
||||
clip,
|
||||
semaphore);
|
||||
|
||||
cairo_region_destroy (clip);
|
||||
|
||||
self->render_passes = g_list_prepend (self->render_passes, pass);
|
||||
|
||||
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 +408,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 +427,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,68 +521,35 @@ 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, 0, NULL, 0, NULL, self->fence);
|
||||
|
||||
if (GSK_RENDER_MODE_CHECK (SYNC))
|
||||
{
|
||||
GSK_VK_CHECK (vkWaitForFences, gdk_vulkan_context_get_device (self->vulkan),
|
||||
@ -634,14 +588,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;
|
||||
|
@ -246,6 +246,7 @@ 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_timer_begin (profiler, self->profile_timers.cpu_time);
|
||||
#endif
|
||||
|
||||
|
@ -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,97 @@ 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;
|
||||
VkImageLayout final_layout;
|
||||
|
||||
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->clip = cairo_region_copy (clip);
|
||||
self->viewport = GRAPHENE_RECT_INIT (0, 0, viewport->size.width, viewport->size.height);
|
||||
|
||||
graphene_matrix_init_scale (&modelview, self->scale_factor, self->scale_factor, 1.0);
|
||||
graphene_matrix_init_ortho (&projection,
|
||||
viewport->origin.x, viewport->origin.x + viewport->size.width,
|
||||
viewport->origin.y, viewport->origin.y + viewport->size.height,
|
||||
ORTHO_NEAR_PLANE,
|
||||
ORTHO_FAR_PLANE);
|
||||
graphene_matrix_multiply (&modelview, &projection, &self->mvp);
|
||||
|
||||
if (signal_semaphore != VK_NULL_HANDLE) // this is a dependent pass
|
||||
final_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
else
|
||||
final_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
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 = final_layout
|
||||
}
|
||||
},
|
||||
.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 +213,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 +626,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);
|
||||
@ -559,15 +653,39 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
|
||||
switch (gsk_render_node_get_node_type (node))
|
||||
{
|
||||
case GSK_TEXTURE_NODE:
|
||||
return gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
|
||||
gsk_texture_node_get_texture (node),
|
||||
uploader);
|
||||
result = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
|
||||
gsk_texture_node_get_texture (node),
|
||||
uploader);
|
||||
gsk_vulkan_render_add_cleanup_image (render, result);
|
||||
return result;
|
||||
|
||||
case GSK_CAIRO_NODE:
|
||||
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);
|
||||
gsk_vulkan_render_add_cleanup_image (render, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -813,7 +931,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
|
||||
}
|
||||
}
|
||||
|
||||
gsize
|
||||
static gsize
|
||||
gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
|
||||
{
|
||||
GskVulkanOp *op;
|
||||
@ -892,6 +1010,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 +1019,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,23 +1243,39 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
GskVulkanBuffer *
|
||||
static GskVulkanBuffer *
|
||||
gsk_vulkan_render_pass_get_vertex_data (GskVulkanRenderPass *self,
|
||||
GskVulkanRender *render)
|
||||
{
|
||||
gsize n_bytes;
|
||||
GskVulkanBuffer *buffer;
|
||||
guchar *data;
|
||||
if (self->vertex_data == NULL)
|
||||
{
|
||||
gsize n_bytes;
|
||||
guchar *data;
|
||||
|
||||
n_bytes = gsk_vulkan_render_pass_count_vertex_data (self);
|
||||
buffer = gsk_vulkan_buffer_new (self->vulkan, n_bytes);
|
||||
data = gsk_vulkan_buffer_map (buffer);
|
||||
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);
|
||||
}
|
||||
|
||||
gsk_vulkan_render_pass_collect_vertex_data (self, render, data, 0, n_bytes);
|
||||
return self->vertex_data;
|
||||
}
|
||||
|
||||
gsk_vulkan_buffer_unmap (buffer);
|
||||
gsize
|
||||
gsk_vulkan_render_pass_get_wait_semaphores (GskVulkanRenderPass *self,
|
||||
VkSemaphore **semaphores)
|
||||
{
|
||||
*semaphores = (VkSemaphore *)self->wait_semaphores->data;
|
||||
return self->wait_semaphores->len;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
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
|
||||
@ -1180,6 +1315,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:
|
||||
@ -1191,18 +1327,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)
|
||||
{
|
||||
@ -1555,3 +1693,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, layout_count, pipeline_layout, command_buffer);
|
||||
|
||||
vkCmdEndRenderPass (command_buffer);
|
||||
}
|
||||
}
|
||||
|
@ -11,36 +11,33 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
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);
|
||||
GskVulkanBuffer * gsk_vulkan_render_pass_get_vertex_data (GskVulkanRenderPass *self,
|
||||
GskVulkanRender *render);
|
||||
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user