Skip to content

Commit 11af881

Browse files
committed
perf: optimize Highway row kernels
1 parent 6bcf6eb commit 11af881

6 files changed

Lines changed: 190 additions & 96 deletions

File tree

src/core/delogo_processor.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ void process_opaque_row(
6161
std::span<Pixel> row,
6262
std::span<const int> colors,
6363
std::span<const int> depths,
64+
std::span<const std::uint32_t> erase_reciprocals,
6465
int bit_depth
6566
) {
6667
if (backend == RowKernelBackend::Scalar) {
@@ -75,7 +76,7 @@ void process_opaque_row(
7576
if (operation == LogoOperation::Add) {
7677
process_add_row_hwy(row, colors, depths, bit_depth);
7778
} else {
78-
process_erase_row_hwy(row, colors, depths, bit_depth);
79+
process_erase_row_hwy(row, colors, depths, erase_reciprocals, bit_depth);
7980
}
8081
}
8182

@@ -187,6 +188,7 @@ void DelogoProcessor::process_plane(
187188
row,
188189
coefficients.c_row(i).first(row_width),
189190
coefficients.d_row(i).first(row_width),
191+
coefficients.d_reciprocal_row(i).first(row_width),
190192
bit_depth_
191193
);
192194
}

src/core/prepared_logo.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "core/canonical_math.hpp"
44
#include "core/delogo_processor.hpp"
5+
#include "core/reciprocal_math.hpp"
56

67
#include <algorithm>
78
#include <optional>
@@ -22,6 +23,14 @@ int chroma_color_for_block(std::int64_t weighted_color, int sum_depth) {
2223
return round_divide_signed(weighted_color, sum_depth);
2324
}
2425

26+
std::uint32_t erase_reciprocal_for_depth(int depth) {
27+
int alpha = clamp_logo_depth(depth);
28+
if (alpha >= LOGO_MAX_DP) {
29+
alpha = LOGO_MAX_DP - 1;
30+
}
31+
return kLogoReciprocalTable32[static_cast<std::size_t>(LOGO_MAX_DP - alpha)];
32+
}
33+
2534
std::optional<LogoImage> shift_logo(LogoImage image, int left, int top) {
2635
const int oldl = image.header.x + left;
2736
const int oldt = image.header.y + top;
@@ -126,10 +135,11 @@ void LogoPlaneCoefficients::reset(int width, int height) {
126135
height_ = height;
127136
c_.reset(static_cast<std::size_t>(width_) * height_);
128137
d_.reset(static_cast<std::size_t>(width_) * height_);
138+
d_reciprocal_.reset(static_cast<std::size_t>(width_) * height_);
129139
}
130140

131141
bool LogoPlaneCoefficients::active() const noexcept {
132-
return !c_.empty() && !d_.empty();
142+
return !c_.empty() && !d_.empty() && !d_reciprocal_.empty();
133143
}
134144

135145
int LogoPlaneCoefficients::width() const noexcept {
@@ -154,6 +164,13 @@ std::span<int> LogoPlaneCoefficients::d_row(int y) noexcept {
154164
);
155165
}
156166

167+
std::span<std::uint32_t> LogoPlaneCoefficients::d_reciprocal_row(int y) noexcept {
168+
return d_reciprocal_.subspan(
169+
static_cast<std::size_t>(y) * width_,
170+
static_cast<std::size_t>(width_)
171+
);
172+
}
173+
157174
std::span<const int> LogoPlaneCoefficients::c_row(int y) const noexcept {
158175
return c_.subspan(
159176
static_cast<std::size_t>(y) * width_,
@@ -168,6 +185,13 @@ std::span<const int> LogoPlaneCoefficients::d_row(int y) const noexcept {
168185
);
169186
}
170187

188+
std::span<const std::uint32_t> LogoPlaneCoefficients::d_reciprocal_row(int y) const noexcept {
189+
return d_reciprocal_.subspan(
190+
static_cast<std::size_t>(y) * width_,
191+
static_cast<std::size_t>(width_)
192+
);
193+
}
194+
171195
PreparedLogo::PreparedLogo(const DelogoProcessorConfig& config)
172196
: subsampling_w_(config.subsampling_w),
173197
subsampling_h_(config.subsampling_h),
@@ -214,6 +238,7 @@ void PreparedLogo::convert(LogoImage& image, bool mono) {
214238
for (int y = 0; y < logo_header_.h; ++y) {
215239
auto y_c = planes_[0].c_row(y);
216240
auto y_d = planes_[0].d_row(y);
241+
auto y_d_reciprocal = planes_[0].d_reciprocal_row(y);
217242
for (int x = 0; x < logo_header_.w; ++x) {
218243
const auto index = (static_cast<std::size_t>(y) * logo_header_.w) + x;
219244
LOGO_PIXEL& pixel = image.pixels[index];
@@ -225,6 +250,7 @@ void PreparedLogo::convert(LogoImage& image, bool mono) {
225250
pixel.dp_y = static_cast<int16_t>(clamp_logo_depth(pixel.dp_y));
226251
y_c[x] = luma_to_internal_color(pixel.y);
227252
y_d[x] = pixel.dp_y;
253+
y_d_reciprocal[x] = erase_reciprocal_for_depth(pixel.dp_y);
228254
if (mono) {
229255
pixel.cb = 0;
230256
pixel.cr = 0;
@@ -245,8 +271,10 @@ void PreparedLogo::convert(LogoImage& image, bool mono) {
245271
const int dst_y = y / hstep;
246272
auto u_c_row = planes_[1].c_row(dst_y);
247273
auto u_d_row = planes_[1].d_row(dst_y);
274+
auto u_d_reciprocal_row = planes_[1].d_reciprocal_row(dst_y);
248275
auto v_c_row = planes_[2].c_row(dst_y);
249276
auto v_d_row = planes_[2].d_row(dst_y);
277+
auto v_d_reciprocal_row = planes_[2].d_reciprocal_row(dst_y);
250278

251279
for (int x = 0; x < logo_header_.w; x += wstep) {
252280
const int dst_x = x / wstep;
@@ -281,6 +309,8 @@ void PreparedLogo::convert(LogoImage& image, bool mono) {
281309
v_c_row[dst_x] = chroma_to_internal_color(vc);
282310
u_d_row[dst_x] = ud;
283311
v_d_row[dst_x] = vd;
312+
u_d_reciprocal_row[dst_x] = erase_reciprocal_for_depth(ud);
313+
v_d_reciprocal_row[dst_x] = erase_reciprocal_for_depth(vd);
284314
}
285315
}
286316
}

src/core/prepared_logo.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "core/logo_file.hpp"
55

66
#include <cstddef>
7+
#include <cstdint>
78
#include <span>
89

910
namespace delogohd::core {
@@ -22,14 +23,17 @@ class LogoPlaneCoefficients {
2223
[[nodiscard]] int height() const noexcept;
2324
std::span<int> c_row(int y) noexcept;
2425
std::span<int> d_row(int y) noexcept;
26+
std::span<std::uint32_t> d_reciprocal_row(int y) noexcept;
2527
[[nodiscard]] std::span<const int> c_row(int y) const noexcept;
2628
[[nodiscard]] std::span<const int> d_row(int y) const noexcept;
29+
[[nodiscard]] std::span<const std::uint32_t> d_reciprocal_row(int y) const noexcept;
2730

2831
private:
2932
int width_ = 0;
3033
int height_ = 0;
3134
AlignedBuffer<int, kLogoAlignment> c_;
3235
AlignedBuffer<int, kLogoAlignment> d_;
36+
AlignedBuffer<std::uint32_t, kLogoAlignment> d_reciprocal_;
3337
};
3438

3539
class PreparedLogo {

src/core/reciprocal_math.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ constexpr std::array<std::uint64_t, LOGO_MAX_DP + 1> make_logo_reciprocal_table(
2121

2222
inline constexpr auto kLogoReciprocalTable = make_logo_reciprocal_table();
2323

24+
constexpr std::array<std::uint32_t, LOGO_MAX_DP + 1> make_logo_reciprocal_table32() noexcept {
25+
std::array<std::uint32_t, LOGO_MAX_DP + 1> table{};
26+
// 1 << 32 does not fit in u32; the correction step still yields exact / 1.
27+
table[1] = 0xFFFFFFFFu;
28+
for (int denominator = 2; denominator <= LOGO_MAX_DP; ++denominator) {
29+
table[denominator] = static_cast<std::uint32_t>(
30+
kReciprocalScale / static_cast<std::uint64_t>(denominator)
31+
);
32+
}
33+
return table;
34+
}
35+
36+
inline constexpr auto kLogoReciprocalTable32 = make_logo_reciprocal_table32();
37+
2438
inline std::uint64_t divide_floor_by_reciprocal(
2539
std::uint64_t numerator,
2640
int denominator

src/core/row_kernel.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,14 @@ void process_erase_row_hwy(
4646
std::span<std::uint8_t> row,
4747
std::span<const int> colors,
4848
std::span<const int> depths,
49+
std::span<const std::uint32_t> reciprocals,
4950
int bit_depth
5051
);
5152
void process_erase_row_hwy(
5253
std::span<std::uint16_t> row,
5354
std::span<const int> colors,
5455
std::span<const int> depths,
56+
std::span<const std::uint32_t> reciprocals,
5557
int bit_depth
5658
);
5759

0 commit comments

Comments
 (0)