From 83960622e3f7eb21dd5bb45639ce171f55d0d8b9 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 28 Jun 2023 05:43:53 +0200 Subject: [PATCH] vulkan: Store shaders in the display Have a resource path => vkShaderModule hash table instead of doing fancy custom objects. A benefit is that shader modules are now shared between all renderers and pipelines. --- gdk/gdkdisplayprivate.h | 1 + gdk/gdkvulkancontext.c | 56 +++++++++++++++ gdk/gdkvulkancontextprivate.h | 3 + gsk/meson.build | 1 - gsk/vulkan/gskvulkanpipeline.c | 31 ++++++--- gsk/vulkan/gskvulkanshader.c | 102 ---------------------------- gsk/vulkan/gskvulkanshaderprivate.h | 32 --------- 7 files changed, 80 insertions(+), 146 deletions(-) delete mode 100644 gsk/vulkan/gskvulkanshader.c delete mode 100644 gsk/vulkan/gskvulkanshaderprivate.h diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h index 72353cf207..9e829f617f 100644 --- a/gdk/gdkdisplayprivate.h +++ b/gdk/gdkdisplayprivate.h @@ -104,6 +104,7 @@ struct _GdkDisplay gsize vk_pipeline_cache_size; char *vk_pipeline_cache_etag; guint vk_save_pipeline_cache_source; + GHashTable *vk_shader_modules; guint vulkan_refcount; #endif /* GDK_RENDERING_VULKAN */ diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c index 4b7efecddc..50bf9f8c72 100644 --- a/gdk/gdkvulkancontext.c +++ b/gdk/gdkvulkancontext.c @@ -1600,6 +1600,8 @@ gdk_display_create_vulkan_instance (GdkDisplay *display, gdk_display_create_pipeline_cache (display); + display->vk_shader_modules = g_hash_table_new (g_str_hash, g_str_equal); + return TRUE; } @@ -1621,6 +1623,9 @@ gdk_display_ref_vulkan (GdkDisplay *display, void gdk_display_unref_vulkan (GdkDisplay *display) { + GHashTableIter iter; + gpointer key, value; + g_return_if_fail (GDK_IS_DISPLAY (display)); g_return_if_fail (display->vulkan_refcount > 0); @@ -1628,6 +1633,16 @@ gdk_display_unref_vulkan (GdkDisplay *display) if (display->vulkan_refcount > 0) return; + display->vk_shader_modules = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_iter_init (&iter, display->vk_shader_modules); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + g_free (key); + vkDestroyShaderModule (display->vk_device, + value, + NULL); + } + if (display->vk_save_pipeline_cache_source) { gdk_vulkan_save_pipeline_cache_cb (display); @@ -1654,6 +1669,47 @@ gdk_display_unref_vulkan (GdkDisplay *display) display->vk_instance = VK_NULL_HANDLE; } +VkShaderModule +gdk_display_get_vk_shader_module (GdkDisplay *self, + const char *resource_name) +{ + VkShaderModule shader; + GError *error = NULL; + GBytes *bytes; + + shader = g_hash_table_lookup (self->vk_shader_modules, resource_name); + if (shader) + return shader; + + bytes = g_resources_lookup_data (resource_name, 0, &error); + if (bytes == NULL) + { + GDK_DEBUG (VULKAN, "Error loading shader data: %s", error->message); + g_clear_error (&error); + return VK_NULL_HANDLE; + } + + if (GDK_VK_CHECK (vkCreateShaderModule, self->vk_device, + &(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) == VK_SUCCESS) + { + g_hash_table_insert (self->vk_shader_modules, g_strdup (resource_name), shader); + } + else + { + shader = VK_NULL_HANDLE; + } + + g_bytes_unref (bytes); + + return shader; +} + #else /* GDK_RENDERING_VULKAN */ static void diff --git a/gdk/gdkvulkancontextprivate.h b/gdk/gdkvulkancontextprivate.h index 479dc86afc..2c6a0ee4ae 100644 --- a/gdk/gdkvulkancontextprivate.h +++ b/gdk/gdkvulkancontextprivate.h @@ -73,6 +73,9 @@ gboolean gdk_display_ref_vulkan (GdkDisp GError **error); void gdk_display_unref_vulkan (GdkDisplay *display); +VkShaderModule gdk_display_get_vk_shader_module (GdkDisplay *display, + const char *resource_name); + VkPipelineCache gdk_vulkan_context_get_pipeline_cache (GdkVulkanContext *self); void gdk_vulkan_context_pipeline_cache_updated (GdkVulkanContext *self); diff --git a/gsk/meson.build b/gsk/meson.build index df886cb4c9..333b33f6a8 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -131,7 +131,6 @@ if have_vulkan 'vulkan/gskvulkanrenderer.c', 'vulkan/gskvulkanrenderpass.c', 'vulkan/gskvulkanscissorop.c', - 'vulkan/gskvulkanshader.c', 'vulkan/gskvulkantextpipeline.c', 'vulkan/gskvulkantexturepipeline.c', 'vulkan/gskvulkantextureop.c', diff --git a/gsk/vulkan/gskvulkanpipeline.c b/gsk/vulkan/gskvulkanpipeline.c index ca4699e699..1d4b2937f5 100644 --- a/gsk/vulkan/gskvulkanpipeline.c +++ b/gsk/vulkan/gskvulkanpipeline.c @@ -3,7 +3,6 @@ #include "gskvulkanpipelineprivate.h" #include "gskvulkanpushconstantsprivate.h" -#include "gskvulkanshaderprivate.h" #include "gdk/gdkvulkancontextprivate.h" @@ -19,9 +18,6 @@ struct _GskVulkanPipelinePrivate VkPipeline pipeline; - GskVulkanShader *vertex_shader; - GskVulkanShader *fragment_shader; - gsize vertex_stride; }; @@ -39,9 +35,6 @@ gsk_vulkan_pipeline_finalize (GObject *gobject) priv->pipeline, NULL); - g_clear_pointer (&priv->fragment_shader, gsk_vulkan_shader_free); - g_clear_pointer (&priv->vertex_shader, gsk_vulkan_shader_free); - G_OBJECT_CLASS (gsk_vulkan_pipeline_parent_class)->finalize (gobject); } @@ -66,7 +59,9 @@ gsk_vulkan_pipeline_new (GType pipeline_type, const VkPipelineVertexInputStateCreateInfo *vertex_input_state; GskVulkanPipelinePrivate *priv; GskVulkanPipeline *self; + GdkDisplay *display; VkDevice device; + char *vertex_shader_name, *fragment_shader_name; g_return_val_if_fail (g_type_is_a (pipeline_type, GSK_TYPE_VULKAN_PIPELINE), NULL); g_return_val_if_fail (layout != VK_NULL_HANDLE, NULL); @@ -77,12 +72,13 @@ gsk_vulkan_pipeline_new (GType pipeline_type, priv = gsk_vulkan_pipeline_get_instance_private (self); + display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)); device = gdk_vulkan_context_get_device (context); priv->context = context; - priv->vertex_shader = gsk_vulkan_shader_new_from_resource (context, GSK_VULKAN_SHADER_VERTEX, shader_name, NULL); - priv->fragment_shader = gsk_vulkan_shader_new_from_resource (context, GSK_VULKAN_SHADER_FRAGMENT, shader_name, NULL); + vertex_shader_name = g_strconcat ("/org/gtk/libgsk/vulkan/", shader_name, ".vert.spv", NULL); + fragment_shader_name = g_strconcat ("/org/gtk/libgsk/vulkan/", shader_name, ".frag.spv", NULL); vertex_input_state = GSK_VULKAN_PIPELINE_GET_CLASS (self)->get_input_state_create_info (self); g_assert (vertex_input_state->vertexBindingDescriptionCount == 1); @@ -95,8 +91,18 @@ gsk_vulkan_pipeline_new (GType pipeline_type, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .stageCount = 2, .pStages = (VkPipelineShaderStageCreateInfo[2]) { - GST_VULKAN_SHADER_STAGE_CREATE_INFO (priv->vertex_shader), - GST_VULKAN_SHADER_STAGE_CREATE_INFO (priv->fragment_shader) + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .module = gdk_display_get_vk_shader_module (display, vertex_shader_name), + .pName = "main", + }, + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .module = gdk_display_get_vk_shader_module (display, fragment_shader_name), + .pName = "main", + }, }, .pVertexInputState = vertex_input_state, .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) { @@ -162,6 +168,9 @@ gsk_vulkan_pipeline_new (GType pipeline_type, NULL, &priv->pipeline); + g_free (fragment_shader_name); + g_free (vertex_shader_name); + gdk_vulkan_context_pipeline_cache_updated (context); return self; diff --git a/gsk/vulkan/gskvulkanshader.c b/gsk/vulkan/gskvulkanshader.c deleted file mode 100644 index 1450f31e2b..0000000000 --- a/gsk/vulkan/gskvulkanshader.c +++ /dev/null @@ -1,102 +0,0 @@ -#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_new0 (GskVulkanShader, 1); - - 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_DEBUG (VULKAN, "Error loading shader data: %s", 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_free (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/vulkan/gskvulkanshaderprivate.h b/gsk/vulkan/gskvulkanshaderprivate.h deleted file mode 100644 index 3f35b6b77f..0000000000 --- a/gsk/vulkan/gskvulkanshaderprivate.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -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 - -- 2.30.2