[gtk+] vulkan: Implement gsk_renderer_render_texture()
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] vulkan: Implement gsk_renderer_render_texture()
- Date: Fri, 23 Dec 2016 07:45:12 +0000 (UTC)
commit 786d3a013e0ec7f19999f05f32df1110585d6443
Author: Benjamin Otte <otte redhat com>
Date: Thu Dec 22 19:01:07 2016 +0100
vulkan: Implement gsk_renderer_render_texture()
gsk/gskvulkanbuffer.c | 6 +++
gsk/gskvulkanbufferprivate.h | 2 +
gsk/gskvulkancommandpool.c | 4 ++
gsk/gskvulkanimage.c | 85 ++++++++++++++++++++++++++++++++++++++++++
gsk/gskvulkanimageprivate.h | 7 +++
gsk/gskvulkanrender.c | 68 ++++++++++++++++++++++-----------
gsk/gskvulkanrenderer.c | 51 ++++++++++++++++++++++++-
gsk/gskvulkanrenderprivate.h | 5 ++-
8 files changed, 204 insertions(+), 24 deletions(-)
---
diff --git a/gsk/gskvulkanbuffer.c b/gsk/gskvulkanbuffer.c
index 3c1d76d..ec5905b 100644
--- a/gsk/gskvulkanbuffer.c
+++ b/gsk/gskvulkanbuffer.c
@@ -71,6 +71,12 @@ gsk_vulkan_buffer_new_staging (GdkVulkanContext *context,
return gsk_vulkan_buffer_new_internal (context, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
}
+GskVulkanBuffer *
+gsk_vulkan_buffer_new_download (GdkVulkanContext *context,
+ gsize size)
+{
+ return gsk_vulkan_buffer_new_internal (context, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+}
void
gsk_vulkan_buffer_free (GskVulkanBuffer *self)
{
diff --git a/gsk/gskvulkanbufferprivate.h b/gsk/gskvulkanbufferprivate.h
index 30e327e..700e400 100644
--- a/gsk/gskvulkanbufferprivate.h
+++ b/gsk/gskvulkanbufferprivate.h
@@ -11,6 +11,8 @@ GskVulkanBuffer * gsk_vulkan_buffer_new (GdkVulk
gsize size);
GskVulkanBuffer * gsk_vulkan_buffer_new_staging (GdkVulkanContext *context,
gsize size);
+GskVulkanBuffer * gsk_vulkan_buffer_new_download (GdkVulkanContext *context,
+ gsize size);
void gsk_vulkan_buffer_free (GskVulkanBuffer *buffer);
VkBuffer gsk_vulkan_buffer_get_buffer (GskVulkanBuffer *self);
diff --git a/gsk/gskvulkancommandpool.c b/gsk/gskvulkancommandpool.c
index 218a8c9..09dd333 100644
--- a/gsk/gskvulkancommandpool.c
+++ b/gsk/gskvulkancommandpool.c
@@ -83,10 +83,12 @@ gsk_vulkan_command_pool_submit_buffer (GskVulkanCommandPool *self,
1,
&(VkSubmitInfo) {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+#if 0
.waitSemaphoreCount = 1,
.pWaitSemaphores = (VkSemaphore[1]) {
gdk_vulkan_context_get_draw_semaphore (self->vulkan)
},
+#endif
.pWaitDstStageMask = (VkPipelineStageFlags []) {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
},
@@ -94,10 +96,12 @@ gsk_vulkan_command_pool_submit_buffer (GskVulkanCommandPool *self,
.pCommandBuffers = (VkCommandBuffer[1]) {
command_buffer
},
+#if 0
.signalSemaphoreCount = 1,
.pSignalSemaphores = (VkSemaphore[1]) {
gdk_vulkan_context_get_draw_semaphore (self->vulkan)
}
+#endif
},
fence);
}
diff --git a/gsk/gskvulkanimage.c b/gsk/gskvulkanimage.c
index b403768..9ef2c51 100644
--- a/gsk/gskvulkanimage.c
+++ b/gsk/gskvulkanimage.c
@@ -562,6 +562,91 @@ gsk_vulkan_image_new_for_swapchain (GdkVulkanContext *context,
return self;
}
+GskVulkanImage *
+gsk_vulkan_image_new_for_framebuffer (GdkVulkanContext *context,
+ gsize width,
+ gsize height)
+{
+ GskVulkanImage *self;
+
+
+ self = gsk_vulkan_image_new (context,
+ width,
+ height,
+ VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+
+ gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_SRGB);
+
+ return self;
+}
+
+GskTexture *
+gsk_vulkan_image_download (GskVulkanImage *self,
+ GskVulkanUploader *uploader)
+{
+ GskVulkanBuffer *buffer;
+ GskTexture *texture;
+ guchar *mem;
+
+ gsk_vulkan_uploader_add_image_barrier (uploader,
+ FALSE,
+ &(VkImageMemoryBarrier) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+ .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
+ .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+ .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+ .image = self->vk_image,
+ .subresourceRange = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1
+ }
+ });
+
+ 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,
+ gsk_vulkan_buffer_get_buffer (buffer),
+ 1,
+ (VkBufferImageCopy[1]) {
+ {
+ .bufferOffset = 0,
+ .imageSubresource = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ .baseArrayLayer = 0,
+ .layerCount = 1
+ },
+ .imageOffset = { 0, 0, 0 },
+ .imageExtent = {
+ .width = self->width,
+ .height = self->height,
+ .depth = 1
+ }
+ }
+ });
+
+ gsk_vulkan_uploader_upload (uploader);
+
+ GSK_VK_CHECK (vkQueueWaitIdle, gdk_vulkan_context_get_queue (self->vulkan));
+
+ mem = gsk_vulkan_buffer_map (buffer);
+ texture = gsk_texture_new_for_data (mem, self->width, self->height, self->width * 4);
+ gsk_vulkan_buffer_unmap (buffer);
+ gsk_vulkan_buffer_free (buffer);
+
+ return texture;
+}
+
void
gsk_vulkan_image_finalize (GObject *object)
{
diff --git a/gsk/gskvulkanimageprivate.h b/gsk/gskvulkanimageprivate.h
index 45d8ca2..feade29 100644
--- a/gsk/gskvulkanimageprivate.h
+++ b/gsk/gskvulkanimageprivate.h
@@ -3,6 +3,7 @@
#include <gdk/gdk.h>
+#include "gsk/gsktexture.h"
#include "gsk/gskvulkancommandpoolprivate.h"
G_BEGIN_DECLS
@@ -30,6 +31,12 @@ GskVulkanImage * gsk_vulkan_image_new_from_data (GskVulk
gsize width,
gsize height,
gsize stride);
+GskVulkanImage * gsk_vulkan_image_new_for_framebuffer (GdkVulkanContext *context,
+ gsize width,
+ gsize height);
+
+GskTexture * gsk_vulkan_image_download (GskVulkanImage *self,
+ GskVulkanUploader *uploader);
gsize gsk_vulkan_image_get_width (GskVulkanImage *self);
gsize gsk_vulkan_image_get_height (GskVulkanImage *self);
diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c
index 05ca19c..eabdd6f 100644
--- a/gsk/gskvulkanrender.c
+++ b/gsk/gskvulkanrender.c
@@ -24,7 +24,7 @@ struct _GskVulkanRender
graphene_matrix_t mvp;
int scale_factor;
- VkExtent2D size;
+ VkRect2D viewport;
VkRect2D scissor;
GHashTable *framebuffers;
@@ -48,29 +48,41 @@ struct _GskVulkanRender
};
static void
-gsk_vulkan_render_compute_mvp (GskVulkanRender *self)
+gsk_vulkan_render_compute_mvp (GskVulkanRender *self,
+ const graphene_rect_t *rect)
{
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;
+ if (rect)
+ {
+ self->scissor = (VkRect2D) { { rect->origin.x, rect->origin.y }, { rect->size.width, rect->size.height
} };
+ self->viewport = self->scissor;
+ self->scale_factor = 1;
+ }
+ else
+ {
+ 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->viewport.offset = (VkOffset2D) { 0, 0 };
+ self->viewport.extent.width = gdk_window_get_width (window) * self->scale_factor;
+ self->viewport.extent.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,
+ self->viewport.offset.x, self->viewport.extent.width,
+ self->viewport.offset.y, self->viewport.extent.height,
ORTHO_NEAR_PLANE,
ORTHO_FAR_PLANE);
+
graphene_matrix_multiply (&modelview, &projection, &self->mvp);
}
@@ -450,10 +462,10 @@ gsk_vulkan_render_draw (GskVulkanRender *self,
0,
1,
&(VkViewport) {
- .x = 0,
- .y = 0,
- .width = self->size.width,
- .height = self->size.height,
+ .x = self->viewport.offset.x,
+ .y = self->viewport.offset.x,
+ .width = self->viewport.extent.width,
+ .height = self->viewport.extent.height,
.minDepth = 0,
.maxDepth = 1
});
@@ -470,7 +482,10 @@ gsk_vulkan_render_draw (GskVulkanRender *self,
.framebuffer = gsk_vulkan_render_get_framebuffer (self, self->target),
.renderArea = {
{ 0, 0 },
- { self->size.width, self->size.height }
+ {
+ gsk_vulkan_image_get_width (self->target),
+ gsk_vulkan_image_get_height (self->target)
+ }
},
.clearValueCount = 1,
.pClearValues = (VkClearValue [1]) {
@@ -500,6 +515,14 @@ gsk_vulkan_render_draw (GskVulkanRender *self,
}
}
+GskTexture *
+gsk_vulkan_render_download_target (GskVulkanRender *self)
+{
+ gsk_vulkan_uploader_reset (self->uploader);
+
+ return gsk_vulkan_image_download (self->target, self->uploader);
+}
+
static void
gsk_vulkan_render_cleanup (GskVulkanRender *self)
{
@@ -589,14 +612,15 @@ gsk_vulkan_render_is_busy (GskVulkanRender *self)
}
void
-gsk_vulkan_render_reset (GskVulkanRender *self,
- GskVulkanImage *target)
+gsk_vulkan_render_reset (GskVulkanRender *self,
+ GskVulkanImage *target,
+ const graphene_rect_t *rect)
{
gsk_vulkan_render_cleanup (self);
self->target = g_object_ref (target);
- gsk_vulkan_render_compute_mvp (self);
+ gsk_vulkan_render_compute_mvp (self, rect);
}
GskRenderer *
diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c
index bb3d79b..747ed09 100644
--- a/gsk/gskvulkanrenderer.c
+++ b/gsk/gskvulkanrenderer.c
@@ -170,6 +170,54 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer)
g_clear_object (&self->vulkan);
}
+static GskTexture *
+gsk_vulkan_renderer_render_texture (GskRenderer *renderer,
+ GskRenderNode *root,
+ const graphene_rect_t *viewport)
+{
+ GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
+ GskVulkanRender *render;
+ GskVulkanImage *image;
+ GskTexture *texture;
+#ifdef G_ENABLE_DEBUG
+ GskProfiler *profiler;
+ gint64 cpu_time;
+#endif
+
+#ifdef G_ENABLE_DEBUG
+ profiler = gsk_renderer_get_profiler (renderer);
+ gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
+#endif
+
+ render = gsk_vulkan_render_new (renderer, self->vulkan);
+
+ image = gsk_vulkan_image_new_for_framebuffer (self->vulkan,
+ ceil (viewport->size.width),
+ ceil (viewport->size.height));
+
+ gsk_vulkan_render_reset (render, image, viewport);
+
+ gsk_vulkan_render_add_node (render, root);
+
+ gsk_vulkan_render_upload (render);
+
+ gsk_vulkan_render_draw (render, self->sampler);
+
+ texture = gsk_vulkan_render_download_target (render);
+
+ g_object_unref (image);
+ gsk_vulkan_render_free (render);
+
+#ifdef G_ENABLE_DEBUG
+ cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time);
+ gsk_profiler_timer_set (profiler, self->profile_timers.cpu_time, cpu_time);
+
+ gsk_profiler_push_samples (profiler);
+#endif
+
+ return texture;
+}
+
static void
gsk_vulkan_renderer_render (GskRenderer *renderer,
GskRenderNode *root)
@@ -188,7 +236,7 @@ gsk_vulkan_renderer_render (GskRenderer *renderer,
render = self->render;
- gsk_vulkan_render_reset (render, self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)]);
+ gsk_vulkan_render_reset (render, self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)], NULL);
gsk_vulkan_render_add_node (render, root);
@@ -238,6 +286,7 @@ gsk_vulkan_renderer_class_init (GskVulkanRendererClass *klass)
renderer_class->realize = gsk_vulkan_renderer_realize;
renderer_class->unrealize = gsk_vulkan_renderer_unrealize;
renderer_class->render = gsk_vulkan_renderer_render;
+ renderer_class->render_texture = gsk_vulkan_renderer_render_texture;
renderer_class->begin_draw_frame = gsk_vulkan_renderer_begin_draw_frame;
}
diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h
index 5696dd3..e44f263 100644
--- a/gsk/gskvulkanrenderprivate.h
+++ b/gsk/gskvulkanrenderprivate.h
@@ -24,7 +24,8 @@ void gsk_vulkan_render_free (GskVulk
gboolean gsk_vulkan_render_is_busy (GskVulkanRender *self);
void gsk_vulkan_render_reset (GskVulkanRender *self,
- GskVulkanImage *target);
+ GskVulkanImage *target,
+ const graphene_rect_t *rect);
GskRenderer * gsk_vulkan_render_get_renderer (GskVulkanRender *self);
@@ -47,6 +48,8 @@ void gsk_vulkan_render_draw (GskVulk
void gsk_vulkan_render_submit (GskVulkanRender *self);
+GskTexture * gsk_vulkan_render_download_target (GskVulkanRender *self);
+
G_END_DECLS
#endif /* __GSK_VULKAN_RENDER_PRIVATE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]