From ef46100fd39bdeb7d590f29e1a7cc5f2d6fc0b47 Mon Sep 17 00:00:00 2001 From: Lenny Maiorani Date: Thu, 23 Jun 2022 13:11:05 -0600 Subject: [PATCH] LibGfx: Increase cache-friendliness in FastBoxBlurFilter Change from 4 vectors of u8 to a single vector of a struct of 4 u8. Since all the accesses are on the same indicies into each vector the cache pressure is decreased by co-locating the data. When scrolling up and down in the `box-shadow` example page the profile changes from about 75% of the function calls being in `apply_single_pass()` to only about 70% on my machine. --- .../LibGfx/Filters/FastBoxBlurFilter.cpp | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/Userland/Libraries/LibGfx/Filters/FastBoxBlurFilter.cpp b/Userland/Libraries/LibGfx/Filters/FastBoxBlurFilter.cpp index cf5f94833d..5ac41a356c 100644 --- a/Userland/Libraries/LibGfx/Filters/FastBoxBlurFilter.cpp +++ b/Userland/Libraries/LibGfx/Filters/FastBoxBlurFilter.cpp @@ -43,15 +43,8 @@ static void do_single_pass(int width, int height, size_t radius_x, size_t radius int div_x = 2 * radius_x + 1; int div_y = 2 * radius_y + 1; - Vector intermediate_red; - Vector intermediate_green; - Vector intermediate_blue; - Vector intermediate_alpha; - - intermediate_red.resize(width * height); - intermediate_green.resize(width * height); - intermediate_blue.resize(width * height); - intermediate_alpha.resize(width * height); + Vector intermediate; + intermediate.resize(width * height); // First pass: vertical for (int y = 0; y < height; ++y) { @@ -70,10 +63,12 @@ static void do_single_pass(int width, int height, size_t radius_x, size_t radius } // Slide horizontally for (int x = 0; x < width; ++x) { - intermediate_red[y * width + x] = (sum_red / div_x); - intermediate_green[y * width + x] = (sum_green / div_x); - intermediate_blue[y * width + x] = (sum_blue / div_x); - intermediate_alpha[y * width + x] = (sum_alpha / div_x); + auto const index = y * width + x; + auto& current_intermediate = intermediate[index]; + current_intermediate.set_red(sum_red / div_x); + current_intermediate.set_green(sum_green / div_x); + current_intermediate.set_blue(sum_blue / div_x); + current_intermediate.set_alpha(sum_alpha / div_x); auto leftmost_x_coord = max(x - (int)radius_x, 0); auto rightmost_x_coord = min(x + (int)radius_x + 1, width - 1); @@ -102,10 +97,11 @@ static void do_single_pass(int width, int height, size_t radius_x, size_t radius // Setup sliding window for (int i = -(int)radius_y; i <= (int)radius_y; ++i) { int offset = clamp(i, 0, height - 1) * width + x; - sum_red += intermediate_red[offset]; - sum_green += intermediate_green[offset]; - sum_blue += intermediate_blue[offset]; - sum_alpha += intermediate_alpha[offset]; + auto& current_intermediate = intermediate[offset]; + sum_red += current_intermediate.red(); + sum_green += current_intermediate.green(); + sum_blue += current_intermediate.blue(); + sum_alpha += current_intermediate.alpha(); } for (int y = 0; y < height; ++y) { @@ -117,17 +113,21 @@ static void do_single_pass(int width, int height, size_t radius_x, size_t radius set_pixel_function(x, y, color); - auto topmost_y_coord = max(y - (int)radius_y, 0); - auto bottommost_y_coord = min(y + (int)radius_y + 1, height - 1); + auto const bottommost_y_coord = min(y + (int)radius_y + 1, height - 1); + auto const bottom_index = x + bottommost_y_coord * width; + auto& bottom_intermediate = intermediate[bottom_index]; + sum_red += bottom_intermediate.red(); + sum_green += bottom_intermediate.green(); + sum_blue += bottom_intermediate.blue(); + sum_alpha += bottom_intermediate.alpha(); - sum_red += intermediate_red[x + bottommost_y_coord * width]; - sum_red -= intermediate_red[x + topmost_y_coord * width]; - sum_green += intermediate_green[x + bottommost_y_coord * width]; - sum_green -= intermediate_green[x + topmost_y_coord * width]; - sum_blue += intermediate_blue[x + bottommost_y_coord * width]; - sum_blue -= intermediate_blue[x + topmost_y_coord * width]; - sum_alpha += intermediate_alpha[x + bottommost_y_coord * width]; - sum_alpha -= intermediate_alpha[x + topmost_y_coord * width]; + auto const topmost_y_coord = max(y - (int)radius_y, 0); + auto const top_index = x + topmost_y_coord * width; + auto& top_intermediate = intermediate[top_index]; + sum_red -= top_intermediate.red(); + sum_green -= top_intermediate.green(); + sum_blue -= top_intermediate.blue(); + sum_alpha -= top_intermediate.alpha(); } } }