[gtk/wip/chergert/glproto] remove state save/restore semantics
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/glproto] remove state save/restore semantics
- Date: Fri, 12 Feb 2021 22:23:11 +0000 (UTC)
commit abe39e2e96bff1e0ee8e4054e4312f3919ee8a14
Author: Christian Hergert <chergert redhat com>
Date: Fri Feb 12 14:09:51 2021 -0800
remove state save/restore semantics
too hard to optimize this when instead we can use stamps and
be more specific about our state changes like the GL renderer
did.
although this does try hard to add a few more variants based
on usage so that we avoid intermediate structs in most cases
thereby saving some copies.
gsk/next/gskgldriver.c | 1 -
gsk/next/gskgldriverprivate.h | 4 +-
gsk/next/gskglrenderjob.c | 270 +++++++++++++++++++++---------------------
3 files changed, 139 insertions(+), 136 deletions(-)
---
diff --git a/gsk/next/gskgldriver.c b/gsk/next/gskgldriver.c
index bd60570393..2e1dfba79b 100644
--- a/gsk/next/gskgldriver.c
+++ b/gsk/next/gskgldriver.c
@@ -315,7 +315,6 @@ gsk_next_driver_class_init (GskNextDriverClass *klass)
static void
gsk_next_driver_init (GskNextDriver *self)
{
- self->last_shared_state = 1;
self->autorelease_framebuffers = g_array_new (FALSE, FALSE, sizeof (guint));
self->textures = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify)gsk_gl_texture_free);
diff --git a/gsk/next/gskgldriverprivate.h b/gsk/next/gskgldriverprivate.h
index f09b42e69f..6531fc9c6c 100644
--- a/gsk/next/gskgldriverprivate.h
+++ b/gsk/next/gskgldriverprivate.h
@@ -114,8 +114,8 @@ struct _GskNextDriver
gint64 current_frame_id;
- /* Monotonic counter to reduce shared state changes */
- guint last_shared_state;
+ /* Used to reduce number of comparisons */
+ guint stamps[UNIFORM_SHARED_LAST];
guint debug : 1;
guint in_frame : 1;
diff --git a/gsk/next/gskglrenderjob.c b/gsk/next/gskglrenderjob.c
index 0f88ce9d37..ebe07af591 100644
--- a/gsk/next/gskglrenderjob.c
+++ b/gsk/next/gskglrenderjob.c
@@ -156,18 +156,6 @@ struct _GskGLRenderJob
guint debug_fallback : 1;
};
-typedef struct GskGLRenderState
-{
- graphene_rect_t viewport;
- graphene_matrix_t projection;
- guint framebuffer;
- float alpha;
- float offset_x;
- float offset_y;
- float scale_x;
- float scale_y;
-} GskGLRenderState;
-
typedef struct _GskGLRenderOffscreen
{
const graphene_rect_t *bounds;
@@ -195,25 +183,13 @@ static inline void
gsk_gl_render_job_begin_draw (GskGLRenderJob *job,
GskGLProgram *program)
{
- /* If the program is up to our shared state value, then we can ignore callign
- * gsk_gl_program_begin_draw() with the initial values saving a bunch of
- * compares. Last checked this saves about 25-35% of the compares when
- * running widget-factory on the first page.
- */
- if G_LIKELY (program->last_shared_state == job->driver->last_shared_state)
- {
- gsk_gl_command_queue_begin_draw (job->command_queue, program->program_info, &job->viewport);
- }
- else
- {
- gsk_gl_program_begin_draw (program,
- &job->viewport,
- &job->projection,
- &job->current_modelview->matrix,
- &job->current_clip->rect,
- job->alpha);
- program->last_shared_state = job->driver->last_shared_state;
- }
+ /* TODO: Use stamps */
+ gsk_gl_program_begin_draw (program,
+ &job->viewport,
+ &job->projection,
+ &job->current_modelview->matrix,
+ &job->current_clip->rect,
+ job->alpha);
}
static inline void
@@ -423,6 +399,21 @@ init_projection_matrix (graphene_matrix_t *projection,
graphene_matrix_scale (projection, 1, -1, 1);
}
+static inline float
+gsk_gl_render_job_set_alpha (GskGLRenderJob *job,
+ float alpha)
+{
+ if (job->alpha != alpha)
+ {
+ float ret = job->alpha;
+ job->alpha = alpha;
+ job->driver->stamps[UNIFORM_SHARED_ALPHA]++;
+ return ret;
+ }
+
+ return alpha;
+}
+
static void
extract_matrix_metadata (GskGLRenderModelview *modelview)
{
@@ -484,7 +475,7 @@ gsk_gl_render_job_set_modelview (GskGLRenderJob *job,
g_assert (job != NULL);
g_assert (job->modelview != NULL);
- job->driver->last_shared_state++;
+ job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
g_array_set_size (job->modelview, job->modelview->len + 1);
@@ -517,7 +508,7 @@ gsk_gl_render_job_push_modelview (GskGLRenderJob *job,
g_assert (job->modelview != NULL);
g_assert (transform != NULL);
- job->driver->last_shared_state++;
+ job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
g_array_set_size (job->modelview, job->modelview->len + 1);
@@ -570,7 +561,7 @@ gsk_gl_render_job_pop_modelview (GskGLRenderJob *job)
g_assert (job->modelview);
g_assert (job->modelview->len > 0);
- job->driver->last_shared_state++;
+ job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
head = job->current_modelview;
@@ -606,7 +597,7 @@ gsk_gl_render_job_push_clip (GskGLRenderJob *job,
g_assert (job->clip != NULL);
g_assert (rect != NULL);
- job->driver->last_shared_state++;
+ job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
g_array_set_size (job->clip, job->clip->len + 1);
@@ -624,11 +615,9 @@ gsk_gl_render_job_pop_clip (GskGLRenderJob *job)
g_assert (job->clip != NULL);
g_assert (job->clip->len > 0);
- job->driver->last_shared_state++;
-
+ job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
+ job->current_clip--;
job->clip->len--;
-
- job->current_clip = &g_array_index (job->clip, GskGLRenderClip, job->clip->len - 1);
}
static inline void
@@ -638,52 +627,67 @@ gsk_gl_render_job_offset (GskGLRenderJob *job,
{
if (offset_x || offset_y)
{
- job->driver->last_shared_state++;
-
job->offset_x += offset_x;
job->offset_y += offset_y;
}
}
-static void
-gsk_gl_render_state_save (GskGLRenderState *state,
- GskGLRenderJob *job)
+static inline void
+gsk_gl_render_job_set_projection (GskGLRenderJob *job,
+ const graphene_matrix_t *projection)
{
- g_assert (state != NULL);
- g_assert (job != NULL);
-
- job->driver->last_shared_state++;
-
- memcpy (&state->viewport, &job->viewport, sizeof state->viewport);
- memcpy (&state->projection, &job->projection, sizeof state->projection);
-
- state->framebuffer = job->command_queue->attachments->fbo.id;
- state->alpha = job->alpha;
- state->offset_x = job->offset_x;
- state->offset_y = job->offset_y;
- state->scale_x = job->scale_x;
- state->scale_y = job->scale_y;
+ memcpy (&job->projection, projection, sizeof job->projection);
+ job->driver->stamps[UNIFORM_SHARED_PROJECTION]++;
}
-static void
-gsk_gl_render_state_restore (GskGLRenderState *state,
- GskGLRenderJob *job)
+static inline void
+gsk_gl_render_job_set_projection_from_rect (GskGLRenderJob *job,
+ const graphene_rect_t *rect,
+ graphene_matrix_t *prev_projection)
{
- g_assert (state != NULL);
- g_assert (job != NULL);
-
- job->driver->last_shared_state++;
+ if (prev_projection)
+ memcpy (prev_projection, &job->projection, sizeof *prev_projection);
+ init_projection_matrix (&job->projection, rect);
+ job->driver->stamps[UNIFORM_SHARED_PROJECTION]++;
+}
- memcpy (&job->viewport, &state->viewport, sizeof state->viewport);
- memcpy (&job->projection, &state->projection, sizeof state->projection);
+static inline void
+gsk_gl_render_job_set_projection_for_size (GskGLRenderJob *job,
+ float width,
+ float height,
+ graphene_matrix_t *prev_projection)
+{
+ if (prev_projection)
+ memcpy (prev_projection, &job->projection, sizeof *prev_projection);
+ graphene_matrix_init_ortho (&job->projection, 0, width, 0, height, ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE);
+ graphene_matrix_scale (&job->projection, 1, -1, 1);
+ job->driver->stamps[UNIFORM_SHARED_PROJECTION]++;
+}
- gsk_gl_command_queue_bind_framebuffer (job->command_queue, state->framebuffer);
+static inline void
+gsk_gl_render_job_set_viewport (GskGLRenderJob *job,
+ const graphene_rect_t *viewport,
+ graphene_rect_t *prev_viewport)
+{
+ if (prev_viewport)
+ memcpy (prev_viewport, &job->viewport, sizeof *prev_viewport);
+ memcpy (&job->viewport, viewport, sizeof job->viewport);
+ job->driver->stamps[UNIFORM_SHARED_VIEWPORT]++;
+}
- job->alpha = state->alpha;
- job->offset_x = state->offset_x;
- job->offset_y = state->offset_y;
- job->scale_x = state->scale_x;
- job->scale_y = state->scale_y;
+static inline void
+gsk_gl_render_job_set_viewport_for_size (GskGLRenderJob *job,
+ float width,
+ float height,
+ graphene_rect_t *prev_viewport)
+{
+ if (prev_viewport)
+ memcpy (prev_viewport, &job->viewport, sizeof *prev_viewport);
+ job->viewport.origin.x = 0;
+ job->viewport.origin.y = 0;
+ job->viewport.size.width = width;
+ job->viewport.size.height = height;
+ job->driver->stamps[UNIFORM_SHARED_VIEWPORT]++;
}
static inline void
@@ -1053,7 +1057,9 @@ blur_offscreen (GskGLRenderJob *job,
const GskRoundedRect new_clip = GSK_ROUNDED_RECT_INIT (0, 0, texture_to_blur_width,
texture_to_blur_height);
GskGLRenderTarget *pass1;
GskGLRenderTarget *pass2;
- GskGLRenderState state;
+ graphene_matrix_t prev_projection;
+ graphene_rect_t prev_viewport;
+ guint prev_fbo;
g_assert (blur_radius_x > 0);
g_assert (blur_radius_y > 0);
@@ -1078,15 +1084,13 @@ blur_offscreen (GskGLRenderJob *job,
&pass2))
return gsk_next_driver_release_render_target (job->driver, pass1, FALSE);
- gsk_gl_render_state_save (&state, job);
-
- init_projection_matrix (&job->projection, &new_clip.bounds);
+ gsk_gl_render_job_set_viewport (job, &new_clip.bounds, &prev_viewport);
+ gsk_gl_render_job_set_projection_from_rect (job, &new_clip.bounds, &prev_projection);
gsk_gl_render_job_set_modelview (job, NULL);
- job->viewport = new_clip.bounds;
gsk_gl_render_job_push_clip (job, &new_clip);
/* Bind new framebuffer and clear it */
- gsk_gl_command_queue_bind_framebuffer (job->command_queue, pass1->framebuffer_id);
+ prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->command_queue, pass1->framebuffer_id);
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
/* Begin drawing the first horizontal pass, using offscreen as the
@@ -1137,8 +1141,9 @@ blur_offscreen (GskGLRenderJob *job,
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_pop_clip (job);
-
- gsk_gl_render_state_restore (&state, job);
+ gsk_gl_render_job_set_viewport (job, &prev_viewport, NULL);
+ gsk_gl_render_job_set_projection (job, &prev_projection);
+ gsk_gl_command_queue_bind_framebuffer (job->command_queue, prev_fbo);
gsk_next_driver_release_render_target (job->driver, pass1, TRUE);
@@ -1865,7 +1870,9 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
GskRoundedRect transformed_outline;
GskRoundedRect outline_to_blur;
GskGLRenderTarget *render_target;
- GskGLRenderState state;
+ graphene_matrix_t prev_projection;
+ graphene_rect_t prev_viewport;
+ guint prev_fbo;
/* TODO: In the following code, we have to be careful about where we apply the scale.
* We're manually scaling stuff (e.g. the outline) so we can later use texture_width
@@ -1900,19 +1907,12 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
&render_target))
g_assert_not_reached ();
- gsk_gl_render_state_save (&state, job);
-
- job->viewport.origin.x = 0;
- job->viewport.origin.y = 0;
- job->viewport.size.width = texture_width;
- job->viewport.size.height = texture_height;
-
- init_projection_matrix (&job->projection,
- &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height));
+ gsk_gl_render_job_set_viewport_for_size (job, texture_width, texture_height, &prev_viewport);
+ gsk_gl_render_job_set_projection_for_size (job, texture_width, texture_height, &prev_projection);
gsk_gl_render_job_set_modelview (job, NULL);
gsk_gl_render_job_push_clip (job, &GSK_ROUNDED_RECT_INIT (0, 0, texture_width, texture_height));
- gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id);
+ prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id);
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
gsk_gl_render_job_transform_rounded_rect (job, &outline_to_blur, &transformed_outline);
@@ -1937,8 +1937,9 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_pop_clip (job);
-
- gsk_gl_render_state_restore (&state, job);
+ gsk_gl_render_job_set_projection (job, &prev_projection);
+ gsk_gl_render_job_set_viewport (job, &prev_viewport, NULL);
+ gsk_gl_command_queue_bind_framebuffer (job->command_queue, prev_fbo);
offscreen.texture_id = render_target->texture_id;
init_full_texture_region (&offscreen);
@@ -2148,7 +2149,9 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
{
GdkGLContext *context = job->command_queue->context;
GskGLRenderTarget *render_target;
- GskGLRenderState state;
+ graphene_matrix_t prev_projection;
+ graphene_rect_t prev_viewport;
+ guint prev_fbo;
gsk_next_driver_create_render_target (job->driver,
texture_width, texture_height,
@@ -2170,16 +2173,13 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
}
/* Change state for offscreen */
- gsk_gl_render_state_save (&state, job);
- init_projection_matrix (&job->projection,
- &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height));
- job->viewport = GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height);
+ gsk_gl_render_job_set_projection_for_size (job, texture_width, texture_height, &prev_projection);
+ gsk_gl_render_job_set_viewport_for_size (job, texture_width, texture_height, &prev_viewport);
gsk_gl_render_job_set_modelview (job, NULL);
gsk_gl_render_job_push_clip (job, &scaled_outline);
/* Bind render target and clear it */
- gsk_gl_command_queue_bind_framebuffer (job->command_queue,
- render_target->framebuffer_id);
+ prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id);
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
/* Draw the outline using color program */
@@ -2193,7 +2193,8 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
/* Reset state from offscreen */
gsk_gl_render_job_pop_clip (job);
gsk_gl_render_job_pop_modelview (job);
- gsk_gl_render_state_restore (&state, job);
+ gsk_gl_render_job_set_viewport (job, &prev_viewport, NULL);
+ gsk_gl_render_job_set_projection (job, &prev_projection);
/* Now blur the outline */
init_full_texture_region (&offscreen);
@@ -2209,6 +2210,8 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
&scaled_outline,
blur_radius,
blurred_texture_id);
+
+ gsk_gl_command_queue_bind_framebuffer (job->command_queue, prev_fbo);
}
else
{
@@ -2448,12 +2451,9 @@ gsk_gl_render_job_visit_cross_fade_node (GskGLRenderJob *job,
if (!gsk_gl_render_job_visit_node_with_offscreen (job, end_node, &offscreen_end))
{
- float prev_alpha = job->alpha;
-
- job->alpha = job->alpha * progress;
+ float prev_alpha = gsk_gl_render_job_set_alpha (job, job->alpha * progress);
gsk_gl_render_job_visit_node (job, start_node);
- job->alpha = prev_alpha;
-
+ gsk_gl_render_job_set_alpha (job, prev_alpha);
return;
}
@@ -2483,14 +2483,12 @@ gsk_gl_render_job_visit_opacity_node (GskGLRenderJob *job,
{
const GskRenderNode *child = gsk_opacity_node_get_child (node);
float opacity = gsk_opacity_node_get_opacity (node);
- float prev_alpha = job->alpha;
float new_alpha = job->alpha * opacity;
- job->alpha = new_alpha;
- job->driver->last_shared_state++;
-
if (!ALPHA_IS_CLEAR (new_alpha))
{
+ float prev_alpha = gsk_gl_render_job_set_alpha (job, new_alpha);
+
if (gsk_render_node_get_node_type (child) == GSK_CONTAINER_NODE)
{
GskGLRenderOffscreen offscreen = {0};
@@ -2520,10 +2518,9 @@ gsk_gl_render_job_visit_opacity_node (GskGLRenderJob *job,
{
gsk_gl_render_job_visit_node (job, child);
}
- }
- job->alpha = prev_alpha;
- job->driver->last_shared_state++;
+ gsk_gl_render_job_set_alpha (job, prev_alpha);
+ }
}
static inline void
@@ -3481,9 +3478,12 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
}
GskGLRenderTarget *render_target;
- GskGLRenderState state;
-
- gsk_gl_render_state_save (&state, job);
+ graphene_matrix_t prev_projection;
+ graphene_rect_t prev_viewport;
+ float offset_x = job->offset_x;
+ float offset_y = job->offset_y;
+ float prev_alpha;
+ guint prev_fbo;
if (!gsk_next_driver_create_render_target (job->driver,
width, height,
@@ -3507,32 +3507,35 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
render_target->framebuffer_id);
}
- job->viewport.origin.x = offscreen->bounds->origin.x * scale_x;
- job->viewport.origin.y = offscreen->bounds->origin.y * scale_y;
- job->viewport.size.width = width;
- job->viewport.size.height = height;
+ gsk_gl_render_job_set_viewport (job,
+ &GRAPHENE_RECT_INIT (offscreen->bounds->origin.x * scale_x,
+ offscreen->bounds->origin.y * scale_y,
+ width, height),
+ &prev_viewport);
+ gsk_gl_render_job_set_projection_from_rect (job, &job->viewport, &prev_projection);
+ gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, scale_x, scale_y));
+ prev_alpha = gsk_gl_render_job_set_alpha (job, 1.0f);
+ job->offset_x = 0;
+ job->offset_y = 0;
- gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id);
+ prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id);
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
- init_projection_matrix (&job->projection, &job->viewport);
- gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, scale_x, scale_y));
-
if (offscreen->reset_clip)
gsk_gl_render_job_push_clip (job, &GSK_ROUNDED_RECT_INIT_FROM_RECT (job->viewport));
- job->offset_x = 0;
- job->offset_y = 0;
- job->alpha = 1.0f;
-
gsk_gl_render_job_visit_node (job, node);
if (offscreen->reset_clip)
gsk_gl_render_job_pop_clip (job);
gsk_gl_render_job_pop_modelview (job);
+ gsk_gl_render_job_set_viewport (job, &prev_viewport, NULL);
+ gsk_gl_render_job_set_projection (job, &prev_projection);
+ gsk_gl_command_queue_bind_framebuffer (job->command_queue, prev_fbo);
- gsk_gl_render_state_restore (&state, job);
+ job->offset_x = offset_x;
+ job->offset_y = offset_y;
offscreen->was_offscreen = TRUE;
offscreen->texture_id = gsk_next_driver_release_render_target (job->driver,
@@ -3588,6 +3591,7 @@ gsk_gl_render_job_render_flipped (GskGLRenderJob *job,
gdk_gl_context_pop_debug_group (job->command_queue->context);
/* Now draw to our real destination, but flipped */
+ gsk_gl_render_job_set_alpha (job, 1.0f);
gsk_gl_command_queue_bind_framebuffer (job->command_queue, job->framebuffer);
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
gsk_gl_program_begin_draw (job->driver->blit,
@@ -3595,7 +3599,7 @@ gsk_gl_render_job_render_flipped (GskGLRenderJob *job,
&proj,
&job->current_modelview->matrix,
&job->current_clip->rect,
- 1.0);
+ job->alpha);
gsk_gl_program_set_uniform_texture (job->driver->blit,
UNIFORM_SHARED_SOURCE,
GL_TEXTURE_2D,
@@ -3694,9 +3698,9 @@ gsk_gl_render_job_new (GskNextDriver *driver,
job->scale_x = scale_factor;
job->scale_y = scale_factor;
job->viewport = *viewport;
- job->alpha = 1.0;
- init_projection_matrix (&job->projection, viewport);
+ gsk_gl_render_job_set_alpha (job, 1.0);
+ gsk_gl_render_job_set_projection_from_rect (job, viewport, NULL);
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, scale_factor, scale_factor));
/* Setup our initial clip. If region is NULL then we are drawing the
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]