1 /*
2 * GStreamer
3 * Copyright (C) 2016 Matthew Waters <matthew@centricular.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "vktrash.h"
26 #include "vkutils_private.h"
27
28 GST_DEBUG_CATEGORY (gst_debug_vulkan_trash);
29 #define GST_CAT_DEFAULT gst_debug_vulkan_trash
30
31 static void
_init_debug(void)32 _init_debug (void)
33 {
34 static volatile gsize init;
35
36 if (g_once_init_enter (&init)) {
37 GST_DEBUG_CATEGORY_INIT (gst_debug_vulkan_trash,
38 "vulkantrash", 0, "Vulkan Trash");
39 g_once_init_leave (&init, 1);
40 }
41 }
42
43 void
gst_vulkan_trash_free(GstVulkanTrash * trash)44 gst_vulkan_trash_free (GstVulkanTrash * trash)
45 {
46 if (!trash)
47 return;
48
49 GST_TRACE ("Freeing trash object %p with fence %" GST_PTR_FORMAT, trash,
50 trash->fence);
51
52 gst_vulkan_fence_unref (trash->fence);
53
54 g_free (trash);
55 }
56
57 GstVulkanTrash *
gst_vulkan_trash_new(GstVulkanFence * fence,GstVulkanTrashNotify notify,gpointer user_data)58 gst_vulkan_trash_new (GstVulkanFence * fence, GstVulkanTrashNotify notify,
59 gpointer user_data)
60 {
61 GstVulkanTrash *ret = NULL;
62
63 g_return_val_if_fail (fence != NULL, NULL);
64 g_return_val_if_fail (GST_IS_VULKAN_DEVICE (fence->device), NULL);
65 g_return_val_if_fail (notify != NULL, NULL);
66
67 _init_debug ();
68
69 ret = g_new0 (GstVulkanTrash, 1);
70 GST_TRACE ("Creating new trash object %p with fence %" GST_PTR_FORMAT
71 " on device %" GST_PTR_FORMAT, ret, fence, fence->device);
72 ret->fence = fence;
73 ret->notify = notify;
74 ret->user_data = user_data;
75
76 return ret;
77 }
78
79 GList *
gst_vulkan_trash_list_gc(GList * trash_list)80 gst_vulkan_trash_list_gc (GList * trash_list)
81 {
82 GList *l = trash_list;
83
84 while (l) {
85 GstVulkanTrash *trash = l->data;
86
87 if (gst_vulkan_fence_is_signaled (trash->fence)) {
88 GList *next = g_list_next (l);
89 GST_TRACE ("fence %" GST_PTR_FORMAT " has been signalled, notifying",
90 trash->fence);
91 trash->notify (trash->fence->device, trash->user_data);
92 gst_vulkan_trash_free (trash);
93 trash_list = g_list_delete_link (trash_list, l);
94 l = next;
95 } else {
96 l = g_list_next (l);
97 }
98 }
99
100 return trash_list;
101 }
102
103 gboolean
gst_vulkan_trash_list_wait(GList * trash_list,guint64 timeout)104 gst_vulkan_trash_list_wait (GList * trash_list, guint64 timeout)
105 {
106 VkResult err = VK_SUCCESS;
107 guint i, n;
108
109 /* remove all the previously signaled fences */
110 trash_list = gst_vulkan_trash_list_gc (trash_list);
111
112 n = g_list_length (trash_list);
113 if (n > 0) {
114 VkFence *fences;
115 GstVulkanDevice *device = NULL;
116 GList *l = NULL;
117
118 fences = g_new0 (VkFence, n);
119 for (i = 0, l = trash_list; i < n; i++, l = g_list_next (l)) {
120 GstVulkanTrash *trash = l->data;
121
122 if (device == NULL)
123 device = trash->fence->device;
124
125 fences[i] = trash->fence->fence;
126
127 /* only support waiting on fences from the same device */
128 g_assert (device == trash->fence->device);
129 }
130
131 GST_TRACE ("Waiting on %d fences with timeout %" GST_TIME_FORMAT, n,
132 GST_TIME_ARGS (timeout));
133 err = vkWaitForFences (device->device, n, fences, TRUE, timeout);
134 g_free (fences);
135
136 trash_list = gst_vulkan_trash_list_gc (trash_list);
137 }
138
139 return err == VK_SUCCESS;
140 }
141
142 static void
_free_command_buffer(GstVulkanDevice * device,VkCommandBuffer * cmd)143 _free_command_buffer (GstVulkanDevice * device, VkCommandBuffer * cmd)
144 {
145 g_assert (cmd);
146 vkFreeCommandBuffers (device->device, device->cmd_pool, 1, cmd);
147
148 g_free (cmd);
149 }
150
151 GstVulkanTrash *
gst_vulkan_trash_new_free_command_buffer(GstVulkanFence * fence,VkCommandBuffer cmd)152 gst_vulkan_trash_new_free_command_buffer (GstVulkanFence * fence,
153 VkCommandBuffer cmd)
154 {
155 VkCommandBuffer *data;
156 GstVulkanTrash *trash;
157
158 data = g_new0 (VkCommandBuffer, 1);
159 *data = cmd;
160 trash = gst_vulkan_trash_new (fence,
161 (GstVulkanTrashNotify) _free_command_buffer, data);
162
163 return trash;
164 }
165
166 static void
_free_semaphore(GstVulkanDevice * device,VkSemaphore * semaphore)167 _free_semaphore (GstVulkanDevice * device, VkSemaphore * semaphore)
168 {
169 if (semaphore)
170 vkDestroySemaphore (device->device, *semaphore, NULL);
171
172 g_free (semaphore);
173 }
174
175 GstVulkanTrash *
gst_vulkan_trash_new_free_semaphore(GstVulkanFence * fence,VkSemaphore semaphore)176 gst_vulkan_trash_new_free_semaphore (GstVulkanFence * fence,
177 VkSemaphore semaphore)
178 {
179 VkSemaphore *data;
180 GstVulkanTrash *trash;
181
182 data = g_new0 (VkSemaphore, 1);
183 *data = semaphore;
184 trash = gst_vulkan_trash_new (fence,
185 (GstVulkanTrashNotify) _free_semaphore, data);
186
187 return trash;
188 }
189