From 6f7ac2be53edae25ebfc97375c7259975e201d45 Mon Sep 17 00:00:00 2001 From: Aras Pranckevicius Date: Fri, 9 Feb 2024 17:17:54 +0100 Subject: [PATCH] VSE: Simplify and speedup sequencer cache drawing 5 years ago (18b693bdbd) part of cache rendering was converted to not draw one quad at a time. However the other part (drawing strip backgrounds when cache visualization is on) was left still drawing one quad at a time. Now that sequencer timeline drawing code has SeqQuadsBatch that batches arbitrary number of things for drawing fairly easily, the existing cache drawing batching code can be simplified to just use that, and the background code changed from immediate quad drawing to use the batcher. Sprite Fright edit, whole timeline visible, all caches visualized and full: `draw_cache_view` on Windows/Ryzen5950X goes 2.40ms -> 0.16ms. And there's less code. Pull Request: https://projects.blender.org/blender/blender/pulls/118027 --- .../sequencer_timeline_draw.cc | 146 +++++------------- 1 file changed, 42 insertions(+), 104 deletions(-) diff --git a/source/blender/editors/space_sequencer/sequencer_timeline_draw.cc b/source/blender/editors/space_sequencer/sequencer_timeline_draw.cc index 1455d0b7e4d..e6eb8fc080a 100644 --- a/source/blender/editors/space_sequencer/sequencer_timeline_draw.cc +++ b/source/blender/editors/space_sequencer/sequencer_timeline_draw.cc @@ -29,8 +29,6 @@ #include "IMB_imbuf.hh" #include "GPU_immediate.h" -#include "GPU_immediate_util.h" -#include "GPU_vertex_buffer.h" #include "GPU_viewport.h" #include "ED_anim_api.hh" @@ -1581,32 +1579,13 @@ struct CacheDrawData { float stripe_ofs_y; float stripe_ht; int cache_flag; - GPUVertBuf *raw_vbo; - GPUVertBuf *preprocessed_vbo; - GPUVertBuf *composite_vbo; - GPUVertBuf *final_out_vbo; - size_t raw_vert_count; - size_t preprocessed_vert_count; - size_t composite_vert_count; - size_t final_out_vert_count; + SeqQuadsBatch *quads; }; /* Called as a callback. */ -static bool draw_cache_view_init_fn(void *userdata, size_t item_count) +static bool draw_cache_view_init_fn(void * /*userdata*/, size_t item_count) { - if (item_count == 0) { - return true; - } - - CacheDrawData *drawdata = static_cast(userdata); - /* We can not get item count per cache type, so using total item count is safe. */ - size_t max_vert_count = item_count * 6; - GPU_vertbuf_data_alloc(drawdata->raw_vbo, max_vert_count); - GPU_vertbuf_data_alloc(drawdata->preprocessed_vbo, max_vert_count); - GPU_vertbuf_data_alloc(drawdata->composite_vbo, max_vert_count); - GPU_vertbuf_data_alloc(drawdata->final_out_vbo, max_vert_count); - - return false; + return item_count == 0; } /* Called as a callback */ @@ -1615,133 +1594,106 @@ static bool draw_cache_view_iter_fn(void *userdata, int timeline_frame, int cache_type) { + using blender::uchar4; CacheDrawData *drawdata = static_cast(userdata); - View2D *v2d = drawdata->v2d; + const View2D *v2d = drawdata->v2d; float stripe_bot; - GPUVertBuf *vbo; - size_t *vert_count; + + const uchar4 col_final{255, 102, 51, 100}; + const uchar4 col_raw{255, 25, 5, 100}; + const uchar4 col_preproc{25, 25, 191, 100}; + const uchar4 col_composite{255, 153, 0, 100}; + + uchar4 col{0, 0, 0, 0}; if ((cache_type & SEQ_CACHE_STORE_FINAL_OUT) && (drawdata->cache_flag & SEQ_CACHE_VIEW_FINAL_OUT)) { stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HANDLE_HEIGHT); - vbo = drawdata->final_out_vbo; - vert_count = &drawdata->final_out_vert_count; + col = col_final; } else if ((cache_type & SEQ_CACHE_STORE_RAW) && (drawdata->cache_flag & SEQ_CACHE_VIEW_RAW)) { stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + drawdata->stripe_ofs_y; - vbo = drawdata->raw_vbo; - vert_count = &drawdata->raw_vert_count; + col = col_raw; } else if ((cache_type & SEQ_CACHE_STORE_PREPROCESSED) && (drawdata->cache_flag & SEQ_CACHE_VIEW_PREPROCESSED)) { stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + drawdata->stripe_ht + drawdata->stripe_ofs_y * 2; - vbo = drawdata->preprocessed_vbo; - vert_count = &drawdata->preprocessed_vert_count; + col = col_preproc; } else if ((cache_type & SEQ_CACHE_STORE_COMPOSITE) && (drawdata->cache_flag & SEQ_CACHE_VIEW_COMPOSITE)) { stripe_bot = seq->machine + SEQ_STRIP_OFSTOP - drawdata->stripe_ofs_y - drawdata->stripe_ht; - vbo = drawdata->composite_vbo; - vert_count = &drawdata->composite_vert_count; + col = col_composite; } else { return false; } float stripe_top = stripe_bot + drawdata->stripe_ht; + drawdata->quads->add_quad(timeline_frame, stripe_bot, timeline_frame + 1, stripe_top, col); - float vert_pos[6][2]; - copy_v2_fl2(vert_pos[0], timeline_frame, stripe_bot); - copy_v2_fl2(vert_pos[1], timeline_frame, stripe_top); - copy_v2_fl2(vert_pos[2], timeline_frame + 1, stripe_top); - copy_v2_v2(vert_pos[3], vert_pos[2]); - copy_v2_v2(vert_pos[4], vert_pos[0]); - copy_v2_fl2(vert_pos[5], timeline_frame + 1, stripe_bot); - - for (int i = 0; i < 6; i++) { - GPU_vertbuf_vert_set(vbo, *vert_count + i, vert_pos[i]); - } - - *vert_count += 6; return false; } -static void draw_cache_view_batch( - GPUVertBuf *vbo, size_t vert_count, float col_r, float col_g, float col_b, float col_a) -{ - GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO); - if (vert_count > 0) { - GPU_vertbuf_data_len_set(vbo, vert_count); - GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); - GPU_batch_uniform_4f(batch, "color", col_r, col_g, col_b, col_a); - GPU_batch_draw(batch); - } - GPU_batch_discard(batch); -} - static void draw_cache_stripe(const Scene *scene, const Sequence *seq, - uint pos, + SeqQuadsBatch &quads, const float stripe_bot, const float stripe_ht, - const float bg_color[4]) + const uchar color[4]) { - immUniformColor4fv(bg_color); - immRectf(pos, - SEQ_time_left_handle_frame_get(scene, seq), - stripe_bot, - SEQ_time_right_handle_frame_get(scene, seq), - stripe_bot + stripe_ht); + quads.add_quad(SEQ_time_left_handle_frame_get(scene, seq), + stripe_bot, + SEQ_time_right_handle_frame_get(scene, seq), + stripe_bot + stripe_ht, + color); } static void draw_cache_background(const bContext *C, CacheDrawData *draw_data) { + using blender::uchar4; Scene *scene = CTX_data_scene(C); View2D *v2d = UI_view2d_fromcontext(C); - float bg_colors[4][4]; - copy_v4_fl4(bg_colors[0], 1.0f, 0.4f, 0.2f, 0.1f); - copy_v4_fl4(bg_colors[1], 1.0f, 0.1f, 0.02f, 0.1f); - copy_v4_fl4(bg_colors[2], 0.1f, 0.1f, 0.75f, 0.1f); - copy_v4_fl4(bg_colors[3], 1.0f, 0.6f, 0.0f, 0.1f); - GPU_blend(GPU_BLEND_ALPHA); - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + const uchar4 bg_final{255, 102, 51, 25}; + const uchar4 bg_raw{255, 25, 5, 25}; + const uchar4 bg_preproc{25, 25, 191, 25}; + const uchar4 bg_composite{255, 153, 0, 25}; float stripe_bot; if (scene->ed->cache_flag & SEQ_CACHE_VIEW_FINAL_OUT) { stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HANDLE_HEIGHT); - immUniformColor4fv(bg_colors[0]); - immRectf(pos, scene->r.sfra, stripe_bot, scene->r.efra, stripe_bot + draw_data->stripe_ht); + draw_data->quads->add_quad( + scene->r.sfra, stripe_bot, scene->r.efra, stripe_bot + draw_data->stripe_ht, bg_final); } blender::Vector strips = sequencer_visible_strips_get(C); strips.remove_if([&](Sequence *seq) { return seq->type == SEQ_TYPE_SOUND_RAM; }); - for (Sequence *seq : strips) { + for (const Sequence *seq : strips) { stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + draw_data->stripe_ofs_y; if (scene->ed->cache_flag & SEQ_CACHE_VIEW_RAW) { - draw_cache_stripe(scene, seq, pos, stripe_bot, draw_data->stripe_ht, bg_colors[1]); + draw_cache_stripe(scene, seq, *draw_data->quads, stripe_bot, draw_data->stripe_ht, bg_raw); } if (scene->ed->cache_flag & SEQ_CACHE_VIEW_PREPROCESSED) { stripe_bot += draw_data->stripe_ht + draw_data->stripe_ofs_y; - draw_cache_stripe(scene, seq, pos, stripe_bot, draw_data->stripe_ht, bg_colors[2]); + draw_cache_stripe( + scene, seq, *draw_data->quads, stripe_bot, draw_data->stripe_ht, bg_preproc); } if (scene->ed->cache_flag & SEQ_CACHE_VIEW_COMPOSITE) { stripe_bot = seq->machine + SEQ_STRIP_OFSTOP - draw_data->stripe_ofs_y - draw_data->stripe_ht; - draw_cache_stripe(scene, seq, pos, stripe_bot, draw_data->stripe_ht, bg_colors[3]); + draw_cache_stripe( + scene, seq, *draw_data->quads, stripe_bot, draw_data->stripe_ht, bg_composite); } } - - immUnbindProgram(); } static void draw_cache_view(const bContext *C) @@ -1760,34 +1712,20 @@ static void draw_cache_view(const bContext *C) CLAMP_MAX(stripe_ht, 0.2f); CLAMP_MIN(stripe_ofs_y, stripe_ht / 2); - GPUVertFormat format = {0}; - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - + SeqQuadsBatch quads; CacheDrawData userdata; userdata.v2d = v2d; userdata.stripe_ofs_y = stripe_ofs_y; userdata.stripe_ht = stripe_ht; userdata.cache_flag = scene->ed->cache_flag; - userdata.raw_vert_count = 0; - userdata.preprocessed_vert_count = 0; - userdata.composite_vert_count = 0; - userdata.final_out_vert_count = 0; - userdata.raw_vbo = GPU_vertbuf_create_with_format(&format); - userdata.preprocessed_vbo = GPU_vertbuf_create_with_format(&format); - userdata.composite_vbo = GPU_vertbuf_create_with_format(&format); - userdata.final_out_vbo = GPU_vertbuf_create_with_format(&format); + userdata.quads = &quads; - SEQ_cache_iterate(scene, &userdata, draw_cache_view_init_fn, draw_cache_view_iter_fn); + GPU_blend(GPU_BLEND_ALPHA); draw_cache_background(C, &userdata); - draw_cache_view_batch(userdata.raw_vbo, userdata.raw_vert_count, 1.0f, 0.1f, 0.02f, 0.4f); - draw_cache_view_batch( - userdata.preprocessed_vbo, userdata.preprocessed_vert_count, 0.1f, 0.1f, 0.75f, 0.4f); - draw_cache_view_batch( - userdata.composite_vbo, userdata.composite_vert_count, 1.0f, 0.6f, 0.0f, 0.4f); - draw_cache_view_batch( - userdata.final_out_vbo, userdata.final_out_vert_count, 1.0f, 0.4f, 0.2f, 0.4f); + SEQ_cache_iterate(scene, &userdata, draw_cache_view_init_fn, draw_cache_view_iter_fn); + quads.draw(); GPU_blend(GPU_BLEND_NONE); }