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.
This commit is contained in:
Benjamin Otte 2016-12-05 02:50:06 +01:00
parent 3f7cc013cc
commit 2a0e7f8829
14 changed files with 796 additions and 25 deletions

View File

@ -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>" >> $@

88
gsk/gskvulkanbuffer.c Normal file
View File

@ -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);
}

View File

@ -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__ */

95
gsk/gskvulkanmemory.c Normal file
View File

@ -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);
}

View File

@ -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__ */

176
gsk/gskvulkanpipeline.c Normal file
View File

@ -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;
}

View File

@ -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__ */

View File

@ -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);
@ -262,11 +271,106 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer)
g_clear_object (&self->vulkan);
}
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
}

102
gsk/gskvulkanshader.c Normal file
View File

@ -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;
}

View File

@ -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__ */

View File

@ -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);
}

Binary file not shown.

View File

@ -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);
}

Binary file not shown.