Drop vulkan refcounting
Change things to have a gdk_display_prepare_vulkan call which sets up Vulkan support for the display. The Vulkan resources will be dropped when the display is disposed. This matches what we do for GL, and seems better than a refcounting approach where everybody leaks the references. Fixes: #7150
This commit is contained in:
@@ -438,11 +438,10 @@ gdk_display_dispose (GObject *object)
|
||||
g_clear_pointer (&display->egl_dmabuf_formats, gdk_dmabuf_formats_unref);
|
||||
g_clear_pointer (&display->egl_internal_formats, gdk_dmabuf_formats_unref);
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
if (display->vk_dmabuf_formats)
|
||||
{
|
||||
gdk_display_unref_vulkan (display);
|
||||
g_assert (display->vk_dmabuf_formats == NULL);
|
||||
}
|
||||
if (display->vk_instance)
|
||||
gdk_display_destroy_vulkan_instance (display);
|
||||
g_assert (display->vk_dmabuf_formats == NULL);
|
||||
g_clear_error (&display->vulkan_error);
|
||||
#endif
|
||||
|
||||
g_clear_object (&priv->gl_context);
|
||||
@@ -1286,6 +1285,53 @@ gdk_display_get_keymap (GdkDisplay *display)
|
||||
return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_display_prepare_vulkan:
|
||||
* @self: a `GdkDisplay`
|
||||
* @error: return location for a `GError`
|
||||
*
|
||||
* Checks that Vulkan is available for @self and ensures that it is
|
||||
* properly initialized.
|
||||
*
|
||||
* When this fails, an @error will be set describing the error and this
|
||||
* function returns %FALSE.
|
||||
*
|
||||
* Note that even if this function succeeds, creating a `GdkVulkanContext`
|
||||
* may still fail.
|
||||
*
|
||||
* This function is idempotent. Calling it multiple times will just
|
||||
* return the same value or error.
|
||||
*
|
||||
* You never need to call this function, GDK will call it automatically
|
||||
* as needed.
|
||||
*
|
||||
* Returns: %TRUE if the display supports Vulkan
|
||||
*/
|
||||
gboolean
|
||||
gdk_display_prepare_vulkan (GdkDisplay *self,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (self), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
if (!self->vk_instance && !self->vulkan_error)
|
||||
gdk_display_create_vulkan_instance (self, &self->vulkan_error);
|
||||
|
||||
if (self->vk_instance == NULL)
|
||||
{
|
||||
if (error)
|
||||
*error = g_error_copy (self->vulkan_error);
|
||||
}
|
||||
|
||||
return self->vk_instance != NULL;
|
||||
#else
|
||||
g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
|
||||
"GTK was built without Vulkan support");
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*<private>
|
||||
* gdk_display_create_vulkan_context:
|
||||
* @self: a `GdkDisplay`
|
||||
|
@@ -126,7 +126,7 @@ struct _GdkDisplay
|
||||
GdkDmabufFormats *vk_dmabuf_formats;
|
||||
GdkVulkanFeatures vulkan_features;
|
||||
|
||||
guint vulkan_refcount;
|
||||
GError *vulkan_error;
|
||||
#endif /* GDK_RENDERING_VULKAN */
|
||||
|
||||
/* egl info */
|
||||
@@ -239,6 +239,8 @@ void _gdk_display_unpause_events (GdkDisplay *display
|
||||
|
||||
void gdk_display_init_dmabuf (GdkDisplay *self);
|
||||
|
||||
gboolean gdk_display_prepare_vulkan (GdkDisplay *self,
|
||||
GError **error);
|
||||
gboolean gdk_display_has_vulkan_feature (GdkDisplay *self,
|
||||
GdkVulkanFeatures feature);
|
||||
GdkVulkanContext * gdk_display_create_vulkan_context (GdkDisplay *self,
|
||||
|
@@ -367,7 +367,6 @@ gdk_vulkan_context_dispose (GObject *gobject)
|
||||
{
|
||||
GdkVulkanContext *context = GDK_VULKAN_CONTEXT (gobject);
|
||||
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
|
||||
GdkDisplay *display;
|
||||
VkDevice device;
|
||||
guint i;
|
||||
|
||||
@@ -397,11 +396,6 @@ gdk_vulkan_context_dispose (GObject *gobject)
|
||||
priv->surface = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
/* display will be unset in gdk_draw_context_dispose() */
|
||||
display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context));
|
||||
if (display && priv->vulkan_ref)
|
||||
gdk_display_unref_vulkan (display);
|
||||
|
||||
G_OBJECT_CLASS (gdk_vulkan_context_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@@ -887,8 +881,7 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
VkBool32 supported;
|
||||
uint32_t i;
|
||||
|
||||
priv->vulkan_ref = gdk_display_init_vulkan (display, error);
|
||||
if (!priv->vulkan_ref)
|
||||
if (!gdk_display_prepare_vulkan (display, error))
|
||||
return FALSE;
|
||||
|
||||
if (surface == NULL)
|
||||
@@ -1668,7 +1661,7 @@ gdk_vulkan_debug_report (VkDebugReportFlagsEXT flags,
|
||||
return VK_FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gboolean
|
||||
gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
@@ -1678,6 +1671,8 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
gboolean have_debug_report = FALSE;
|
||||
VkResult res;
|
||||
|
||||
g_assert (display->vk_instance == NULL);
|
||||
|
||||
if (!gdk_has_feature (GDK_FEATURE_VULKAN))
|
||||
{
|
||||
g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
|
||||
@@ -1804,66 +1799,16 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* gdk_display_init_vulkan:
|
||||
* @display: a display
|
||||
* @error: A potential error message
|
||||
*
|
||||
* Initializes Vulkan and returns an error on failure.
|
||||
*
|
||||
* If Vulkan is already initialized, this function returns
|
||||
* %TRUE and increases the refcount of the existing instance.
|
||||
*
|
||||
* You need to gdk_display_unref_vulkan() to close it again.
|
||||
*
|
||||
* Returns: %TRUE if Vulkan is initialized.
|
||||
**/
|
||||
gboolean
|
||||
gdk_display_init_vulkan (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
if (display->vulkan_refcount == 0)
|
||||
{
|
||||
if (!gdk_display_create_vulkan_instance (display, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
display->vulkan_refcount++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* gdk_display_ref_vulkan:
|
||||
* @display: a GdkDisplay
|
||||
*
|
||||
* Increases the refcount of an existing Vulkan instance.
|
||||
*
|
||||
* This function must not be called if Vulkan may not be initialized
|
||||
* yet, call gdk_display_init_vulkan() in that case.
|
||||
**/
|
||||
void
|
||||
gdk_display_ref_vulkan (GdkDisplay *display)
|
||||
{
|
||||
g_assert (display->vulkan_refcount > 0);
|
||||
|
||||
display->vulkan_refcount++;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_unref_vulkan (GdkDisplay *display)
|
||||
gdk_display_destroy_vulkan_instance (GdkDisplay *display)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
g_return_if_fail (display->vulkan_refcount > 0);
|
||||
g_assert (GDK_IS_DISPLAY (display));
|
||||
g_assert (display->vk_instance != NULL);
|
||||
|
||||
display->vulkan_refcount--;
|
||||
if (display->vulkan_refcount > 0)
|
||||
return;
|
||||
|
||||
GDK_DEBUG (VULKAN, "Closing Vulkan instance");
|
||||
GDK_DEBUG (VULKAN, "Destroy Vulkan instance");
|
||||
display->vulkan_features = 0;
|
||||
g_clear_pointer (&display->vk_dmabuf_formats, gdk_dmabuf_formats_unref);
|
||||
g_hash_table_iter_init (&iter, display->vk_shader_modules);
|
||||
@@ -1941,11 +1886,9 @@ gdk_vulkan_init_dmabuf (GdkDisplay *display)
|
||||
return;
|
||||
|
||||
if (!gdk_has_feature (GDK_FEATURE_DMABUF) ||
|
||||
!gdk_display_init_vulkan (display, NULL) ||
|
||||
((display->vulkan_features & GDK_VULKAN_FEATURE_DMABUF) == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
!gdk_display_prepare_vulkan (display, NULL) ||
|
||||
(display->vulkan_features & GDK_VULKAN_FEATURE_DMABUF) == 0)
|
||||
return;
|
||||
|
||||
vulkan_builder = gdk_dmabuf_formats_builder_new ();
|
||||
|
||||
|
@@ -73,10 +73,9 @@ gdk_vulkan_handle_result (VkResult res,
|
||||
|
||||
#define GDK_VK_CHECK(func, ...) gdk_vulkan_handle_result (func (__VA_ARGS__), G_STRINGIFY (func))
|
||||
|
||||
gboolean gdk_display_init_vulkan (GdkDisplay *display,
|
||||
gboolean gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
GError **error);
|
||||
void gdk_display_ref_vulkan (GdkDisplay *display);
|
||||
void gdk_display_unref_vulkan (GdkDisplay *display);
|
||||
void gdk_display_destroy_vulkan_instance (GdkDisplay *display);
|
||||
|
||||
void gdk_vulkan_init_dmabuf (GdkDisplay *display);
|
||||
|
||||
|
@@ -343,8 +343,6 @@ gsk_vulkan_device_finalize (GObject *object)
|
||||
g_clear_pointer (&self->allocators[i], gsk_vulkan_allocator_unref);
|
||||
g_clear_pointer (&self->external_allocator, gsk_vulkan_allocator_unref);
|
||||
|
||||
gdk_display_unref_vulkan (display);
|
||||
|
||||
G_OBJECT_CLASS (gsk_vulkan_device_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@@ -422,7 +420,7 @@ gsk_vulkan_device_get_for_display (GdkDisplay *display,
|
||||
if (self)
|
||||
return GSK_GPU_DEVICE (g_object_ref (self));
|
||||
|
||||
if (!gdk_display_init_vulkan (display, error))
|
||||
if (!gdk_display_prepare_vulkan (display, error))
|
||||
return NULL;
|
||||
|
||||
self = g_object_new (GSK_TYPE_VULKAN_DEVICE, NULL);
|
||||
|
@@ -653,7 +653,7 @@ vulkan_supported_platform (GdkSurface *surface,
|
||||
VkPhysicalDeviceProperties props;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gdk_display_init_vulkan (display, &error))
|
||||
if (!gdk_display_prepare_vulkan (display, &error))
|
||||
{
|
||||
GSK_DEBUG (RENDERER, "Not using Vulkan%s: %s",
|
||||
as_fallback ? " as fallback" : "",
|
||||
|
@@ -577,7 +577,7 @@ init_vulkan (GtkInspectorGeneral *gen)
|
||||
const char *types[] = { "other", "integrated GPU", "discrete GPU", "virtual GPU", "CPU" };
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gdk_display_init_vulkan (gen->display, &error))
|
||||
if (!gdk_display_prepare_vulkan (gen->display, &error))
|
||||
{
|
||||
gtk_label_set_text (GTK_LABEL (gen->vk_device), C_("Vulkan device", "None"));
|
||||
gtk_widget_set_visible (gen->vk_error_row, TRUE);
|
||||
@@ -617,8 +617,6 @@ init_vulkan (GtkInspectorGeneral *gen)
|
||||
add_instance_extensions (gen->vulkan_extensions_list);
|
||||
add_device_extensions (gen->display->vk_physical_device, gen->vulkan_extensions_list);
|
||||
add_layers (gen->vulkan_layers_list);
|
||||
|
||||
gdk_display_unref_vulkan (gen->display);
|
||||
#else
|
||||
gtk_label_set_text (GTK_LABEL (gen->vk_device), C_("Vulkan device", "None"));
|
||||
gtk_widget_set_visible (gen->vk_api_version_row, FALSE);
|
||||
|
Reference in New Issue
Block a user