Compare commits
6 Commits
ebassi/css
...
wip/matthi
Author | SHA1 | Date | |
---|---|---|---|
|
5a2cd3e582 | ||
|
5059ae00bf | ||
|
59b4dec216 | ||
|
0823c6de2f | ||
|
ff111b3f4f | ||
|
337f96541f |
@@ -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__ */
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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]) {
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user