gpu: Refactor waiting for frames
Instead of having renderer API to wait for any number of frames, just have gsk_gpu_frame_wait() to wait for a single frame. This unifies behavior on Vulkan and GL, because unlike Vulkan, GL does not allow waiting for multiple fences. To make up for it, we replace waiting for multiple frames with finding the frame with the earliest timestamp and waiting for that one. Also implement wait() for GL.
This commit is contained in:
@@ -43,6 +43,17 @@ gsk_gl_frame_is_busy (GskGpuFrame *frame)
|
||||
return glClientWaitSync (self->sync, 0, 0) == GL_TIMEOUT_EXPIRED;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_frame_wait (GskGpuFrame *frame)
|
||||
{
|
||||
GskGLFrame *self = GSK_GL_FRAME (frame);
|
||||
|
||||
if (!self->sync)
|
||||
return;
|
||||
|
||||
glClientWaitSync (self->sync, 0, G_MAXINT64);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_frame_setup (GskGpuFrame *frame)
|
||||
{
|
||||
@@ -194,6 +205,7 @@ gsk_gl_frame_class_init (GskGLFrameClass *klass)
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gpu_frame_class->is_busy = gsk_gl_frame_is_busy;
|
||||
gpu_frame_class->wait = gsk_gl_frame_wait;
|
||||
gpu_frame_class->setup = gsk_gl_frame_setup;
|
||||
gpu_frame_class->cleanup = gsk_gl_frame_cleanup;
|
||||
gpu_frame_class->upload_texture = gsk_gl_frame_upload_texture;
|
||||
|
||||
@@ -505,6 +505,12 @@ gsk_gpu_frame_is_busy (GskGpuFrame *self)
|
||||
return GSK_GPU_FRAME_GET_CLASS (self)->is_busy (self);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gpu_frame_wait (GskGpuFrame *self)
|
||||
{
|
||||
GSK_GPU_FRAME_GET_CLASS (self)->wait (self);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_texture (gpointer user_data,
|
||||
GdkTexture *texture)
|
||||
|
||||
@@ -24,6 +24,7 @@ struct _GskGpuFrameClass
|
||||
GObjectClass parent_class;
|
||||
|
||||
gboolean (* is_busy) (GskGpuFrame *self);
|
||||
void (* wait) (GskGpuFrame *self);
|
||||
void (* setup) (GskGpuFrame *self);
|
||||
void (* cleanup) (GskGpuFrame *self);
|
||||
GskGpuImage * (* upload_texture) (GskGpuFrame *self,
|
||||
@@ -69,6 +70,7 @@ GskGpuBuffer * gsk_gpu_frame_write_storage_buffer (GskGpuF
|
||||
gsize *out_offset);
|
||||
|
||||
gboolean gsk_gpu_frame_is_busy (GskGpuFrame *self);
|
||||
void gsk_gpu_frame_wait (GskGpuFrame *self);
|
||||
|
||||
void gsk_gpu_frame_render (GskGpuFrame *self,
|
||||
gint64 timestamp,
|
||||
|
||||
@@ -166,24 +166,36 @@ static GskGpuFrame *
|
||||
gsk_gpu_renderer_get_frame (GskGpuRenderer *self)
|
||||
{
|
||||
GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self);
|
||||
GskGpuFrame *earliest_frame = NULL;
|
||||
gint64 earliest_time = G_MAXINT64;
|
||||
guint i;
|
||||
|
||||
while (TRUE)
|
||||
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
|
||||
{
|
||||
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
|
||||
{
|
||||
if (priv->frames[i] == NULL)
|
||||
{
|
||||
priv->frames[i] = gsk_gpu_renderer_create_frame (self);
|
||||
return priv->frames[i];
|
||||
}
|
||||
gint64 timestamp;
|
||||
|
||||
if (!gsk_gpu_frame_is_busy (priv->frames[i]))
|
||||
return priv->frames[i];
|
||||
if (priv->frames[i] == NULL)
|
||||
{
|
||||
priv->frames[i] = gsk_gpu_renderer_create_frame (self);
|
||||
return priv->frames[i];
|
||||
}
|
||||
|
||||
GSK_GPU_RENDERER_GET_CLASS (self)->wait (self, priv->frames, GSK_GPU_MAX_FRAMES);
|
||||
if (!gsk_gpu_frame_is_busy (priv->frames[i]))
|
||||
return priv->frames[i];
|
||||
|
||||
timestamp = gsk_gpu_frame_get_timestamp (priv->frames[i]);
|
||||
if (timestamp < earliest_time)
|
||||
{
|
||||
earliest_time = timestamp;
|
||||
earliest_frame = priv->frames[i];
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (earliest_frame);
|
||||
|
||||
gsk_gpu_frame_wait (earliest_frame);
|
||||
|
||||
return earliest_frame;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -217,31 +229,17 @@ gsk_gpu_renderer_unrealize (GskRenderer *renderer)
|
||||
{
|
||||
GskGpuRenderer *self = GSK_GPU_RENDERER (renderer);
|
||||
GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self);
|
||||
gsize i, j;
|
||||
gsize i;
|
||||
|
||||
gsk_gpu_renderer_make_current (self);
|
||||
|
||||
while (TRUE)
|
||||
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
|
||||
{
|
||||
for (i = 0, j = 0; i < G_N_ELEMENTS (priv->frames); i++)
|
||||
{
|
||||
if (priv->frames[i] == NULL)
|
||||
break;
|
||||
if (gsk_gpu_frame_is_busy (priv->frames[i]))
|
||||
{
|
||||
if (i > j)
|
||||
{
|
||||
priv->frames[j] = priv->frames[i];
|
||||
priv->frames[i] = NULL;
|
||||
}
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
g_clear_object (&priv->frames[i]);
|
||||
}
|
||||
if (j == 0)
|
||||
if (priv->frames[i] == NULL)
|
||||
break;
|
||||
GSK_GPU_RENDERER_GET_CLASS (self)->wait (self, priv->frames, j);
|
||||
if (gsk_gpu_frame_is_busy (priv->frames[i]))
|
||||
gsk_gpu_frame_wait (priv->frames[i]);
|
||||
g_clear_object (&priv->frames[i]);
|
||||
}
|
||||
|
||||
g_clear_object (&priv->context);
|
||||
|
||||
@@ -35,9 +35,6 @@ struct _GskGpuRendererClass
|
||||
|
||||
void (* make_current) (GskGpuRenderer *self);
|
||||
GskGpuImage * (* get_backbuffer) (GskGpuRenderer *self);
|
||||
void (* wait) (GskGpuRenderer *self,
|
||||
GskGpuFrame **frame,
|
||||
gsize n_frames);
|
||||
|
||||
double (* get_scale) (GskGpuRenderer *self);
|
||||
GdkDmabufFormats * (* get_dmabuf_formats) (GskGpuRenderer *self);
|
||||
|
||||
@@ -119,13 +119,6 @@ gsk_ngl_renderer_get_backbuffer (GskGpuRenderer *renderer)
|
||||
return self->backbuffer;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_ngl_renderer_wait (GskGpuRenderer *self,
|
||||
GskGpuFrame **frame,
|
||||
gsize n_frames)
|
||||
{
|
||||
}
|
||||
|
||||
static double
|
||||
gsk_ngl_renderer_get_scale (GskGpuRenderer *self)
|
||||
{
|
||||
@@ -164,7 +157,6 @@ gsk_ngl_renderer_class_init (GskNglRendererClass *klass)
|
||||
gpu_renderer_class->create_context = gsk_ngl_renderer_create_context;
|
||||
gpu_renderer_class->make_current = gsk_ngl_renderer_make_current;
|
||||
gpu_renderer_class->get_backbuffer = gsk_ngl_renderer_get_backbuffer;
|
||||
gpu_renderer_class->wait = gsk_ngl_renderer_wait;
|
||||
gpu_renderer_class->get_scale = gsk_ngl_renderer_get_scale;
|
||||
gpu_renderer_class->get_dmabuf_formats = gsk_ngl_renderer_get_dmabuf_formats;
|
||||
|
||||
|
||||
@@ -74,6 +74,21 @@ gsk_vulkan_frame_is_busy (GskGpuFrame *frame)
|
||||
return vkGetFenceStatus (device, self->vk_fence) == VK_NOT_READY;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_frame_wait (GskGpuFrame *frame)
|
||||
{
|
||||
GskVulkanFrame *self = GSK_VULKAN_FRAME (frame);
|
||||
VkDevice vk_device;
|
||||
|
||||
vk_device = gsk_vulkan_device_get_vk_device (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)));
|
||||
|
||||
GSK_VK_CHECK (vkWaitForFences, vk_device,
|
||||
1,
|
||||
&self->vk_fence,
|
||||
VK_FALSE,
|
||||
INT64_MAX);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_frame_setup (GskGpuFrame *frame)
|
||||
{
|
||||
@@ -387,6 +402,7 @@ gsk_vulkan_frame_class_init (GskVulkanFrameClass *klass)
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gpu_frame_class->is_busy = gsk_vulkan_frame_is_busy;
|
||||
gpu_frame_class->wait = gsk_vulkan_frame_wait;
|
||||
gpu_frame_class->setup = gsk_vulkan_frame_setup;
|
||||
gpu_frame_class->cleanup = gsk_vulkan_frame_cleanup;
|
||||
gpu_frame_class->upload_texture = gsk_vulkan_frame_upload_texture;
|
||||
|
||||
@@ -129,31 +129,6 @@ gsk_vulkan_renderer_get_backbuffer (GskGpuRenderer *renderer)
|
||||
return self->targets[gdk_vulkan_context_get_draw_index (context)];
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_renderer_wait (GskGpuRenderer *renderer,
|
||||
GskGpuFrame **frames,
|
||||
gsize n_frames)
|
||||
{
|
||||
VkFence *fences;
|
||||
VkDevice vk_device;
|
||||
gsize i;
|
||||
|
||||
vk_device = gsk_vulkan_device_get_vk_device (GSK_VULKAN_DEVICE (gsk_gpu_renderer_get_device (renderer)));
|
||||
|
||||
fences = g_alloca (sizeof (VkFence) * n_frames);
|
||||
|
||||
for (i = 0; i < n_frames; i++)
|
||||
{
|
||||
fences[i] = gsk_vulkan_frame_get_vk_fence (GSK_VULKAN_FRAME (frames[i]));
|
||||
}
|
||||
|
||||
GSK_VK_CHECK (vkWaitForFences, vk_device,
|
||||
n_frames,
|
||||
fences,
|
||||
VK_FALSE,
|
||||
INT64_MAX);
|
||||
}
|
||||
|
||||
static GdkDmabufFormats *
|
||||
gsk_vulkan_renderer_get_dmabuf_formats (GskGpuRenderer *renderer)
|
||||
{
|
||||
@@ -189,7 +164,6 @@ gsk_vulkan_renderer_class_init (GskVulkanRendererClass *klass)
|
||||
gpu_renderer_class->create_context = gsk_vulkan_renderer_create_context;
|
||||
gpu_renderer_class->make_current = gsk_vulkan_renderer_make_current;
|
||||
gpu_renderer_class->get_backbuffer = gsk_vulkan_renderer_get_backbuffer;
|
||||
gpu_renderer_class->wait = gsk_vulkan_renderer_wait;
|
||||
gpu_renderer_class->get_dmabuf_formats = gsk_vulkan_renderer_get_dmabuf_formats;
|
||||
|
||||
renderer_class->unrealize = gsk_vulkan_renderer_unrealize;
|
||||
|
||||
Reference in New Issue
Block a user