[gtk+/wip/otte/vulkan: 39/39] gsk: Loads of work on Vulkan backend
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/vulkan: 39/39] gsk: Loads of work on Vulkan backend
- Date: Mon, 5 Dec 2016 14:38:25 +0000 (UTC)
commit 4a1334749ac5e84f25e3e318fff246626c7f35aa
Author: Benjamin Otte <otte redhat com>
Date: Mon Dec 5 02:50:06 2016 +0100
gsk: Loads of work on Vulkan backend
We can now upload vertices.
And we use this to draw a yellow background. Which is clearly superior
to not drawing anything.
Also, we have shaders now. If you modify them, you need glslc installed
so they can be recompiled into Spir-V bytecode.
gsk/Makefile.am | 29 +++++-
gsk/gskvulkanbuffer.c | 88 +++++++++++++++
gsk/gskvulkanbufferprivate.h | 21 ++++
gsk/gskvulkanmemory.c | 95 +++++++++++++++++
gsk/gskvulkanmemoryprivate.h | 23 ++++
gsk/gskvulkanpipeline.c | 176 ++++++++++++++++++++++++++++++
gsk/gskvulkanpipelineprivate.h | 34 ++++++
gsk/gskvulkanrenderer.c | 200 +++++++++++++++++++++++++++++++----
gsk/gskvulkanshader.c | 102 ++++++++++++++++++
gsk/gskvulkanshaderprivate.h | 34 ++++++
gsk/resources/vulkan/blit.frag.glsl | 8 ++
gsk/resources/vulkan/blit.frag.spv | Bin 0 -> 420 bytes
gsk/resources/vulkan/blit.vert.glsl | 11 ++
gsk/resources/vulkan/blit.vert.spv | Bin 0 -> 692 bytes
14 files changed, 796 insertions(+), 25 deletions(-)
---
diff --git a/gsk/Makefile.am b/gsk/Makefile.am
index 77bfc0e..84ae987 100644
--- a/gsk/Makefile.am
+++ b/gsk/Makefile.am
@@ -24,9 +24,17 @@ noinst_LTLIBRARIES =
if HAVE_VULKAN
gsk_private_vulan_source_h = \
- gskvulkanrendererprivate.h
+ gskvulkanbufferprivate.h \
+ gskvulkanmemoryprivate.h \
+ gskvulkanpipelineprivate.h \
+ gskvulkanrendererprivate.h \
+ gskvulkanshaderprivate.h
gsk_private_vulkan_source_c = \
- gskvulkanrenderer.c
+ gskvulkanbuffer.c \
+ gskvulkanmemory.c \
+ gskvulkanpipeline.c \
+ gskvulkanrenderer.c \
+ gskvulkanshader.c
endif
gsk_public_source_h = \
@@ -48,7 +56,6 @@ gsk_private_source_h = \
gskrendererprivate.h \
gskrendernodeprivate.h \
gskshaderbuilderprivate.h \
- gskvulkanrendererprivate.h \
gsktextureprivate.h
gsk_public_source_c = \
gskrenderer.c \
@@ -95,6 +102,14 @@ DISTCLEANFILES += gskenumtypes.h gskenumtypes.c
resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies
$(builddir)/gsk.resources.xml)
+resources/vulkan/%.frag.spv: resources/vulkan/%.frag.glsl
+ @if test -z "$(GLSLC)"; then echo "Missing glslc. See https://github.com/google/shaderc"; exit 1; fi
+ $(AM_V_GEN) $(GLSLC) -fshader-stage=fragment -o $@.tmp $< && mv $@.tmp $@
+
+resources/vulkan/%.vert.spv: resources/vulkan/%.vert.glsl
+ @if test -z "$(GLSLC)"; then echo "Missing glslc. See https://github.com/google/shaderc"; exit 1; fi
+ $(AM_V_GEN) $(GLSLC) -fshader-stage=vertex -o $@.tmp $< && mv $@.tmp $@
+
gsk.resources.xml: Makefile.am
$(AM_V_GEN) echo "<?xml version='1.0' encoding='UTF-8'?>" > $@; \
echo "<gresources>" >> $@; \
@@ -103,6 +118,14 @@ gsk.resources.xml: Makefile.am
n=`basename $$f`; \
echo " <file alias='glsl/$$n'>resources/glsl/$$n</file>" >> $@; \
done; \
+ for f in $(top_srcdir)/gsk/resources/vulkan/*.spv; do \
+ n=`basename $$f`; \
+ echo " <file alias='vulkan/$$n'>resources/vulkan/$$n</file>" >> $@; \
+ done; \
+ for f in $(top_srcdir)/gsk/resources/vulkan/*.glsl; do \
+ n=`basename $$f`; \
+ echo " <file alias='vulkan/$$n'>resources/vulkan/$$n</file>" >> $@; \
+ done; \
echo " </gresource>" >> $@; \
echo "</gresources>" >> $@
diff --git a/gsk/gskvulkanbuffer.c b/gsk/gskvulkanbuffer.c
new file mode 100644
index 0000000..6694131
--- /dev/null
+++ b/gsk/gskvulkanbuffer.c
@@ -0,0 +1,88 @@
+#include "config.h"
+
+#include "gskvulkanbufferprivate.h"
+#include "gskvulkanmemoryprivate.h"
+#include "gskvulkanpipelineprivate.h"
+
+struct _GskVulkanBuffer
+{
+ GdkVulkanContext *vulkan;
+
+ gsize size;
+
+ VkBuffer vk_buffer;
+
+ GskVulkanMemory *memory;
+};
+
+GskVulkanBuffer *
+gsk_vulkan_buffer_new (GdkVulkanContext *context,
+ gsize size)
+{
+ VkMemoryRequirements requirements;
+ GskVulkanBuffer *self;
+
+ self = g_slice_new0 (GskVulkanBuffer);
+
+ self->vulkan = g_object_ref (context);
+ self->size = size;
+
+ GSK_VK_CHECK (vkCreateBuffer, gdk_vulkan_context_get_device (context),
+ &(VkBufferCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ .size = size,
+ .flags = 0,
+ .usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
+ | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
+ .sharingMode = VK_SHARING_MODE_EXCLUSIVE
+ },
+ NULL,
+ &self->vk_buffer);
+
+ vkGetBufferMemoryRequirements (gdk_vulkan_context_get_device (context),
+ self->vk_buffer,
+ &requirements);
+
+ self->memory = gsk_vulkan_memory_new (context,
+ requirements.memoryTypeBits,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+ size);
+
+ GSK_VK_CHECK (vkBindBufferMemory, gdk_vulkan_context_get_device (context),
+ self->vk_buffer,
+ gsk_vulkan_memory_get_device_memory (self->memory),
+ 0);
+ return self;
+}
+
+void
+gsk_vulkan_buffer_free (GskVulkanBuffer *self)
+{
+ gsk_vulkan_memory_free (self->memory);
+
+ vkDestroyBuffer (gdk_vulkan_context_get_device (self->vulkan),
+ self->vk_buffer,
+ NULL);
+
+ g_object_unref (self->vulkan);
+
+ g_slice_free (GskVulkanBuffer, self);
+}
+
+VkBuffer
+gsk_vulkan_buffer_get_buffer (GskVulkanBuffer *self)
+{
+ return self->vk_buffer;
+}
+
+guchar *
+gsk_vulkan_buffer_map (GskVulkanBuffer *self)
+{
+ return gsk_vulkan_memory_map (self->memory);
+}
+
+void
+gsk_vulkan_buffer_unmap (GskVulkanBuffer *self)
+{
+ gsk_vulkan_memory_unmap (self->memory);
+}
diff --git a/gsk/gskvulkanbufferprivate.h b/gsk/gskvulkanbufferprivate.h
new file mode 100644
index 0000000..e497192
--- /dev/null
+++ b/gsk/gskvulkanbufferprivate.h
@@ -0,0 +1,21 @@
+#ifndef __GSK_VULKAN_BUFFER_PRIVATE_H__
+#define __GSK_VULKAN_BUFFER_PRIVATE_H__
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GskVulkanBuffer GskVulkanBuffer;
+
+GskVulkanBuffer * gsk_vulkan_buffer_new (GdkVulkanContext *context,
+ gsize size);
+void gsk_vulkan_buffer_free (GskVulkanBuffer *buffer);
+
+VkBuffer gsk_vulkan_buffer_get_buffer (GskVulkanBuffer *self);
+
+guchar * gsk_vulkan_buffer_map (GskVulkanBuffer *self);
+void gsk_vulkan_buffer_unmap (GskVulkanBuffer *self);
+
+G_END_DECLS
+
+#endif /* __GSK_VULKAN_BUFFER_PRIVATE_H__ */
diff --git a/gsk/gskvulkanmemory.c b/gsk/gskvulkanmemory.c
new file mode 100644
index 0000000..1ff4675
--- /dev/null
+++ b/gsk/gskvulkanmemory.c
@@ -0,0 +1,95 @@
+#include "config.h"
+
+#include "gskvulkanpipelineprivate.h"
+#include "gskvulkanmemoryprivate.h"
+
+struct _GskVulkanMemory
+{
+ GdkVulkanContext *vulkan;
+
+ gsize size;
+
+ VkDeviceMemory vk_memory;
+};
+
+GskVulkanMemory *
+gsk_vulkan_memory_new (GdkVulkanContext *context,
+ uint32_t allowed_types,
+ VkMemoryPropertyFlags flags,
+ gsize size)
+{
+ VkPhysicalDeviceMemoryProperties properties;
+ GskVulkanMemory *self;
+ uint32_t i;
+
+ self = g_slice_new0 (GskVulkanMemory);
+
+ self->vulkan = g_object_ref (context);
+ self->size = size;
+
+ vkGetPhysicalDeviceMemoryProperties (gdk_vulkan_context_get_physical_device (context),
+ &properties);
+
+ for (i = 0; i < properties.memoryTypeCount; i++)
+ {
+ if (!(allowed_types & (1 << i)))
+ continue;
+
+ if ((properties.memoryTypes[i].propertyFlags & flags) == flags)
+ break;
+ }
+
+ g_assert (i < properties.memoryTypeCount);
+
+ GSK_VK_CHECK (vkAllocateMemory, gdk_vulkan_context_get_device (context),
+ &(VkMemoryAllocateInfo) {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .allocationSize = size,
+ .memoryTypeIndex = i
+ },
+ NULL,
+ &self->vk_memory);
+
+ return self;
+}
+
+void
+gsk_vulkan_memory_free (GskVulkanMemory *self)
+{
+ vkFreeMemory (gdk_vulkan_context_get_device (self->vulkan),
+ self->vk_memory,
+ NULL);
+
+ g_object_unref (self->vulkan);
+
+ g_slice_free (GskVulkanMemory, self);
+}
+
+VkDeviceMemory
+gsk_vulkan_memory_get_device_memory (GskVulkanMemory *self)
+{
+ return self->vk_memory;
+}
+
+guchar *
+gsk_vulkan_memory_map (GskVulkanMemory *self)
+{
+ void *data;
+
+ GSK_VK_CHECK (vkMapMemory, gdk_vulkan_context_get_device (self->vulkan),
+ self->vk_memory,
+ 0,
+ self->size,
+ 0,
+ &data);
+
+ return data;
+}
+
+void
+gsk_vulkan_memory_unmap (GskVulkanMemory *self)
+{
+ vkUnmapMemory (gdk_vulkan_context_get_device (self->vulkan),
+ self->vk_memory);
+}
+
diff --git a/gsk/gskvulkanmemoryprivate.h b/gsk/gskvulkanmemoryprivate.h
new file mode 100644
index 0000000..010c133
--- /dev/null
+++ b/gsk/gskvulkanmemoryprivate.h
@@ -0,0 +1,23 @@
+#ifndef __GSK_VULKAN_MEMORY_PRIVATE_H__
+#define __GSK_VULKAN_MEMORY_PRIVATE_H__
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GskVulkanMemory GskVulkanMemory;
+
+GskVulkanMemory * gsk_vulkan_memory_new (GdkVulkanContext *context,
+ uint32_t
allowed_types,
+ VkMemoryPropertyFlags properties,
+ gsize size);
+void gsk_vulkan_memory_free (GskVulkanMemory *memory);
+
+VkDeviceMemory gsk_vulkan_memory_get_device_memory (GskVulkanMemory *self);
+
+guchar * gsk_vulkan_memory_map (GskVulkanMemory *self);
+void gsk_vulkan_memory_unmap (GskVulkanMemory *self);
+
+G_END_DECLS
+
+#endif /* __GSK_VULKAN_MEMORY_PRIVATE_H__ */
diff --git a/gsk/gskvulkanpipeline.c b/gsk/gskvulkanpipeline.c
new file mode 100644
index 0000000..8da3f27
--- /dev/null
+++ b/gsk/gskvulkanpipeline.c
@@ -0,0 +1,176 @@
+#include "config.h"
+
+#include "gskvulkanpipelineprivate.h"
+
+#include "gskvulkanshaderprivate.h"
+
+struct _GskVulkanPipeline
+{
+ GObject parent_instance;
+
+ GdkVulkanContext *vulkan;
+
+ VkPipeline pipeline;
+ VkPipelineLayout pipeline_layout;
+
+ GskVulkanShader *vertex_shader;
+ GskVulkanShader *fragment_shader;
+};
+
+G_DEFINE_TYPE (GskVulkanPipeline, gsk_vulkan_pipeline, G_TYPE_OBJECT)
+
+static void
+gsk_vulkan_pipeline_finalize (GObject *gobject)
+{
+ GskVulkanPipeline *self = GSK_VULKAN_PIPELINE (gobject);
+ VkDevice device = gdk_vulkan_context_get_device (self->vulkan);
+
+ vkDestroyPipeline (device,
+ self->pipeline,
+ NULL);
+
+ g_clear_pointer (&self->fragment_shader, gsk_vulkan_shader_free);
+ g_clear_pointer (&self->vertex_shader, gsk_vulkan_shader_free);
+
+ vkDestroyPipelineLayout (device,
+ self->pipeline_layout,
+ NULL);
+
+ g_clear_object (&self->vulkan);
+
+ G_OBJECT_CLASS (gsk_vulkan_pipeline_parent_class)->finalize (gobject);
+}
+
+static void
+gsk_vulkan_pipeline_class_init (GskVulkanPipelineClass *klass)
+{
+ G_OBJECT_CLASS (klass)->finalize = gsk_vulkan_pipeline_finalize;
+}
+
+static void
+gsk_vulkan_pipeline_init (GskVulkanPipeline *self)
+{
+}
+
+GskVulkanPipeline *
+gsk_vulkan_pipeline_new (GdkVulkanContext *context,
+ VkRenderPass render_pass)
+{
+ GskVulkanPipeline *self;
+ VkDevice device;
+
+ g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), NULL);
+ g_return_val_if_fail (render_pass != VK_NULL_HANDLE, NULL);
+
+ device = gdk_vulkan_context_get_device (context);
+
+ self = g_object_new (GSK_TYPE_VULKAN_PIPELINE, NULL);
+
+ self->vulkan = g_object_ref (context);
+
+ GSK_VK_CHECK (vkCreatePipelineLayout, device,
+ &(VkPipelineLayoutCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ .setLayoutCount = 0,
+ },
+ NULL,
+ &self->pipeline_layout);
+
+ self->vertex_shader = gsk_vulkan_shader_new_from_resource (context, GSK_VULKAN_SHADER_VERTEX, "blit",
NULL);
+ self->fragment_shader = gsk_vulkan_shader_new_from_resource (context, GSK_VULKAN_SHADER_FRAGMENT, "blit",
NULL);
+
+ GSK_VK_CHECK (vkCreateGraphicsPipelines, device,
+ VK_NULL_HANDLE,
+ 1,
+ &(VkGraphicsPipelineCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+ .stageCount = 2,
+ .pStages = (VkPipelineShaderStageCreateInfo[2]) {
+ GST_VULKAN_SHADER_STAGE_CREATE_INFO (self->vertex_shader),
+ GST_VULKAN_SHADER_STAGE_CREATE_INFO
(self->fragment_shader)
+ },
+ .pVertexInputState = &(VkPipelineVertexInputStateCreateInfo) {
+ .sType =
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+ .vertexBindingDescriptionCount = 1,
+ .pVertexBindingDescriptions =
(VkVertexInputBindingDescription[]) {
+ {
+ .binding = 0,
+ .stride = 2 * sizeof(float),
+ .inputRate = VK_VERTEX_INPUT_RATE_VERTEX
+ }
+ },
+ .vertexAttributeDescriptionCount = 1,
+ .pVertexAttributeDescriptions =
(VkVertexInputAttributeDescription[]) {
+ {
+ .location = 0,
+ .binding = 0,
+ .format = VK_FORMAT_R32G32_SFLOAT,
+ .offset = 0,
+ }
+ }
+ },
+ .pInputAssemblyState =
&(VkPipelineInputAssemblyStateCreateInfo) {
+ .sType =
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+ .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
+ .primitiveRestartEnable = VK_FALSE,
+ },
+ .pTessellationState = NULL,
+ .pViewportState = &(VkPipelineViewportStateCreateInfo) {
+ .sType =
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
+ .viewportCount = 1,
+ .scissorCount = 1
+ },
+ .pRasterizationState =
&(VkPipelineRasterizationStateCreateInfo) {
+ .sType =
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
+ .depthClampEnable = VK_FALSE,
+ .rasterizerDiscardEnable = VK_FALSE,
+ .polygonMode = VK_POLYGON_MODE_FILL,
+ .cullMode = VK_CULL_MODE_BACK_BIT,
+ .frontFace = VK_FRONT_FACE_CLOCKWISE,
+ .lineWidth = 1.0f,
+ },
+ .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
+ .sType =
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
+ .rasterizationSamples = 1,
+ },
+ .pDepthStencilState =
&(VkPipelineDepthStencilStateCreateInfo) {
+ .sType =
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO
+ },
+ .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) {
+ .sType =
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+ .attachmentCount = 1,
+ .pAttachments = (VkPipelineColorBlendAttachmentState []) {
+ { .colorWriteMask = VK_COLOR_COMPONENT_A_BIT |
+ VK_COLOR_COMPONENT_R_BIT |
+ VK_COLOR_COMPONENT_G_BIT |
+ VK_COLOR_COMPONENT_B_BIT },
+ }
+ },
+ .pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
+ .sType =
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
+ .dynamicStateCount = 2,
+ .pDynamicStates = (VkDynamicState[2]) {
+ VK_DYNAMIC_STATE_VIEWPORT,
+ VK_DYNAMIC_STATE_SCISSOR
+ },
+ },
+ .layout = self->pipeline_layout,
+ .renderPass = render_pass,
+ .subpass = 0,
+ .basePipelineHandle = VK_NULL_HANDLE,
+ .basePipelineIndex = -1,
+ },
+ NULL,
+ &self->pipeline);
+
+
+ return self;
+}
+
+VkPipeline
+gsk_vulkan_pipeline_get_pipeline (GskVulkanPipeline *self)
+{
+ return self->pipeline;
+}
+
+
diff --git a/gsk/gskvulkanpipelineprivate.h b/gsk/gskvulkanpipelineprivate.h
new file mode 100644
index 0000000..b4e9e28
--- /dev/null
+++ b/gsk/gskvulkanpipelineprivate.h
@@ -0,0 +1,34 @@
+#ifndef __GSK_VULKAN_PIPELINE_PRIVATE_H__
+#define __GSK_VULKAN_PIPELINE_PRIVATE_H__
+
+#include <gdk/gdk.h>
+
+#include "gskdebugprivate.h"
+
+G_BEGIN_DECLS
+
+#define GSK_TYPE_VULKAN_PIPELINE (gsk_vulkan_pipeline_get_type ())
+
+G_DECLARE_FINAL_TYPE (GskVulkanPipeline, gsk_vulkan_pipeline, GSK, VULKAN_PIPELINE, GObject)
+
+static inline VkResult
+gsk_vulkan_handle_result (VkResult res,
+ const char *called_function)
+{
+ if (res != VK_SUCCESS)
+ {
+ GSK_NOTE (VULKAN,g_printerr ("%s(): %s (%d)\n", called_function, gdk_vulkan_strerror (res), res));
+ }
+ return res;
+}
+
+#define GSK_VK_CHECK(func, ...) gsk_vulkan_handle_result (func (__VA_ARGS__), G_STRINGIFY (func))
+
+GskVulkanPipeline * gsk_vulkan_pipeline_new (GdkVulkanContext *context,
+ VkRenderPass
render_pass);
+
+VkPipeline gsk_vulkan_pipeline_get_pipeline (GskVulkanPipeline *self);
+
+G_END_DECLS
+
+#endif /* __GSK_VULKAN_PIPELINE_PRIVATE_H__ */
diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c
index ccae2de..927197f 100644
--- a/gsk/gskvulkanrenderer.c
+++ b/gsk/gskvulkanrenderer.c
@@ -3,10 +3,13 @@
#include "gskvulkanrendererprivate.h"
#include "gskdebugprivate.h"
+#include "gskprivate.h"
#include "gskrendererprivate.h"
#include "gskrendernodeiter.h"
#include "gskrendernodeprivate.h"
#include "gsktextureprivate.h"
+#include "gskvulkanbufferprivate.h"
+#include "gskvulkanpipelineprivate.h"
typedef struct _GskVulkanTarget GskVulkanTarget;
@@ -28,6 +31,9 @@ struct _GskVulkanRenderer
VkRenderPass render_pass;
VkCommandPool command_pool;
+ VkFence command_pool_fence;
+
+ GskVulkanPipeline *pipeline;
#ifdef G_ENABLE_DEBUG
ProfileTimers profile_timers;
@@ -47,19 +53,6 @@ struct _GskVulkanTarget {
VkFramebuffer framebuffer;
};
-static inline VkResult
-gsk_vulkan_handle_result (VkResult res,
- const char *called_function)
-{
- if (res != VK_SUCCESS)
- {
- GSK_NOTE (VULKAN,g_printerr ("%s(): %s (%d)\n", called_function, gdk_vulkan_strerror (res), res));
- }
- return res;
-}
-
-#define GSK_VK_CHECK(func, ...) gsk_vulkan_handle_result (func (__VA_ARGS__), G_STRINGIFY (func))
-
static GskVulkanTarget *
gsk_vulkan_target_new_for_image (GskVulkanRenderer *self,
VkImage image)
@@ -218,14 +211,25 @@ gsk_vulkan_renderer_realize (GskRenderer *renderer,
},
NULL,
&self->render_pass);
- GSK_VK_CHECK (vkCreateCommandPool, device,
- &(const VkCommandPoolCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
- .queueFamilyIndex = gdk_vulkan_context_get_queue_family_index
(self->vulkan),
- .flags = 0
- },
- NULL,
- &self->command_pool);
+ GSK_VK_CHECK (vkCreateCommandPool, device,
+ &(const VkCommandPoolCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ .queueFamilyIndex = gdk_vulkan_context_get_queue_family_index
(self->vulkan),
+ .flags = 0
+ },
+ NULL,
+ &self->command_pool);
+
+ GSK_VK_CHECK (vkCreateFence, device,
+ &(VkFenceCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ .flags = 0
+ },
+ NULL,
+ &self->command_pool_fence);
+
+
+ self->pipeline = gsk_vulkan_pipeline_new (self->vulkan, self->render_pass);
g_signal_connect (self->vulkan,
"images-updated",
@@ -249,6 +253,11 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer)
gsk_vulkan_renderer_update_images_cb,
self);
+ vkDestroyFence (device,
+ self->command_pool_fence,
+ NULL);
+ self->command_pool_fence = VK_NULL_HANDLE;
+
vkDestroyCommandPool (device,
self->command_pool,
NULL);
@@ -263,10 +272,105 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer)
}
static void
+gsk_vulkan_renderer_do_render_commands (GskVulkanRenderer *self,
+ VkCommandBuffer command_buffer)
+{
+ GskVulkanBuffer *buffer;
+ float pts[] = {
+ -1.0, -1.0,
+ 1.0, -1.0,
+ -1.0, 1.0,
+
+ -1.0, 1.0,
+ 1.0, -1.0,
+ 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));
+
+ 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);
+}
+
+static void
+gsk_vulkan_renderer_do_render_pass (GskVulkanRenderer *self,
+ VkCommandBuffer command_buffer,
+ GskRenderNode *root)
+{
+ GdkRectangle extents;
+ GdkWindow *window;
+
+ 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);
+
+ 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 },
+ { gdk_window_get_width (window), gdk_window_get_height (window) }
+ },
+ .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 = gdk_window_get_width (window),
+ .height = gdk_window_get_height (window),
+ .minDepth = 0,
+ .maxDepth = 1
+ });
+
+ vkCmdSetScissor (command_buffer,
+ 0,
+ 1,
+ &(VkRect2D) {
+ { extents.x, extents.y },
+ { extents.width, extents.height }
+ });
+
+ gsk_vulkan_renderer_do_render_commands (self, command_buffer);
+
+ vkCmdEndRenderPass (command_buffer);
+}
+
+static void
gsk_vulkan_renderer_render (GskRenderer *renderer,
GskRenderNode *root)
{
GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
+ VkCommandBuffer command_buffer;
#ifdef G_ENABLE_DEBUG
GskProfiler *profiler;
gint64 cpu_time;
@@ -277,6 +381,54 @@ gsk_vulkan_renderer_render (GskRenderer *renderer,
gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
#endif
+ GSK_VK_CHECK (vkAllocateCommandBuffers, gdk_vulkan_context_get_device (self->vulkan),
+ &(VkCommandBufferAllocateInfo) {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ .commandPool = self->command_pool,
+ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ .commandBufferCount = 1,
+ },
+ &command_buffer);
+
+ GSK_VK_CHECK (vkBeginCommandBuffer, command_buffer,
+ &(VkCommandBufferBeginInfo) {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ .flags = 0
+ });
+
+ gsk_vulkan_renderer_do_render_pass (self, command_buffer, root);
+
+ GSK_VK_CHECK (vkEndCommandBuffer, command_buffer);
+
+ 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,
+ },
+ .commandBufferCount = 1,
+ .pCommandBuffers = &command_buffer,
+ },
+ self->command_pool_fence);
+
+ GSK_VK_CHECK (vkWaitForFences, gdk_vulkan_context_get_device (self->vulkan),
+ 1,
+ &self->command_pool_fence,
+ true,
+ INT64_MAX);
+ GSK_VK_CHECK (vkResetFences, gdk_vulkan_context_get_device (self->vulkan),
+ 1,
+ &self->command_pool_fence);
+
+ GSK_VK_CHECK (vkResetCommandPool, gdk_vulkan_context_get_device (self->vulkan),
+ self->command_pool,
+ 0);
+
#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);
@@ -304,7 +456,7 @@ gsk_vulkan_renderer_begin_draw_frame (GskRenderer *renderer,
result = gdk_window_begin_draw_frame (window,
GDK_DRAW_CONTEXT (self->vulkan),
- region);
+ whole_window);
cairo_region_destroy (whole_window);
@@ -327,7 +479,11 @@ gsk_vulkan_renderer_init (GskVulkanRenderer *self)
{
#ifdef G_ENABLE_DEBUG
GskProfiler *profiler = gsk_renderer_get_profiler (GSK_RENDERER (self));
+#endif
+
+ gsk_ensure_resources ();
+#ifdef G_ENABLE_DEBUG
self->profile_timers.cpu_time = gsk_profiler_add_timer (profiler, "cpu-time", "CPU time", FALSE, TRUE);
#endif
}
diff --git a/gsk/gskvulkanshader.c b/gsk/gskvulkanshader.c
new file mode 100644
index 0000000..1010b21
--- /dev/null
+++ b/gsk/gskvulkanshader.c
@@ -0,0 +1,102 @@
+#include "config.h"
+
+#include "gskvulkanshaderprivate.h"
+#include "gskvulkanpipelineprivate.h"
+
+struct _GskVulkanShader
+{
+ GdkVulkanContext *vulkan;
+
+ GskVulkanShaderType type;
+ VkShaderModule vk_shader;
+};
+
+static GskVulkanShader *
+gsk_vulkan_shader_new_from_bytes (GdkVulkanContext *context,
+ GskVulkanShaderType type,
+ GBytes *bytes,
+ GError **error)
+{
+ GskVulkanShader *self;
+ VkShaderModule shader;
+ VkResult res;
+
+ res = GSK_VK_CHECK (vkCreateShaderModule, gdk_vulkan_context_get_device (context),
+ &(VkShaderModuleCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ .codeSize = g_bytes_get_size (bytes),
+ .pCode = (uint32_t *) g_bytes_get_data (bytes, NULL),
+ },
+ NULL,
+ &shader);
+ if (res != VK_SUCCESS)
+ {
+ /* Someone invent better error categories plz */
+ g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
+ "Could not create shader: %s", gdk_vulkan_strerror (res));
+ return NULL;
+ }
+
+ self = g_slice_new0 (GskVulkanShader);
+
+ self->vulkan = g_object_ref (context);
+ self->type = type;
+ self->vk_shader = shader;
+
+ return self;
+}
+
+GskVulkanShader *
+gsk_vulkan_shader_new_from_resource (GdkVulkanContext *context,
+ GskVulkanShaderType type,
+ const char *resource_name,
+ GError **error)
+{
+ GskVulkanShader *self;
+ GBytes *bytes;
+ GError *local_error = NULL;
+ char *path;
+
+ path = g_strconcat ("/org/gtk/libgsk/vulkan/",
+ resource_name,
+ type == GSK_VULKAN_SHADER_VERTEX ? ".vert.spv" : ".frag.spv",
+ NULL);
+ bytes = g_resources_lookup_data (path, 0, &local_error);
+ g_free (path);
+ if (bytes == NULL)
+ {
+ GSK_NOTE (VULKAN, g_printerr ("Error loading shader data: %s\n", local_error->message));
+ g_propagate_error (error, local_error);
+ return NULL;
+ }
+
+ self = gsk_vulkan_shader_new_from_bytes (context, type, bytes, error);
+ g_bytes_unref (bytes);
+
+ return self;
+}
+
+void
+gsk_vulkan_shader_free (GskVulkanShader *self)
+{
+ vkDestroyShaderModule (gdk_vulkan_context_get_device (self->vulkan),
+ self->vk_shader,
+ NULL);
+
+ g_object_unref (self->vulkan);
+
+ g_slice_free (GskVulkanShader, self);
+}
+
+GskVulkanShaderType
+gsk_vulkan_shader_get_type (GskVulkanShader *shader)
+{
+ return shader->type;
+}
+
+VkShaderModule
+gsk_vulkan_shader_get_module (GskVulkanShader *shader)
+{
+ return shader->vk_shader;
+}
+
diff --git a/gsk/gskvulkanshaderprivate.h b/gsk/gskvulkanshaderprivate.h
new file mode 100644
index 0000000..e94424f
--- /dev/null
+++ b/gsk/gskvulkanshaderprivate.h
@@ -0,0 +1,34 @@
+#ifndef __GSK_VULKAN_SHADER_PRIVATE_H__
+#define __GSK_VULKAN_SHADER_PRIVATE_H__
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ GSK_VULKAN_SHADER_VERTEX,
+ GSK_VULKAN_SHADER_FRAGMENT
+} GskVulkanShaderType;
+
+typedef struct _GskVulkanShader GskVulkanShader;
+
+#define GST_VULKAN_SHADER_STAGE_CREATE_INFO(shader) \
+ (VkPipelineShaderStageCreateInfo) { \
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, \
+ .stage = gsk_vulkan_shader_get_type (shader) == GSK_VULKAN_SHADER_VERTEX ? VK_SHADER_STAGE_VERTEX_BIT :
VK_SHADER_STAGE_FRAGMENT_BIT, \
+ .module = gsk_vulkan_shader_get_module (shader), \
+ .pName = "main", \
+}
+
+GskVulkanShader * gsk_vulkan_shader_new_from_resource (GdkVulkanContext *context,
+ GskVulkanShaderType type,
+ const char
*resource_name,
+ GError **error);
+void gsk_vulkan_shader_free (GskVulkanShader *shader);
+
+GskVulkanShaderType gsk_vulkan_shader_get_type (GskVulkanShader *shader);
+VkShaderModule gsk_vulkan_shader_get_module (GskVulkanShader *shader);
+
+G_END_DECLS
+
+#endif /* __GSK_VULKAN_SHADER_PRIVATE_H__ */
diff --git a/gsk/resources/vulkan/blit.frag.glsl b/gsk/resources/vulkan/blit.frag.glsl
new file mode 100644
index 0000000..94f76e4
--- /dev/null
+++ b/gsk/resources/vulkan/blit.frag.glsl
@@ -0,0 +1,8 @@
+#version 420 core
+
+layout(location = 0) out vec4 color;
+
+void main()
+{
+ color = vec4(1.0, 1.0, 0.0, 1.0);
+}
diff --git a/gsk/resources/vulkan/blit.frag.spv b/gsk/resources/vulkan/blit.frag.spv
new file mode 100644
index 0000000..76adb08
Binary files /dev/null and b/gsk/resources/vulkan/blit.frag.spv differ
diff --git a/gsk/resources/vulkan/blit.vert.glsl b/gsk/resources/vulkan/blit.vert.glsl
new file mode 100644
index 0000000..ae45000
--- /dev/null
+++ b/gsk/resources/vulkan/blit.vert.glsl
@@ -0,0 +1,11 @@
+#version 420 core
+
+layout(location = 0) in vec2 inPosition;
+
+out gl_PerVertex {
+ vec4 gl_Position;
+};
+
+void main() {
+ gl_Position = vec4(inPosition, 0.0, 1.0);
+}
diff --git a/gsk/resources/vulkan/blit.vert.spv b/gsk/resources/vulkan/blit.vert.spv
new file mode 100644
index 0000000..41ea691
Binary files /dev/null and b/gsk/resources/vulkan/blit.vert.spv differ
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]