From ab7214ca2ef93c0827d2dbb1ecbdebca184996bf Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 8 Nov 2021 16:49:19 +0100 Subject: Fix performance issues with pose library sidebar and many poses When the asset view in the sidebar of the pose library would contain more than a few handful poses, interaction and animation playback performance would be impacted considerably. This was because our icon drawing scales image buffers using a rather slow method on the CPU. This commit changes it so the asset icons are scaled using the GPU. Note that this is a temporary change. I'd like all icon code to use GPU-side scaling, see D13144. But such a change is too risky to do in the release branch at this point, so this fix is specifically for the 3.0 release. --- source/blender/editors/interface/interface_icons.c | 76 +++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index e7991d46918..f849ec55e4f 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1482,6 +1482,78 @@ PreviewImage *UI_icon_to_preview(int icon_id) return NULL; } +/** + * Version of #icon_draw_rect() that uses the GPU for scaling. This is only used for + * #ICON_TYPE_IMBUF because it's a backported fix for performance issues, see T92922. Only + * File/Asset Browser use #ICON_TYPE_IMBUF right now, which makes implications more predictable. + * + * TODO(Julian): This code is mostly duplicated. #icon_draw_rect() should be ported to use the GPU + * instead (D13144). + */ +static void icon_draw_rect_fast(float x, + float y, + int w, + int h, + float UNUSED(aspect), + int rw, + int rh, + uint *rect, + float alpha, + const float desaturate) +{ + int draw_w = w; + int draw_h = h; + int draw_x = x; + /* We need to round y, to avoid the icon jittering in some cases. */ + int draw_y = round_fl_to_int(y); + + /* sanity check */ + if (w <= 0 || h <= 0 || w > 2000 || h > 2000) { + printf("%s: icons are %i x %i pixels?\n", __func__, w, h); + BLI_assert_msg(0, "invalid icon size"); + return; + } + /* modulate color */ + const float col[4] = {alpha, alpha, alpha, alpha}; + + float scale_x = 1.0f; + float scale_y = 1.0f; + /* rect contains image in 'rendersize', we only scale if needed */ + if (rw != w || rh != h) { + /* preserve aspect ratio and center */ + if (rw > rh) { + draw_w = w; + draw_h = (int)(((float)rh / (float)rw) * (float)w); + draw_y += (h - draw_h) / 2; + } + else if (rw < rh) { + draw_w = (int)(((float)rw / (float)rh) * (float)h); + draw_h = h; + draw_x += (w - draw_w) / 2; + } + scale_x = draw_w / (float)rw; + scale_y = draw_h / (float)rh; + /* If the image is squared, the `draw_*` initialization values are good. */ + } + + /* draw */ + eGPUBuiltinShader shader; + if (desaturate != 0.0f) { + shader = GPU_SHADER_2D_IMAGE_DESATURATE_COLOR; + } + else { + shader = GPU_SHADER_2D_IMAGE_COLOR; + } + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(shader); + + if (shader == GPU_SHADER_2D_IMAGE_DESATURATE_COLOR) { + immUniform1f("factor", desaturate); + } + + immDrawPixelsTexScaled( + &state, draw_x, draw_y, rw, rh, GPU_RGBA8, true, rect, scale_x, scale_y, 1.0f, 1.0f, col); +} + static void icon_draw_rect(float x, float y, int w, @@ -1806,7 +1878,9 @@ static void icon_draw_size(float x, ImBuf *ibuf = icon->obj; GPU_blend(GPU_BLEND_ALPHA_PREMULT); - icon_draw_rect(x, y, w, h, aspect, ibuf->x, ibuf->y, ibuf->rect, alpha, desaturate); + /* These icons are only used by the File/Asset Browser currently. Without this `_fast()` + * version, there may be performance issues, see T92922. */ + icon_draw_rect_fast(x, y, w, h, aspect, ibuf->x, ibuf->y, ibuf->rect, alpha, desaturate); GPU_blend(GPU_BLEND_ALPHA); } else if (di->type == ICON_TYPE_VECTOR) { -- cgit v1.2.3