forked from AuroraMiddleware/gtk
vulkan: Add GskVulkanRenderPass
And move the actual rendering code there. A RenderPass is a collection of operations on the same target that get executed one after another. It roughly targets VkRenderPass or rather the subpasses of a VkRenderPass. For now, only the infrastructure is there. No real stuff is happening.
This commit is contained in:
parent
681554787b
commit
3c5b25b1d1
@ -30,6 +30,7 @@ gsk_private_vulan_source_h = \
|
|||||||
gskvulkanpipelineprivate.h \
|
gskvulkanpipelineprivate.h \
|
||||||
gskvulkanrenderprivate.h \
|
gskvulkanrenderprivate.h \
|
||||||
gskvulkanrendererprivate.h \
|
gskvulkanrendererprivate.h \
|
||||||
|
gskvulkanrenderpassprivate.h \
|
||||||
gskvulkanshaderprivate.h
|
gskvulkanshaderprivate.h
|
||||||
gsk_private_vulkan_source_c = \
|
gsk_private_vulkan_source_c = \
|
||||||
gskvulkanbuffer.c \
|
gskvulkanbuffer.c \
|
||||||
@ -38,6 +39,7 @@ gsk_private_vulkan_source_c = \
|
|||||||
gskvulkanpipeline.c \
|
gskvulkanpipeline.c \
|
||||||
gskvulkanrender.c \
|
gskvulkanrender.c \
|
||||||
gskvulkanrenderer.c \
|
gskvulkanrenderer.c \
|
||||||
|
gskvulkanrenderpass.c \
|
||||||
gskvulkanshader.c
|
gskvulkanshader.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -2,16 +2,56 @@
|
|||||||
|
|
||||||
#include "gskvulkanrenderprivate.h"
|
#include "gskvulkanrenderprivate.h"
|
||||||
|
|
||||||
|
#include "gskrendererprivate.h"
|
||||||
|
#include "gskvulkanbufferprivate.h"
|
||||||
#include "gskvulkanpipelineprivate.h"
|
#include "gskvulkanpipelineprivate.h"
|
||||||
|
#include "gskvulkanrenderpassprivate.h"
|
||||||
|
|
||||||
|
#define ORTHO_NEAR_PLANE -10000
|
||||||
|
#define ORTHO_FAR_PLANE 10000
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_vulkan_render_compute_mvp (GskVulkanRender *self)
|
||||||
|
{
|
||||||
|
GdkWindow *window = gsk_renderer_get_window (self->renderer);
|
||||||
|
graphene_matrix_t modelview, projection;
|
||||||
|
cairo_rectangle_int_t extents;
|
||||||
|
|
||||||
|
cairo_region_get_extents (gdk_drawing_context_get_clip (gsk_renderer_get_drawing_context (self->renderer)),
|
||||||
|
&extents);
|
||||||
|
|
||||||
|
self->scale_factor = gsk_renderer_get_scale_factor (self->renderer);
|
||||||
|
self->size.width = gdk_window_get_width (window) * self->scale_factor;
|
||||||
|
self->size.height = gdk_window_get_height (window) * self->scale_factor;
|
||||||
|
self->scissor.offset.x = extents.x * self->scale_factor;
|
||||||
|
self->scissor.offset.y = extents.y * self->scale_factor;
|
||||||
|
self->scissor.extent.width = extents.width * self->scale_factor;
|
||||||
|
self->scissor.extent.height = extents.height * self->scale_factor;
|
||||||
|
|
||||||
|
graphene_matrix_init_scale (&modelview, self->scale_factor, self->scale_factor, 1.0);
|
||||||
|
graphene_matrix_init_ortho (&projection,
|
||||||
|
0, self->size.width,
|
||||||
|
0, self->size.height,
|
||||||
|
ORTHO_NEAR_PLANE,
|
||||||
|
ORTHO_FAR_PLANE);
|
||||||
|
graphene_matrix_multiply (&modelview, &projection, &self->mvp);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gsk_vulkan_render_init (GskVulkanRender *self,
|
gsk_vulkan_render_init (GskVulkanRender *self,
|
||||||
|
GskRenderer *renderer,
|
||||||
GdkVulkanContext *context,
|
GdkVulkanContext *context,
|
||||||
VkCommandPool command_pool)
|
VkCommandPool command_pool)
|
||||||
{
|
{
|
||||||
self->vulkan = context;
|
self->vulkan = context;
|
||||||
|
self->renderer = renderer;
|
||||||
self->command_pool = command_pool;
|
self->command_pool = command_pool;
|
||||||
|
|
||||||
|
self->render_passes = NULL;
|
||||||
|
self->cleanup_images = NULL;
|
||||||
|
|
||||||
|
gsk_vulkan_render_compute_mvp (self);
|
||||||
|
|
||||||
GSK_VK_CHECK (vkAllocateCommandBuffers, gdk_vulkan_context_get_device (self->vulkan),
|
GSK_VK_CHECK (vkAllocateCommandBuffers, gdk_vulkan_context_get_device (self->vulkan),
|
||||||
&(VkCommandBufferAllocateInfo) {
|
&(VkCommandBufferAllocateInfo) {
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
@ -28,6 +68,163 @@ gsk_vulkan_render_init (GskVulkanRender *self,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_vulkan_render_add_cleanup_image (GskVulkanRender *self,
|
||||||
|
GskVulkanImage *image)
|
||||||
|
{
|
||||||
|
self->cleanup_images = g_slist_prepend (self->cleanup_images, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_vulkan_render_add_node (GskVulkanRender *self,
|
||||||
|
GskRenderNode *node)
|
||||||
|
{
|
||||||
|
GskVulkanRenderPass *pass = gsk_vulkan_render_pass_new (self->vulkan);
|
||||||
|
|
||||||
|
self->render_passes = g_slist_prepend (self->render_passes, pass);
|
||||||
|
|
||||||
|
gsk_vulkan_render_pass_add_node (pass, self, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_vulkan_render_upload (GskVulkanRender *self)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
for (l = self->render_passes; l; l = l->next)
|
||||||
|
{
|
||||||
|
gsk_vulkan_render_pass_upload (l->data, self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gsize
|
||||||
|
gsk_vulkan_renderer_count_vertices (GskVulkanRender *self)
|
||||||
|
{
|
||||||
|
gsize count;
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (l = self->render_passes; l; l = l->next)
|
||||||
|
{
|
||||||
|
count += gsk_vulkan_render_pass_count_vertices (l->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GskVulkanBuffer *
|
||||||
|
gsk_vulkan_render_collect_vertices (GskVulkanRender *self)
|
||||||
|
{
|
||||||
|
GskVulkanBuffer *buffer;
|
||||||
|
GskVulkanVertex *vertices;
|
||||||
|
GSList *l;
|
||||||
|
gsize offset, count;
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
count = gsk_vulkan_renderer_count_vertices (self);
|
||||||
|
buffer = gsk_vulkan_buffer_new (self->vulkan, sizeof (GskVulkanVertex) * count);
|
||||||
|
vertices = (GskVulkanVertex *) gsk_vulkan_buffer_map (buffer);
|
||||||
|
|
||||||
|
for (l = self->render_passes; l; l = l->next)
|
||||||
|
{
|
||||||
|
offset += gsk_vulkan_render_pass_collect_vertices (l->data, vertices, offset, count - offset);
|
||||||
|
g_assert (offset <= count);
|
||||||
|
}
|
||||||
|
|
||||||
|
gsk_vulkan_buffer_unmap (buffer);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_vulkan_render_draw (GskVulkanRender *self,
|
||||||
|
GskVulkanPipeline *pipeline,
|
||||||
|
VkRenderPass render_pass,
|
||||||
|
VkFramebuffer framebuffer,
|
||||||
|
VkDescriptorSet descriptor_set,
|
||||||
|
VkSampler sampler)
|
||||||
|
{
|
||||||
|
GskVulkanBuffer *buffer;
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
buffer = gsk_vulkan_render_collect_vertices (self);
|
||||||
|
|
||||||
|
for (l = self->render_passes; l; l = l->next)
|
||||||
|
{
|
||||||
|
gsk_vulkan_render_pass_update_descriptor_sets (l->data, descriptor_set, sampler);
|
||||||
|
}
|
||||||
|
|
||||||
|
vkCmdSetViewport (self->command_buffer,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
&(VkViewport) {
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.width = self->size.width,
|
||||||
|
.height = self->size.height,
|
||||||
|
.minDepth = 0,
|
||||||
|
.maxDepth = 1
|
||||||
|
});
|
||||||
|
|
||||||
|
vkCmdSetScissor (self->command_buffer,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
&self->scissor);
|
||||||
|
|
||||||
|
vkCmdBeginRenderPass (self->command_buffer,
|
||||||
|
&(VkRenderPassBeginInfo) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
|
.renderPass = render_pass,
|
||||||
|
.framebuffer = framebuffer,
|
||||||
|
.renderArea = {
|
||||||
|
{ 0, 0 },
|
||||||
|
{ self->size.width, self->size.height }
|
||||||
|
},
|
||||||
|
.clearValueCount = 1,
|
||||||
|
.pClearValues = (VkClearValue [1]) {
|
||||||
|
{ .color = { .float32 = { 0.f, 0.f, 0.f, 0.f } } }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
|
vkCmdBindPipeline (self->command_buffer,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
gsk_vulkan_pipeline_get_pipeline (pipeline));
|
||||||
|
|
||||||
|
vkCmdBindDescriptorSets (self->command_buffer,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
gsk_vulkan_pipeline_get_pipeline_layout (pipeline),
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
&descriptor_set,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
vkCmdBindVertexBuffers (self->command_buffer,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
(VkBuffer[1]) {
|
||||||
|
gsk_vulkan_buffer_get_buffer (buffer)
|
||||||
|
},
|
||||||
|
(VkDeviceSize[1]) { 0 });
|
||||||
|
|
||||||
|
vkCmdPushConstants (self->command_buffer,
|
||||||
|
gsk_vulkan_pipeline_get_pipeline_layout (pipeline),
|
||||||
|
VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
0,
|
||||||
|
sizeof (graphene_matrix_t),
|
||||||
|
&self->mvp);
|
||||||
|
|
||||||
|
for (l = self->render_passes; l; l = l->next)
|
||||||
|
{
|
||||||
|
gsk_vulkan_render_pass_draw (l->data, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
vkCmdEndRenderPass (self->command_buffer);
|
||||||
|
|
||||||
|
gsk_vulkan_buffer_free (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gsk_vulkan_render_submit (GskVulkanRender *self,
|
gsk_vulkan_render_submit (GskVulkanRender *self,
|
||||||
VkFence fence)
|
VkFence fence)
|
||||||
@ -66,4 +263,7 @@ gsk_vulkan_render_finish (GskVulkanRender *self)
|
|||||||
GSK_VK_CHECK (vkResetCommandPool, gdk_vulkan_context_get_device (self->vulkan),
|
GSK_VK_CHECK (vkResetCommandPool, gdk_vulkan_context_get_device (self->vulkan),
|
||||||
self->command_pool,
|
self->command_pool,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
|
g_slist_free_full (self->render_passes, (GDestroyNotify) gsk_vulkan_render_pass_free);
|
||||||
|
g_slist_free_full (self->cleanup_images, (GDestroyNotify) gsk_vulkan_image_free);
|
||||||
}
|
}
|
||||||
|
@ -332,201 +332,12 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer)
|
|||||||
g_clear_object (&self->vulkan);
|
g_clear_object (&self->vulkan);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GskVulkanImage *
|
|
||||||
gsk_vulkan_renderer_prepare_render (GskVulkanRenderer *self,
|
|
||||||
VkCommandBuffer command_buffer,
|
|
||||||
GskRenderNode *root)
|
|
||||||
{
|
|
||||||
GdkWindow *window;
|
|
||||||
GskRenderer *fallback;
|
|
||||||
GskVulkanImage *image;
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
cairo_t *cr;
|
|
||||||
|
|
||||||
window = gsk_renderer_get_window (GSK_RENDERER (self));
|
|
||||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
|
||||||
gdk_window_get_width (window),
|
|
||||||
gdk_window_get_height (window));
|
|
||||||
cr = cairo_create (surface);
|
|
||||||
fallback = gsk_renderer_create_fallback (GSK_RENDERER (self),
|
|
||||||
&GRAPHENE_RECT_INIT(
|
|
||||||
0, 0,
|
|
||||||
gdk_window_get_width (window),
|
|
||||||
gdk_window_get_height (window)
|
|
||||||
),
|
|
||||||
cr);
|
|
||||||
|
|
||||||
gsk_renderer_render (fallback, root, NULL);
|
|
||||||
g_object_unref (fallback);
|
|
||||||
|
|
||||||
cairo_destroy (cr);
|
|
||||||
|
|
||||||
image = gsk_vulkan_image_new_from_data (self->vulkan,
|
|
||||||
command_buffer,
|
|
||||||
cairo_image_surface_get_data (surface),
|
|
||||||
cairo_image_surface_get_width (surface),
|
|
||||||
cairo_image_surface_get_height (surface),
|
|
||||||
cairo_image_surface_get_stride (surface));
|
|
||||||
cairo_surface_destroy (surface);
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gsk_vulkan_renderer_do_render_commands (GskVulkanRenderer *self,
|
|
||||||
VkCommandBuffer command_buffer)
|
|
||||||
{
|
|
||||||
GskVulkanBuffer *buffer;
|
|
||||||
GdkWindow *window = gsk_renderer_get_window (GSK_RENDERER (self));
|
|
||||||
int width = gdk_window_get_width (window);
|
|
||||||
int height = gdk_window_get_height (window);
|
|
||||||
float pts[] = {
|
|
||||||
0.0, 0.0, 0.0, 0.0,
|
|
||||||
width, 0.0, 1.0, 0.0,
|
|
||||||
0.0, height, 0.0, 1.0,
|
|
||||||
|
|
||||||
0.0, height, 0.0, 1.0,
|
|
||||||
width, 0.0, 1.0, 0.0,
|
|
||||||
width, height, 1.0, 1.0
|
|
||||||
};
|
|
||||||
guchar *data;
|
|
||||||
|
|
||||||
buffer = gsk_vulkan_buffer_new (self->vulkan, sizeof (pts));
|
|
||||||
|
|
||||||
data = gsk_vulkan_buffer_map (buffer);
|
|
||||||
memcpy (data, pts, sizeof (pts));
|
|
||||||
gsk_vulkan_buffer_unmap (buffer);
|
|
||||||
|
|
||||||
vkCmdBindPipeline (command_buffer,
|
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
||||||
gsk_vulkan_pipeline_get_pipeline (self->pipeline));
|
|
||||||
|
|
||||||
vkCmdBindDescriptorSets (command_buffer,
|
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
||||||
gsk_vulkan_pipeline_get_pipeline_layout (self->pipeline),
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
&self->descriptor_set,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
vkCmdBindVertexBuffers (command_buffer,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
(VkBuffer[1]) {
|
|
||||||
gsk_vulkan_buffer_get_buffer (buffer)
|
|
||||||
},
|
|
||||||
(VkDeviceSize[1]) { 0 });
|
|
||||||
|
|
||||||
vkCmdDraw (command_buffer,
|
|
||||||
6, 1,
|
|
||||||
0, 0);
|
|
||||||
|
|
||||||
gsk_vulkan_buffer_free (buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ORTHO_NEAR_PLANE -10000
|
|
||||||
#define ORTHO_FAR_PLANE 10000
|
|
||||||
|
|
||||||
static void
|
|
||||||
gsk_vulkan_renderer_do_render_pass (GskVulkanRenderer *self,
|
|
||||||
VkCommandBuffer command_buffer,
|
|
||||||
GskVulkanImage *image)
|
|
||||||
{
|
|
||||||
GdkRectangle extents;
|
|
||||||
GdkWindow *window;
|
|
||||||
int scale_factor, unscaled_width, unscaled_height;
|
|
||||||
graphene_matrix_t modelview, projection, mvp;
|
|
||||||
|
|
||||||
window = gsk_renderer_get_window (GSK_RENDERER (self));
|
|
||||||
cairo_region_get_extents (gdk_drawing_context_get_clip (gsk_renderer_get_drawing_context (GSK_RENDERER (self))),
|
|
||||||
&extents);
|
|
||||||
scale_factor = gsk_renderer_get_scale_factor (GSK_RENDERER (self));
|
|
||||||
unscaled_width = gdk_window_get_width (window) * scale_factor;
|
|
||||||
unscaled_height = gdk_window_get_height (window) * scale_factor;
|
|
||||||
|
|
||||||
vkUpdateDescriptorSets (gdk_vulkan_context_get_device (self->vulkan),
|
|
||||||
1,
|
|
||||||
(VkWriteDescriptorSet[1]) {
|
|
||||||
{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
||||||
.dstSet = self->descriptor_set,
|
|
||||||
.dstBinding = 0,
|
|
||||||
.dstArrayElement = 0,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
||||||
.pImageInfo = &(VkDescriptorImageInfo) {
|
|
||||||
.sampler = self->sampler,
|
|
||||||
.imageView = gsk_vulkan_image_get_image_view (image),
|
|
||||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
0, NULL);
|
|
||||||
|
|
||||||
vkCmdBeginRenderPass (command_buffer,
|
|
||||||
&(VkRenderPassBeginInfo) {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
|
||||||
.renderPass = self->render_pass,
|
|
||||||
.framebuffer = self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)]->framebuffer,
|
|
||||||
.renderArea = {
|
|
||||||
{ 0, 0 },
|
|
||||||
{ unscaled_width, unscaled_height }
|
|
||||||
},
|
|
||||||
.clearValueCount = 1,
|
|
||||||
.pClearValues = (VkClearValue [1]) {
|
|
||||||
{ .color = { .float32 = { 0.f, 0.f, 0.f, 0.f } } }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
VK_SUBPASS_CONTENTS_INLINE);
|
|
||||||
|
|
||||||
vkCmdSetViewport (command_buffer,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
&(VkViewport) {
|
|
||||||
.x = 0,
|
|
||||||
.y = 0,
|
|
||||||
.width = unscaled_width,
|
|
||||||
.height = unscaled_height,
|
|
||||||
.minDepth = 0,
|
|
||||||
.maxDepth = 1
|
|
||||||
});
|
|
||||||
|
|
||||||
vkCmdSetScissor (command_buffer,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
&(VkRect2D) {
|
|
||||||
{ extents.x * scale_factor, extents.y * scale_factor },
|
|
||||||
{ extents.width * scale_factor, extents.height * scale_factor }
|
|
||||||
});
|
|
||||||
|
|
||||||
graphene_matrix_init_scale (&modelview, scale_factor, scale_factor, 1.0);
|
|
||||||
graphene_matrix_init_ortho (&projection,
|
|
||||||
0, unscaled_width,
|
|
||||||
0, unscaled_height,
|
|
||||||
ORTHO_NEAR_PLANE,
|
|
||||||
ORTHO_FAR_PLANE);
|
|
||||||
graphene_matrix_multiply (&modelview, &projection, &mvp);
|
|
||||||
|
|
||||||
vkCmdPushConstants (command_buffer,
|
|
||||||
gsk_vulkan_pipeline_get_pipeline_layout (self->pipeline),
|
|
||||||
VK_SHADER_STAGE_VERTEX_BIT,
|
|
||||||
0,
|
|
||||||
sizeof (graphene_matrix_t),
|
|
||||||
&mvp);
|
|
||||||
|
|
||||||
gsk_vulkan_renderer_do_render_commands (self, command_buffer);
|
|
||||||
|
|
||||||
vkCmdEndRenderPass (command_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_vulkan_renderer_render (GskRenderer *renderer,
|
gsk_vulkan_renderer_render (GskRenderer *renderer,
|
||||||
GskRenderNode *root)
|
GskRenderNode *root)
|
||||||
{
|
{
|
||||||
GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
|
GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
|
||||||
GskVulkanRender render;
|
GskVulkanRender render;
|
||||||
GskVulkanImage *image;
|
|
||||||
#ifdef G_ENABLE_DEBUG
|
#ifdef G_ENABLE_DEBUG
|
||||||
GskProfiler *profiler;
|
GskProfiler *profiler;
|
||||||
gint64 cpu_time;
|
gint64 cpu_time;
|
||||||
@ -537,16 +348,19 @@ gsk_vulkan_renderer_render (GskRenderer *renderer,
|
|||||||
gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
|
gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gsk_vulkan_render_init (&render, self->vulkan, self->command_pool);
|
gsk_vulkan_render_init (&render, renderer, self->vulkan, self->command_pool);
|
||||||
|
|
||||||
image = gsk_vulkan_renderer_prepare_render (self, render.command_buffer, root);
|
gsk_vulkan_render_add_node (&render, root);
|
||||||
|
|
||||||
gsk_vulkan_renderer_do_render_pass (self, render.command_buffer, image);
|
gsk_vulkan_render_upload (&render);
|
||||||
|
|
||||||
|
gsk_vulkan_render_draw (&render, self->pipeline,
|
||||||
|
self->render_pass,
|
||||||
|
self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)]->framebuffer,
|
||||||
|
self->descriptor_set, self->sampler);
|
||||||
|
|
||||||
gsk_vulkan_render_submit (&render, self->command_pool_fence);
|
gsk_vulkan_render_submit (&render, self->command_pool_fence);
|
||||||
|
|
||||||
gsk_vulkan_image_free (image);
|
|
||||||
|
|
||||||
gsk_vulkan_render_finish (&render);
|
gsk_vulkan_render_finish (&render);
|
||||||
|
|
||||||
#ifdef G_ENABLE_DEBUG
|
#ifdef G_ENABLE_DEBUG
|
||||||
|
233
gsk/gskvulkanrenderpass.c
Normal file
233
gsk/gskvulkanrenderpass.c
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gskvulkanrenderpassprivate.h"
|
||||||
|
|
||||||
|
#include "gskvulkanimageprivate.h"
|
||||||
|
#include "gskrendernodeprivate.h"
|
||||||
|
#include "gskrenderer.h"
|
||||||
|
|
||||||
|
typedef struct _GskVulkanRenderOp GskVulkanRenderOp;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GSK_VULKAN_OP_FALLBACK
|
||||||
|
} GskVulkanOpType;
|
||||||
|
|
||||||
|
struct _GskVulkanRenderOp
|
||||||
|
{
|
||||||
|
GskVulkanOpType type;
|
||||||
|
GskRenderNode *node; /* node that's the source of this op */
|
||||||
|
GskVulkanRenderPass *pass; /* render pass required to set up node */
|
||||||
|
GskVulkanImage *source; /* source image to render */
|
||||||
|
gsize vertex_offset; /* offset into vertex buffer */
|
||||||
|
gsize vertex_count; /* number of vertices */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GskVulkanRenderPass
|
||||||
|
{
|
||||||
|
GdkVulkanContext *vulkan;
|
||||||
|
|
||||||
|
GArray *render_ops;
|
||||||
|
};
|
||||||
|
|
||||||
|
GskVulkanRenderPass *
|
||||||
|
gsk_vulkan_render_pass_new (GdkVulkanContext *context)
|
||||||
|
{
|
||||||
|
GskVulkanRenderPass *self;
|
||||||
|
|
||||||
|
self = g_slice_new0 (GskVulkanRenderPass);
|
||||||
|
self->vulkan = g_object_ref (context);
|
||||||
|
self->render_ops = g_array_new (FALSE, FALSE, sizeof (GskVulkanRenderOp));
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_vulkan_render_pass_free (GskVulkanRenderPass *self)
|
||||||
|
{
|
||||||
|
g_array_unref (self->render_ops);
|
||||||
|
g_object_unref (self->vulkan);
|
||||||
|
|
||||||
|
g_slice_free (GskVulkanRenderPass, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
|
||||||
|
GskVulkanRender *render,
|
||||||
|
GskRenderNode *node)
|
||||||
|
{
|
||||||
|
GskVulkanRenderOp op = {
|
||||||
|
.type = GSK_VULKAN_OP_FALLBACK,
|
||||||
|
.node = node
|
||||||
|
};
|
||||||
|
|
||||||
|
g_array_append_val (self->render_ops, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderOp *op,
|
||||||
|
GskVulkanRender *render)
|
||||||
|
{
|
||||||
|
graphene_rect_t bounds;
|
||||||
|
GskRenderer *fallback;
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
cairo_t *cr;
|
||||||
|
|
||||||
|
gsk_render_node_get_bounds (op->node, &bounds);
|
||||||
|
|
||||||
|
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||||
|
ceil (bounds.size.width),
|
||||||
|
ceil (bounds.size.height));
|
||||||
|
cr = cairo_create (surface);
|
||||||
|
cairo_translate (cr, bounds.origin.x, bounds.origin.y);
|
||||||
|
|
||||||
|
fallback = gsk_renderer_create_fallback (render->renderer,
|
||||||
|
&bounds,
|
||||||
|
cr);
|
||||||
|
gsk_renderer_render (fallback, op->node, NULL);
|
||||||
|
g_object_unref (fallback);
|
||||||
|
|
||||||
|
cairo_destroy (cr);
|
||||||
|
|
||||||
|
op->source = gsk_vulkan_image_new_from_data (render->vulkan,
|
||||||
|
render->command_buffer,
|
||||||
|
cairo_image_surface_get_data (surface),
|
||||||
|
cairo_image_surface_get_width (surface),
|
||||||
|
cairo_image_surface_get_height (surface),
|
||||||
|
cairo_image_surface_get_stride (surface));
|
||||||
|
|
||||||
|
cairo_surface_destroy (surface);
|
||||||
|
|
||||||
|
gsk_vulkan_render_add_cleanup_image (render, op->source);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
|
||||||
|
GskVulkanRender *render)
|
||||||
|
{
|
||||||
|
GskVulkanRenderOp *op;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < self->render_ops->len; i++)
|
||||||
|
{
|
||||||
|
op = &g_array_index (self->render_ops, GskVulkanRenderOp, i);
|
||||||
|
|
||||||
|
switch (op->type)
|
||||||
|
{
|
||||||
|
case GSK_VULKAN_OP_FALLBACK:
|
||||||
|
gsk_vulkan_render_pass_upload_fallback (op, render);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gsize
|
||||||
|
gsk_vulkan_render_pass_count_vertices (GskVulkanRenderPass *self)
|
||||||
|
{
|
||||||
|
return self->render_ops->len * 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gsize
|
||||||
|
gsk_vulkan_render_op_collect_vertices (GskVulkanRenderOp *op,
|
||||||
|
GskVulkanVertex *vertices)
|
||||||
|
{
|
||||||
|
graphene_rect_t bounds;
|
||||||
|
|
||||||
|
gsk_render_node_get_bounds (op->node, &bounds);
|
||||||
|
|
||||||
|
vertices[0] = (GskVulkanVertex) { bounds.origin.x, bounds.origin.y, 0.0, 0.0 };
|
||||||
|
vertices[1] = (GskVulkanVertex) { bounds.origin.x + bounds.size.width, bounds.origin.y, 1.0, 0.0 };
|
||||||
|
vertices[2] = (GskVulkanVertex) { bounds.origin.x, bounds.origin.y + bounds.size.height, 0.0, 1.0 };
|
||||||
|
vertices[3] = (GskVulkanVertex) { bounds.origin.x, bounds.origin.y + bounds.size.height, 0.0, 1.0 };
|
||||||
|
vertices[4] = (GskVulkanVertex) { bounds.origin.x + bounds.size.width, bounds.origin.y, 1.0, 0.0 };
|
||||||
|
vertices[5] = (GskVulkanVertex) { bounds.origin.x + bounds.size.width, bounds.origin.y + bounds.size.height, 1.0, 1.0 };
|
||||||
|
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsize
|
||||||
|
gsk_vulkan_render_pass_collect_vertices (GskVulkanRenderPass *self,
|
||||||
|
GskVulkanVertex *vertices,
|
||||||
|
gsize offset,
|
||||||
|
gsize total)
|
||||||
|
{
|
||||||
|
GskVulkanRenderOp *op;
|
||||||
|
gsize n;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
for (i = 0; i < self->render_ops->len; i++)
|
||||||
|
{
|
||||||
|
op = &g_array_index (self->render_ops, GskVulkanRenderOp, i);
|
||||||
|
|
||||||
|
switch (op->type)
|
||||||
|
{
|
||||||
|
case GSK_VULKAN_OP_FALLBACK:
|
||||||
|
op->vertex_offset = offset + n;
|
||||||
|
op->vertex_count = gsk_vulkan_render_op_collect_vertices (op, vertices + n + offset);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
n += op->vertex_count;
|
||||||
|
g_assert (n + offset <= total);
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_vulkan_render_pass_update_descriptor_sets (GskVulkanRenderPass *self,
|
||||||
|
VkDescriptorSet descriptor_set,
|
||||||
|
VkSampler sampler)
|
||||||
|
{
|
||||||
|
GskVulkanRenderOp *op;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < self->render_ops->len; i++)
|
||||||
|
{
|
||||||
|
op = &g_array_index (self->render_ops, GskVulkanRenderOp, i);
|
||||||
|
|
||||||
|
vkUpdateDescriptorSets (gdk_vulkan_context_get_device (self->vulkan),
|
||||||
|
1,
|
||||||
|
(VkWriteDescriptorSet[1]) {
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
.dstSet = descriptor_set,
|
||||||
|
.dstBinding = 0,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
.pImageInfo = &(VkDescriptorImageInfo) {
|
||||||
|
.sampler = sampler,
|
||||||
|
.imageView = gsk_vulkan_image_get_image_view (op->source),
|
||||||
|
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
|
||||||
|
GskVulkanRender *render)
|
||||||
|
{
|
||||||
|
GskVulkanRenderOp *op;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < self->render_ops->len; i++)
|
||||||
|
{
|
||||||
|
op = &g_array_index (self->render_ops, GskVulkanRenderOp, i);
|
||||||
|
|
||||||
|
vkCmdDraw (render->command_buffer,
|
||||||
|
op->vertex_count, 1,
|
||||||
|
op->vertex_offset, 0);
|
||||||
|
}
|
||||||
|
}
|
37
gsk/gskvulkanrenderpassprivate.h
Normal file
37
gsk/gskvulkanrenderpassprivate.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef __GSK_VULKAN_RENDER_PASS_PRIVATE_H__
|
||||||
|
#define __GSK_VULKAN_RENDER_PASS_PRIVATE_H__
|
||||||
|
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
#include <gsk/gskrendernode.h>
|
||||||
|
|
||||||
|
#include "gsk/gskvulkanrenderprivate.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GskVulkanRenderPass GskVulkanRenderPass;
|
||||||
|
|
||||||
|
GskVulkanRenderPass * gsk_vulkan_render_pass_new (GdkVulkanContext *context);
|
||||||
|
void gsk_vulkan_render_pass_free (GskVulkanRenderPass *self);
|
||||||
|
|
||||||
|
void gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
|
||||||
|
GskVulkanRender *render,
|
||||||
|
GskRenderNode *node);
|
||||||
|
|
||||||
|
void gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
|
||||||
|
GskVulkanRender *render);
|
||||||
|
|
||||||
|
gsize gsk_vulkan_render_pass_count_vertices (GskVulkanRenderPass *self);
|
||||||
|
gsize gsk_vulkan_render_pass_collect_vertices (GskVulkanRenderPass *self,
|
||||||
|
GskVulkanVertex *vertices,
|
||||||
|
gsize offset,
|
||||||
|
gsize total);
|
||||||
|
|
||||||
|
void gsk_vulkan_render_pass_update_descriptor_sets (GskVulkanRenderPass *self,
|
||||||
|
VkDescriptorSet descriptor_set,
|
||||||
|
VkSampler sampler);
|
||||||
|
void gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
|
||||||
|
GskVulkanRender *render);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSK_VULKAN_RENDER_PASS_PRIVATE_H__ */
|
@ -2,28 +2,66 @@
|
|||||||
#define __GSK_VULKAN_RENDER_PRIVATE_H__
|
#define __GSK_VULKAN_RENDER_PRIVATE_H__
|
||||||
|
|
||||||
#include <gdk/gdk.h>
|
#include <gdk/gdk.h>
|
||||||
|
#include <gsk/gskrendernode.h>
|
||||||
|
|
||||||
|
#include "gsk/gskvulkanimageprivate.h"
|
||||||
|
#include "gsk/gskvulkanpipelineprivate.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef struct _GskVulkanRender GskVulkanRender;
|
typedef struct _GskVulkanRender GskVulkanRender;
|
||||||
|
typedef struct _GskVulkanVertex GskVulkanVertex;
|
||||||
|
|
||||||
struct _GskVulkanRender
|
struct _GskVulkanRender
|
||||||
{
|
{
|
||||||
|
GskRenderer *renderer;
|
||||||
GdkVulkanContext *vulkan;
|
GdkVulkanContext *vulkan;
|
||||||
|
|
||||||
|
graphene_matrix_t mvp;
|
||||||
|
int scale_factor;
|
||||||
|
VkExtent2D size;
|
||||||
|
VkRect2D scissor;
|
||||||
|
|
||||||
|
|
||||||
VkCommandPool command_pool;
|
VkCommandPool command_pool;
|
||||||
VkCommandBuffer command_buffer;
|
VkCommandBuffer command_buffer;
|
||||||
|
|
||||||
|
GSList *render_passes;
|
||||||
|
GSList *cleanup_images;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GskVulkanVertex
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float tex_x;
|
||||||
|
float tex_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
void gsk_vulkan_render_init (GskVulkanRender *self,
|
void gsk_vulkan_render_init (GskVulkanRender *self,
|
||||||
|
GskRenderer *renderer,
|
||||||
GdkVulkanContext *context,
|
GdkVulkanContext *context,
|
||||||
VkCommandPool command_pool);
|
VkCommandPool command_pool);
|
||||||
|
void gsk_vulkan_render_finish (GskVulkanRender *self);
|
||||||
|
|
||||||
|
void gsk_vulkan_render_add_cleanup_image (GskVulkanRender *self,
|
||||||
|
GskVulkanImage *image);
|
||||||
|
|
||||||
|
void gsk_vulkan_render_add_node (GskVulkanRender *self,
|
||||||
|
GskRenderNode *node);
|
||||||
|
|
||||||
|
void gsk_vulkan_render_upload (GskVulkanRender *self);
|
||||||
|
|
||||||
|
void gsk_vulkan_render_draw (GskVulkanRender *self,
|
||||||
|
GskVulkanPipeline *pipeline,
|
||||||
|
VkRenderPass render_pass,
|
||||||
|
VkFramebuffer framebuffer,
|
||||||
|
VkDescriptorSet descriptor_set,
|
||||||
|
VkSampler sampler);
|
||||||
|
|
||||||
void gsk_vulkan_render_submit (GskVulkanRender *self,
|
void gsk_vulkan_render_submit (GskVulkanRender *self,
|
||||||
VkFence fence);
|
VkFence fence);
|
||||||
|
|
||||||
void gsk_vulkan_render_finish (GskVulkanRender *self);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GSK_VULKAN_RENDER_PRIVATE_H__ */
|
#endif /* __GSK_VULKAN_RENDER_PRIVATE_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user