mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 14:18:21 +01:00
neon: GetResidualCost
Direct copy of sse2. Slight improvement because neon has abs(). flower.ppm had minimal improvement. Somewhat expected because GetResidualCost_C is only ~3.6% mug.ppm had a better improvement because GetResidualCost_C is almost 9%. C 2.150 NEON 2.130 BUG=b/118740850 Change-Id: Ibc0dd97a81596635f5599cf568205974b4fd2597
This commit is contained in:
parent
0fd7514b55
commit
9f4d4a3f49
@ -48,6 +48,63 @@ static void SetResidualCoeffs_NEON(const int16_t* const coeffs,
|
|||||||
res->coeffs = coeffs;
|
res->coeffs = coeffs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int GetResidualCost_NEON(int ctx0, const VP8Residual* const res) {
|
||||||
|
uint8_t levels[16], ctxs[16];
|
||||||
|
uint16_t abs_levels[16];
|
||||||
|
int n = res->first;
|
||||||
|
// should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
|
||||||
|
const int p0 = res->prob[n][ctx0][0];
|
||||||
|
CostArrayPtr const costs = res->costs;
|
||||||
|
const uint16_t* t = costs[n][ctx0];
|
||||||
|
// bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0
|
||||||
|
// (as required by the syntax). For ctx0 == 0, we need to add it here or it'll
|
||||||
|
// be missing during the loop.
|
||||||
|
int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0;
|
||||||
|
|
||||||
|
if (res->last < 0) {
|
||||||
|
return VP8BitCost(0, p0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // precompute clamped levels and contexts, packed to 8b.
|
||||||
|
const uint8x16_t kCst2 = vdupq_n_u8(2);
|
||||||
|
const uint8x16_t kCst67 = vdupq_n_u8(MAX_VARIABLE_LEVEL);
|
||||||
|
const int16x8_t c0 = vld1q_s16(res->coeffs);
|
||||||
|
const int16x8_t c1 = vld1q_s16(res->coeffs + 8);
|
||||||
|
const uint16x8_t E0 = vreinterpretq_u16_s16(vabsq_s16(c0));
|
||||||
|
const uint16x8_t E1 = vreinterpretq_u16_s16(vabsq_s16(c1));
|
||||||
|
const uint8x16_t F = vcombine_u8(vqmovn_u16(E0), vqmovn_u16(E1));
|
||||||
|
const uint8x16_t G = vminq_u8(F, kCst2); // context = 0,1,2
|
||||||
|
const uint8x16_t H = vminq_u8(F, kCst67); // clamp_level in [0..67]
|
||||||
|
|
||||||
|
vst1q_u8(ctxs, G);
|
||||||
|
vst1q_u8(levels, H);
|
||||||
|
|
||||||
|
vst1q_u16(abs_levels, E0);
|
||||||
|
vst1q_u16(abs_levels + 8, E1);
|
||||||
|
}
|
||||||
|
for (; n < res->last; ++n) {
|
||||||
|
const int ctx = ctxs[n];
|
||||||
|
const int level = levels[n];
|
||||||
|
const int flevel = abs_levels[n]; // full level
|
||||||
|
cost += VP8LevelFixedCosts[flevel] + t[level]; // simplified VP8LevelCost()
|
||||||
|
t = costs[n + 1][ctx];
|
||||||
|
}
|
||||||
|
// Last coefficient is always non-zero
|
||||||
|
{
|
||||||
|
const int level = levels[n];
|
||||||
|
const int flevel = abs_levels[n];
|
||||||
|
assert(flevel != 0);
|
||||||
|
cost += VP8LevelFixedCosts[flevel] + t[level];
|
||||||
|
if (n < 15) {
|
||||||
|
const int b = VP8EncBands[n + 1];
|
||||||
|
const int ctx = ctxs[n];
|
||||||
|
const int last_p0 = res->prob[b][ctx][0];
|
||||||
|
cost += VP8BitCost(0, last_p0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Entry point
|
// Entry point
|
||||||
|
|
||||||
@ -55,6 +112,7 @@ extern void VP8EncDspCostInitNEON(void);
|
|||||||
|
|
||||||
WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitNEON(void) {
|
WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitNEON(void) {
|
||||||
VP8SetResidualCoeffs = SetResidualCoeffs_NEON;
|
VP8SetResidualCoeffs = SetResidualCoeffs_NEON;
|
||||||
|
VP8GetResidualCost = GetResidualCost_NEON;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // !WEBP_USE_NEON
|
#else // !WEBP_USE_NEON
|
||||||
|
Loading…
Reference in New Issue
Block a user