shithub: dav1d

Download patch

ref: bb505b3e7bbd23e67531ce82059845b2d83cdbe9
parent: 7e693a1d26779acf8e21378a898c25ab35f2bcac
author: Henrik Gramner <gramner@twoorioles.com>
date: Fri Oct 5 11:33:35 EDT 2018

Intra prediction DSP refactoring

Also remove some redundant clips in DC pred.

--- a/src/decode.c
+++ b/src/decode.c
@@ -2713,7 +2713,7 @@
     const int bd_idx = (f->seq_hdr.bpc - 8) >> 1;
     f->dsp = &c->dsp[bd_idx];
 
-    if (!f->dsp->ipred.intra_pred[TX_4X4][DC_PRED]) {
+    if (!f->dsp->ipred.intra_pred[DC_PRED]) {
         Dav1dDSPContext *const dsp = &c->dsp[bd_idx];
 
         switch (f->seq_hdr.bpc) {
--- a/src/ipred.c
+++ b/src/ipred.c
@@ -35,45 +35,25 @@
 #include "common/intops.h"
 
 #include "src/ipred.h"
+#include "src/tables.h"
 
-#define sz_grid(l_fn) \
-l_fn( 4,  4) \
-l_fn( 4,  8) \
-l_fn( 4, 16) \
-l_fn( 8,  4) \
-l_fn( 8,  8) \
-l_fn( 8, 16) \
-l_fn( 8, 32) \
-l_fn(16,  4) \
-l_fn(16,  8) \
-l_fn(16, 16) \
-l_fn(16, 32) \
-l_fn(16, 64) \
-l_fn(32,  8) \
-l_fn(32, 16) \
-l_fn(32, 32) \
-l_fn(32, 64) \
-l_fn(64, 16) \
-l_fn(64, 32) \
-l_fn(64, 64)
-
 static NOINLINE void
-splat_dc_c(pixel *dst, const ptrdiff_t stride,
-           const int w, const int h, const unsigned dc)
+splat_dc(pixel *dst, const ptrdiff_t stride,
+         const int width, const int height, const unsigned dc)
 {
     assert(dc <= (1 << BITDEPTH) - 1);
 #if BITDEPTH == 8
-    if (w > 4) {
+    if (width > 4) {
         const uint64_t dcN = dc * 0x0101010101010101ULL;
-        for (int y = 0; y < h; y++) {
-            for (int x = 0; x < w; x += sizeof(dcN))
+        for (int y = 0; y < height; y++) {
+            for (int x = 0; x < width; x += sizeof(dcN))
                 *((uint64_t *) &dst[x]) = dcN;
             dst += PXSTRIDE(stride);
         }
     } else {
         const unsigned dcN = dc * 0x01010101U;
-        for (int y = 0; y < h; y++) {
-            for (int x = 0; x < w; x += sizeof(dcN))
+        for (int y = 0; y < height; y++) {
+            for (int x = 0; x < width; x += sizeof(dcN))
                 *((unsigned *) &dst[x]) = dcN;
             dst += PXSTRIDE(stride);
         }
@@ -80,8 +60,8 @@
     }
 #else
     const uint64_t dcN = dc * 0x0001000100010001ULL;
-    for (int y = 0; y < h; y++) {
-        for (int x = 0; x < w; x += sizeof(dcN) >> 1)
+    for (int y = 0; y < height; y++) {
+        for (int x = 0; x < width; x += sizeof(dcN) >> 1)
             *((uint64_t *) &dst[x]) = dcN;
         dst += PXSTRIDE(stride);
     }
@@ -88,52 +68,28 @@
 #endif
 }
 
-#define dc_lfn(w, h, dir, dc_gen) \
-static void dc##dir##_##w##x##h##_c(pixel *dst, const ptrdiff_t stride, \
-                                    const pixel *const topleft, const int a) \
-{ \
-    dc_gen; \
-    splat_dc_c(dst, stride, w, h, dc); \
+static void ipred_dc_top_c(pixel *dst, const ptrdiff_t stride,
+                           const pixel *const topleft,
+                           const int width, const int height, const int a)
+{
+    unsigned dc = width >> 1;
+    for (int i = 0; i < width; i++)
+       dc += topleft[1 + i];
+
+    splat_dc(dst, stride, width, height, dc >> ctz(width));
 }
 
-#define dc1d_lfns(width, height, sh1, sh2) \
-dc_lfn(width, height, top, unsigned dc = width >> 1; \
-                           for (int i = 0; i < width; i++) \
-                               dc += topleft[1 + i]; \
-                           dc >>= sh1) \
-dc_lfn(width, height, left, unsigned dc = height >> 1; \
-                            for (int i = 0; i < height; i++) \
-                                dc += topleft[-(1 + i)]; \
-                            dc >>= sh2)
+static void ipred_dc_left_c(pixel *dst, const ptrdiff_t stride,
+                            const pixel *const topleft,
+                            const int width, const int height, const int a)
+{
+    unsigned dc = height >> 1;
+    for (int i = 0; i < height; i++)
+       dc += topleft[-(1 + i)];
 
-dc1d_lfns( 4,  4, 2, 2)
-dc1d_lfns( 4,  8, 2, 3)
-dc1d_lfns( 4, 16, 2, 4)
-dc1d_lfns( 8,  4, 3, 2)
-dc1d_lfns( 8,  8, 3, 3)
-dc1d_lfns( 8, 16, 3, 4)
-dc1d_lfns( 8, 32, 3, 5)
-dc1d_lfns(16,  4, 4, 2)
-dc1d_lfns(16,  8, 4, 3)
-dc1d_lfns(16, 16, 4, 4)
-dc1d_lfns(16, 32, 4, 5)
-dc1d_lfns(16, 64, 4, 6)
-dc1d_lfns(32,  8, 5, 3)
-dc1d_lfns(32, 16, 5, 4)
-dc1d_lfns(32, 32, 5, 5)
-dc1d_lfns(32, 64, 5, 6)
-dc1d_lfns(64, 16, 6, 4)
-dc1d_lfns(64, 32, 6, 5)
-dc1d_lfns(64, 64, 6, 6)
+    splat_dc(dst, stride, width, height, dc >> ctz(height));
+}
 
-#define dc2d_lfn(width, height, dc_gen) \
-dc_lfn(width, height,, unsigned dc = (width + height) >> 1; \
-                       for (int i = 0; i < width; i++) \
-                           dc += topleft[i + 1]; \
-                       for (int i = 0; i < height; i++) \
-                           dc += topleft[-(i + 1)]; \
-                       dc_gen)
-
 #if BITDEPTH == 8
 #define MULTIPLIER_1x2 0x5556
 #define MULTIPLIER_1x4 0x3334
@@ -144,38 +100,40 @@
 #define BASE_SHIFT 17
 #endif
 
-dc2d_lfn( 4,  4, dc >>= 3)
-dc2d_lfn( 4,  8, dc = iclip_pixel(MULTIPLIER_1x2 * (dc >> 2) >> BASE_SHIFT))
-dc2d_lfn( 4, 16, dc = iclip_pixel(MULTIPLIER_1x4 * (dc >> 2) >> BASE_SHIFT))
-dc2d_lfn( 8,  4, dc = iclip_pixel(MULTIPLIER_1x2 * (dc >> 2) >> BASE_SHIFT))
-dc2d_lfn( 8,  8, dc >>= 4)
-dc2d_lfn( 8, 16, dc = iclip_pixel(MULTIPLIER_1x2 * (dc >> 3) >> BASE_SHIFT))
-dc2d_lfn( 8, 32, dc = iclip_pixel(MULTIPLIER_1x4 * (dc >> 3) >> BASE_SHIFT))
-dc2d_lfn(16,  4, dc = iclip_pixel(MULTIPLIER_1x4 * (dc >> 2) >> BASE_SHIFT))
-dc2d_lfn(16,  8, dc = iclip_pixel(MULTIPLIER_1x2 * (dc >> 3) >> BASE_SHIFT))
-dc2d_lfn(16, 16, dc >>= 5)
-dc2d_lfn(16, 32, dc = iclip_pixel(MULTIPLIER_1x2 * (dc >> 4) >> BASE_SHIFT))
-dc2d_lfn(16, 64, dc = iclip_pixel(MULTIPLIER_1x4 * (dc >> 4) >> BASE_SHIFT))
-dc2d_lfn(32,  8, dc = iclip_pixel(MULTIPLIER_1x4 * (dc >> 3) >> BASE_SHIFT))
-dc2d_lfn(32, 16, dc = iclip_pixel(MULTIPLIER_1x2 * (dc >> 4) >> BASE_SHIFT))
-dc2d_lfn(32, 32, dc >>= 6)
-dc2d_lfn(32, 64, dc = iclip_pixel(MULTIPLIER_1x2 * (dc >> 5) >> BASE_SHIFT))
-dc2d_lfn(64, 16, dc = iclip_pixel(MULTIPLIER_1x4 * (dc >> 4) >> BASE_SHIFT))
-dc2d_lfn(64, 32, dc = iclip_pixel(MULTIPLIER_1x2 * (dc >> 5) >> BASE_SHIFT))
-dc2d_lfn(64, 64, dc >>= 7)
+static void ipred_dc_c(pixel *dst, const ptrdiff_t stride,
+                       const pixel *const topleft,
+                       const int width, const int height, const int a)
+{
+    unsigned dc = (width + height) >> 1;
+    for (int i = 0; i < width; i++)
+       dc += topleft[i + 1];
+    for (int i = 0; i < height; i++)
+       dc += topleft[-(i + 1)];
+    dc >>= ctz(width + height);
 
+    if (width != height) {
+        dc *= (width > height * 2 || height > width * 2) ? MULTIPLIER_1x4 :
+                                                           MULTIPLIER_1x2;
+        dc >>= BASE_SHIFT;
+    }
+
+    splat_dc(dst, stride, width, height, dc);
+}
+
 #undef MULTIPLIER_1x2
 #undef MULTIPLIER_1x4
 #undef BASE_SHIFT
 
-#define dc128_lfn(width, height) \
-dc_lfn(width, height, 128, const unsigned dc = (1 << BITDEPTH) >> 1)
+static void ipred_dc_128_c(pixel *dst, const ptrdiff_t stride,
+                           const pixel *const topleft,
+                           const int width, const int height, const int a)
+{
+    splat_dc(dst, stride, width, height, 1 << (BITDEPTH - 1));
+}
 
-sz_grid(dc128_lfn)
-
-static NOINLINE void
-v_c(pixel *dst, const ptrdiff_t stride,
-    const pixel *const topleft, const int width, const int height)
+static void ipred_v_c(pixel *dst, const ptrdiff_t stride,
+                      const pixel *const topleft,
+                      const int width, const int height, const int a)
 {
     for (int y = 0; y < height; y++) {
         pixel_copy(dst, topleft + 1, width);
@@ -183,18 +141,9 @@
     }
 }
 
-#define v_lfn(width, height) \
-static void v_##width##x##height##_##c(pixel *dst, const ptrdiff_t stride, \
-                                       const pixel *const topleft, const int a) \
-{ \
-    v_c(dst, stride, topleft, width, height); \
-}
-
-sz_grid(v_lfn)
-
-static NOINLINE void
-h_c(pixel *dst, const ptrdiff_t stride,
-    const pixel *const topleft, const int width, const int height)
+static void ipred_h_c(pixel *dst, const ptrdiff_t stride,
+                      const pixel *const topleft,
+                      const int width, const int height, const int a)
 {
     for (int y = 0; y < height; y++) {
         pixel_set(dst, topleft[-(1 + y)], width);
@@ -202,18 +151,9 @@
     }
 }
 
-#define h_lfn(width, height) \
-static void h_##width##x##height##_c(pixel *dst, const ptrdiff_t stride, \
-                                     const pixel *const topleft, const int a) \
-{ \
-    h_c(dst, stride, topleft, width, height); \
-}
-
-sz_grid(h_lfn)
-
-static NOINLINE void
-paeth_c(pixel *dst, const ptrdiff_t stride, const pixel *const tl_ptr,
-        const int width, const int height)
+static void ipred_paeth_c(pixel *dst, const ptrdiff_t stride,
+                          const pixel *const tl_ptr,
+                          const int width, const int height, const int a)
 {
     const int topleft = tl_ptr[0];
     for (int y = 0; y < height; y++) {
@@ -232,43 +172,12 @@
     }
 }
 
-#define paeth_lfn(width, height) \
-static void paeth_##width##x##height##_c(pixel *dst, const ptrdiff_t stride, \
-                                         const pixel *const topleft, \
-                                         const int a) \
-{ \
-    paeth_c(dst, stride, topleft, width, height); \
-}
-
-sz_grid(paeth_lfn)
-
-static const uint8_t sm_weight_arrays[] = {
-    // Unused, because we always offset by bs, which is at least 2.
-    0, 0,
-    // bs = 2
-    255, 128,
-    // bs = 4
-    255, 149, 85, 64,
-    // bs = 8
-    255, 197, 146, 105, 73, 50, 37, 32,
-    // bs = 16
-    255, 225, 196, 170, 145, 123, 102, 84, 68, 54, 43, 33, 26, 20, 17, 16,
-    // bs = 32
-    255, 240, 225, 210, 196, 182, 169, 157, 145, 133, 122, 111, 101, 92, 83, 74,
-    66, 59, 52, 45, 39, 34, 29, 25, 21, 17, 14, 12, 10, 9, 8, 8,
-    // bs = 64
-    255, 248, 240, 233, 225, 218, 210, 203, 196, 189, 182, 176, 169, 163, 156,
-    150, 144, 138, 133, 127, 121, 116, 111, 106, 101, 96, 91, 86, 82, 77, 73, 69,
-    65, 61, 57, 54, 50, 47, 44, 41, 38, 35, 32, 29, 27, 25, 22, 20, 18, 16, 15,
-    13, 12, 10, 9, 8, 7, 6, 6, 5, 5, 4, 4, 4,
-};
-
-static NOINLINE void
-smooth_c(pixel *dst, const ptrdiff_t stride, const pixel *const topleft,
-         const int width, const int height)
+static void ipred_smooth_c(pixel *dst, const ptrdiff_t stride,
+                           const pixel *const topleft,
+                           const int width, const int height, const int a)
 {
-    const uint8_t *const weights_hor = &sm_weight_arrays[width];
-    const uint8_t *const weights_ver = &sm_weight_arrays[height];
+    const uint8_t *const weights_hor = &dav1d_sm_weights[width];
+    const uint8_t *const weights_ver = &dav1d_sm_weights[height];
     const int right = topleft[width], bottom = topleft[-height];
 
     for (int y = 0; y < height; y++) {
@@ -283,21 +192,11 @@
     }
 }
 
-#define smooth_lfn(width, height) \
-static void smooth_##width##x##height##_c(pixel *dst, const ptrdiff_t stride, \
-                                          const pixel *const topleft, \
-                                          const int a) \
-{ \
-    smooth_c(dst, stride, topleft, width, height); \
-}
-
-sz_grid(smooth_lfn)
-
-static NOINLINE void
-smooth_v_c(pixel *dst, const ptrdiff_t stride, const pixel *const topleft,
-           const int width, const int height)
+static void ipred_smooth_v_c(pixel *dst, const ptrdiff_t stride,
+                             const pixel *const topleft,
+                             const int width, const int height, const int a)
 {
-    const uint8_t *const weights_ver = &sm_weight_arrays[height];
+    const uint8_t *const weights_ver = &dav1d_sm_weights[height];
     const int bottom = topleft[-height];
 
     for (int y = 0; y < height; y++) {
@@ -310,21 +209,11 @@
     }
 }
 
-#define smooth_v_lfn(width, height) \
-static void smooth_v_##width##x##height##_c(pixel *dst, const ptrdiff_t stride, \
-                                            const pixel *const topleft, \
-                                            const int a) \
-{ \
-    smooth_v_c(dst, stride, topleft, width, height); \
-}
-
-sz_grid(smooth_v_lfn)
-
-static NOINLINE void
-smooth_h_c(pixel *dst, const ptrdiff_t stride, const pixel *const topleft,
-           const int width, const int height)
+static void ipred_smooth_h_c(pixel *dst, const ptrdiff_t stride,
+                             const pixel *const topleft,
+                             const int width, const int height, const int a)
 {
-    const uint8_t *const weights_hor = &sm_weight_arrays[width];
+    const uint8_t *const weights_hor = &dav1d_sm_weights[width];
     const int right = topleft[width];
 
     for (int y = 0; y < height; y++) {
@@ -337,50 +226,6 @@
     }
 }
 
-#define smooth_h_lfn(width, height) \
-static void smooth_h_##width##x##height##_c(pixel *dst, const ptrdiff_t stride, \
-                                            const pixel *const topleft, \
-                                            const int a) \
-{ \
-    smooth_h_c(dst, stride, topleft, width, height); \
-}
-
-sz_grid(smooth_h_lfn)
-
-static const int16_t dr_intra_derivative[90] = {
-  // More evenly spread out angles and limited to 10-bit
-  // Values that are 0 will never be used
-  //                    Approx angle
-  0,    0, 0,        //
-  1023, 0, 0,        // 3, ...
-  547,  0, 0,        // 6, ...
-  372,  0, 0, 0, 0,  // 9, ...
-  273,  0, 0,        // 14, ...
-  215,  0, 0,        // 17, ...
-  178,  0, 0,        // 20, ...
-  151,  0, 0,        // 23, ... (113 & 203 are base angles)
-  132,  0, 0,        // 26, ...
-  116,  0, 0,        // 29, ...
-  102,  0, 0, 0,     // 32, ...
-  90,   0, 0,        // 36, ...
-  80,   0, 0,        // 39, ...
-  71,   0, 0,        // 42, ...
-  64,   0, 0,        // 45, ... (45 & 135 are base angles)
-  57,   0, 0,        // 48, ...
-  51,   0, 0,        // 51, ...
-  45,   0, 0, 0,     // 54, ...
-  40,   0, 0,        // 58, ...
-  35,   0, 0,        // 61, ...
-  31,   0, 0,        // 64, ...
-  27,   0, 0,        // 67, ... (67 & 157 are base angles)
-  23,   0, 0,        // 70, ...
-  19,   0, 0,        // 73, ...
-  15,   0, 0, 0, 0,  // 76, ...
-  11,   0, 0,        // 81, ...
-  7,    0, 0,        // 84, ...
-  3,    0, 0,        // 87, ...
-};
-
 static int get_filter_strength(const unsigned blk_wh, const unsigned d,
                                const int type)
 {
@@ -421,11 +266,10 @@
     return strength;
 }
 
-static void filter_edge(pixel *const out, const int sz,
-                        const pixel *const in, const int from, const int to,
-                        const unsigned strength)
+static void filter_edge(pixel *const out, const int sz, const pixel *const in,
+                        const int from, const int to, const unsigned strength)
 {
-    const uint8_t kernel[3][5] = {
+    static const uint8_t kernel[3][5] = {
         { 0, 4, 8, 4, 0 },
         { 0, 5, 6, 5, 0 },
         { 2, 4, 4, 4, 2 }
@@ -448,7 +292,7 @@
 static void upsample_edge(pixel *const out, const int hsz,
                           const pixel *const in, const int from, const int to)
 {
-    const int8_t kernel[4] = { -1, 9, 9, -1 };
+    static const int8_t kernel[4] = { -1, 9, 9, -1 };
     int i;
     for (i = 0; i < hsz - 1; i++) {
         out[i * 2] = in[iclip(i, from, to - 1)];
@@ -461,14 +305,14 @@
     out[i * 2] = in[iclip(i, from, to - 1)];
 }
 
-static NOINLINE void
-z1_c(pixel *dst, const ptrdiff_t stride, const pixel *const topleft_in,
-     int angle, const int width, const int height)
+static void ipred_z1_c(pixel *dst, const ptrdiff_t stride,
+                       const pixel *const topleft_in,
+                       const int width, const int height, int angle)
 {
     const int is_sm = angle >> 9;
     angle &= 511;
     assert(angle < 90);
-    const int dx = dr_intra_derivative[angle];
+    const int dx = dav1d_dr_intra_derivative[angle];
     pixel top_out[(64 + 64) * 2];
     const pixel *top;
     int max_base_x;
@@ -513,25 +357,15 @@
     }
 }
 
-#define z1_lfn(width, height) \
-static void z1_##width##x##height##_c(pixel *dst, const ptrdiff_t stride, \
-                                      const pixel *const topleft, \
-                                      const int angle) \
-{ \
-    z1_c(dst, stride, topleft, angle, width, height); \
-}
-
-sz_grid(z1_lfn)
-
-static NOINLINE void
-z2_c(pixel *dst, const ptrdiff_t stride, const pixel *const topleft_in,
-     int angle, const int width, const int height)
+static void ipred_z2_c(pixel *dst, const ptrdiff_t stride,
+                       const pixel *const topleft_in,
+                       const int width, const int height, int angle)
 {
     const int is_sm = angle >> 9;
     angle &= 511;
     assert(angle > 90 && angle < 180);
-    const int dy = dr_intra_derivative[angle - 90];
-    const int dx = dr_intra_derivative[180 - angle];
+    const int dy = dav1d_dr_intra_derivative[angle - 90];
+    const int dx = dav1d_dr_intra_derivative[180 - angle];
     const int upsample_left = get_upsample(width + height, 180 - angle, is_sm);
     const int upsample_above = get_upsample(width + height, angle - 90, is_sm);
     pixel edge[64 * 2 + 64 * 2 + 1];
@@ -594,24 +428,14 @@
     }
 }
 
-#define z2_lfn(width, height) \
-static void z2_##width##x##height##_c(pixel *dst, const ptrdiff_t stride, \
-                                      const pixel *const topleft, \
-                                      const int angle) \
-{ \
-    z2_c(dst, stride, topleft, angle, width, height); \
-}
-
-sz_grid(z2_lfn)
-
-static NOINLINE void
-z3_c(pixel *dst, const ptrdiff_t stride, const pixel *const topleft_in,
-     int angle, const int width, const int height)
+static void ipred_z3_c(pixel *dst, const ptrdiff_t stride,
+                       const pixel *const topleft_in,
+                       const int width, const int height, int angle)
 {
     const int is_sm = angle >> 9;
     angle &= 511;
     assert(angle > 180);
-    const int dy = dr_intra_derivative[270 - angle];
+    const int dy = dav1d_dr_intra_derivative[270 - angle];
     pixel left_out[(64 + 64) * 2];
     const pixel *left;
     int max_base_y;
@@ -659,74 +483,15 @@
     }
 }
 
-#define z3_lfn(width, height) \
-static void z3_##width##x##height##_c(pixel *dst, const ptrdiff_t stride, \
-                                      const pixel *const topleft, \
-                                      const int angle) \
-{ \
-    z3_c(dst, stride, topleft, angle, width, height); \
-}
-
-sz_grid(z3_lfn)
-
-static const int8_t av1_filter_intra_taps[5][8][8] = {
-    {
-        { -6, 10,  0,  0,  0, 12,  0, 0 },
-        { -5,  2, 10,  0,  0,  9,  0, 0 },
-        { -3,  1,  1, 10,  0,  7,  0, 0 },
-        { -3,  1,  1,  2, 10,  5,  0, 0 },
-        { -4,  6,  0,  0,  0,  2, 12, 0 },
-        { -3,  2,  6,  0,  0,  2,  9, 0 },
-        { -3,  2,  2,  6,  0,  2,  7, 0 },
-        { -3,  1,  2,  2,  6,  3,  5, 0 },
-    }, {
-        { -10, 16,  0,  0,  0, 10,  0, 0 },
-        {  -6,  0, 16,  0,  0,  6,  0, 0 },
-        {  -4,  0,  0, 16,  0,  4,  0, 0 },
-        {  -2,  0,  0,  0, 16,  2,  0, 0 },
-        { -10, 16,  0,  0,  0,  0, 10, 0 },
-        {  -6,  0, 16,  0,  0,  0,  6, 0 },
-        {  -4,  0,  0, 16,  0,  0,  4, 0 },
-        {  -2,  0,  0,  0, 16,  0,  2, 0 },
-    }, {
-        { -8, 8, 0, 0, 0, 16,  0, 0 },
-        { -8, 0, 8, 0, 0, 16,  0, 0 },
-        { -8, 0, 0, 8, 0, 16,  0, 0 },
-        { -8, 0, 0, 0, 8, 16,  0, 0 },
-        { -4, 4, 0, 0, 0,  0, 16, 0 },
-        { -4, 0, 4, 0, 0,  0, 16, 0 },
-        { -4, 0, 0, 4, 0,  0, 16, 0 },
-        { -4, 0, 0, 0, 4,  0, 16, 0 },
-    }, {
-        { -2, 8, 0, 0, 0, 10,  0, 0 },
-        { -1, 3, 8, 0, 0,  6,  0, 0 },
-        { -1, 2, 3, 8, 0,  4,  0, 0 },
-        {  0, 1, 2, 3, 8,  2,  0, 0 },
-        { -1, 4, 0, 0, 0,  3, 10, 0 },
-        { -1, 3, 4, 0, 0,  4,  6, 0 },
-        { -1, 2, 3, 4, 0,  4,  4, 0 },
-        { -1, 2, 2, 3, 4,  3,  3, 0 },
-    }, {
-        { -12, 14,  0,  0,  0, 14,  0, 0 },
-        { -10,  0, 14,  0,  0, 12,  0, 0 },
-        {  -9,  0,  0, 14,  0, 11,  0, 0 },
-        {  -8,  0,  0,  0, 14, 10,  0, 0 },
-        { -10, 12,  0,  0,  0,  0, 14, 0 },
-        {  -9,  1, 12,  0,  0,  0, 12, 0 },
-        {  -8,  0,  0, 12,  0,  1, 11, 0 },
-        {  -7,  0,  0,  1, 12,  1,  9, 0 },
-    },
-};
-
-static NOINLINE void
-filter_intra_c(pixel *dst, const ptrdiff_t stride,
-               const pixel *const topleft_in,
-               int filt_idx, const int width, const int height)
+/* Up to 32x32 only */
+static void ipred_filter_c(pixel *dst, const ptrdiff_t stride,
+                           const pixel *const topleft_in,
+                           const int width, const int height, int filt_idx)
 {
     filt_idx &= 511;
     assert(filt_idx < 5);
 
-    const int8_t (*const filter)[8] = av1_filter_intra_taps[filt_idx];
+    const int8_t (*const filter)[8] = dav1d_filter_intra_taps[filt_idx];
     int x, y;
     ptrdiff_t left_stride;
     const pixel *left, *topleft, *top;
@@ -764,30 +529,6 @@
     }
 }
 
-#define filter_lfn(width, height) \
-static void filter_##width##x##height##_c(pixel *const dst, \
-                                          const ptrdiff_t stride, \
-                                          const pixel *const topleft, \
-                                          const int filt_idx) \
-{ \
-    filter_intra_c(dst, stride, topleft, filt_idx, width, height); \
-}
-
-filter_lfn( 4,  4)
-filter_lfn( 8,  4)
-filter_lfn(16,  4)
-filter_lfn( 4,  8)
-filter_lfn( 8,  8)
-filter_lfn(16,  8)
-filter_lfn(32,  8)
-filter_lfn( 4, 16)
-filter_lfn( 8, 16)
-filter_lfn(16, 16)
-filter_lfn(32, 16)
-filter_lfn( 8, 32)
-filter_lfn(16, 32)
-filter_lfn(32, 32)
-
 static NOINLINE void
 cfl_ac_c(int16_t *ac, const pixel *ypx, const ptrdiff_t stride,
          const int w_pad, const int h_pad, const int width, const int height,
@@ -956,57 +697,20 @@
 }
 
 void bitfn(dav1d_intra_pred_dsp_init)(Dav1dIntraPredDSPContext *const c) {
-#define assign_lfn(w, h, p1, p2, pfx) \
-    c->intra_pred[pfx##TX_##w##X##h][p1##_PRED] = p2##_##w##x##h##_c
-#define assign_fns(p1, p2) \
-    assign_lfn( 4,  4, p1, p2,); \
-    assign_lfn( 4,  8, p1, p2, R); \
-    assign_lfn( 4, 16, p1, p2, R); \
-    assign_lfn( 8,  4, p1, p2, R); \
-    assign_lfn( 8,  8, p1, p2,); \
-    assign_lfn( 8, 16, p1, p2, R); \
-    assign_lfn( 8, 32, p1, p2, R); \
-    assign_lfn(16,  4, p1, p2, R); \
-    assign_lfn(16,  8, p1, p2, R); \
-    assign_lfn(16, 16, p1, p2,); \
-    assign_lfn(16, 32, p1, p2, R); \
-    assign_lfn(16, 64, p1, p2, R); \
-    assign_lfn(32,  8, p1, p2, R); \
-    assign_lfn(32, 16, p1, p2, R); \
-    assign_lfn(32, 32, p1, p2,); \
-    assign_lfn(32, 64, p1, p2, R); \
-    assign_lfn(64, 16, p1, p2, R); \
-    assign_lfn(64, 32, p1, p2, R); \
-    assign_lfn(64, 64, p1, p2,); \
-
-    assign_fns(DC, dc);
-    assign_fns(DC_128, dc128);
-    assign_fns(TOP_DC,  dctop);
-    assign_fns(LEFT_DC, dcleft);
-    assign_fns(HOR, h);
-    assign_fns(VERT, v);
-    assign_fns(PAETH, paeth);
-    assign_fns(SMOOTH, smooth);
-    assign_fns(SMOOTH_V, smooth_v);
-    assign_fns(SMOOTH_H, smooth_h);
-    assign_fns(Z1, z1);
-    assign_fns(Z2, z2);
-    assign_fns(Z3, z3);
-
-    assign_lfn( 4,  4, FILTER, filter,);
-    assign_lfn( 8,  4, FILTER, filter, R);
-    assign_lfn(16,  4, FILTER, filter, R);
-    assign_lfn( 4,  8, FILTER, filter, R);
-    assign_lfn( 8,  8, FILTER, filter,);
-    assign_lfn(16,  8, FILTER, filter, R);
-    assign_lfn(32,  8, FILTER, filter, R);
-    assign_lfn( 4, 16, FILTER, filter, R);
-    assign_lfn( 8, 16, FILTER, filter, R);
-    assign_lfn(16, 16, FILTER, filter,);
-    assign_lfn(32, 16, FILTER, filter, R);
-    assign_lfn( 8, 32, FILTER, filter, R);
-    assign_lfn(16, 32, FILTER, filter, R);
-    assign_lfn(32, 32, FILTER, filter,);
+    c->intra_pred[DC_PRED      ] = ipred_dc_c;
+    c->intra_pred[DC_128_PRED  ] = ipred_dc_128_c;
+    c->intra_pred[TOP_DC_PRED  ] = ipred_dc_top_c;
+    c->intra_pred[LEFT_DC_PRED ] = ipred_dc_left_c;
+    c->intra_pred[HOR_PRED     ] = ipred_h_c;
+    c->intra_pred[VERT_PRED    ] = ipred_v_c;
+    c->intra_pred[PAETH_PRED   ] = ipred_paeth_c;
+    c->intra_pred[SMOOTH_PRED  ] = ipred_smooth_c;
+    c->intra_pred[SMOOTH_V_PRED] = ipred_smooth_v_c;
+    c->intra_pred[SMOOTH_H_PRED] = ipred_smooth_h_c;
+    c->intra_pred[Z1_PRED      ] = ipred_z1_c;
+    c->intra_pred[Z2_PRED      ] = ipred_z2_c;
+    c->intra_pred[Z3_PRED      ] = ipred_z3_c;
+    c->intra_pred[FILTER_PRED  ] = ipred_filter_c;
 
     // cfl functions are split per chroma subsampling type
     c->cfl_ac[DAV1D_PIXEL_LAYOUT_I420 - 1][ TX_4X4  ] = cfl_ac_8x8_to_4x4_c;
--- a/src/ipred.h
+++ b/src/ipred.h
@@ -40,7 +40,8 @@
  *   see ipred_prepare.h for more detailed documentation.
  */
 #define decl_angular_ipred_fn(name) \
-void (name)(pixel *dst, ptrdiff_t stride, const pixel *topleft, int angle)
+void (name)(pixel *dst, ptrdiff_t stride, const pixel *topleft, \
+            int width, int height, int angle)
 typedef decl_angular_ipred_fn(*angular_ipred_fn);
 
 /*
@@ -84,7 +85,7 @@
 typedef decl_pal_pred_fn(*pal_pred_fn);
 
 typedef struct Dav1dIntraPredDSPContext {
-    angular_ipred_fn intra_pred[N_RECT_TX_SIZES][N_IMPL_INTRA_PRED_MODES];
+    angular_ipred_fn intra_pred[N_IMPL_INTRA_PRED_MODES];
 
     // chroma-from-luma
     cfl_ac_fn cfl_ac[3 /* 420, 422, 444 */][N_RECT_TX_SIZES /* chroma tx size */];
--- a/src/recon.c
+++ b/src/recon.c
@@ -767,8 +767,9 @@
                                                           f->cur.p.stride[0], top_sb_edge,
                                                           b->y_mode, &angle,
                                                           t_dim->w, t_dim->h, edge);
-                    dsp->ipred.intra_pred[b->tx][m](dst, f->cur.p.stride[0],
-                                                    edge, angle | sm_fl);
+                    dsp->ipred.intra_pred[m](dst, f->cur.p.stride[0], edge,
+                                             t_dim->w * 4, t_dim->h * 4,
+                                             angle | sm_fl);
 
                     if (DEBUG_BLOCK_INFO && DEBUG_B_PIXELS) {
                         hex_dump(edge - t_dim->h * 4, t_dim->h * 4,
@@ -869,7 +870,9 @@
                                                           top_sb_edge, DC_PRED, &angle,
                                                           cfl_uv_t_dim->w,
                                                           cfl_uv_t_dim->h, edge);
-                    dsp->ipred.intra_pred[cfl_uvtx][m](uv_dst[pl], stride, edge, 0);
+                    dsp->ipred.intra_pred[m](uv_dst[pl], stride, edge,
+                                             cfl_uv_t_dim->w * 4,
+                                             cfl_uv_t_dim->h * 4, 0);
                 }
                 const int furthest_r =
                     ((cw4 << ss_hor) + t_dim->w - 1) & ~(t_dim->w - 1);
@@ -981,8 +984,10 @@
                                                               top_sb_edge, b->uv_mode,
                                                               &angle, uv_t_dim->w,
                                                               uv_t_dim->h, edge);
-                        dsp->ipred.intra_pred[b->uvtx][m](dst, stride,
-                                                          edge, angle | sm_uv_fl);
+                        dsp->ipred.intra_pred[m](dst, stride, edge,
+                                                 uv_t_dim->w * 4,
+                                                 uv_t_dim->h * 4,
+                                                 angle | sm_uv_fl);
                         if (DEBUG_BLOCK_INFO && DEBUG_B_PIXELS) {
                             hex_dump(edge - uv_t_dim->h * 4, uv_t_dim->h * 4,
                                      uv_t_dim->h * 4, 2, "l");
@@ -1100,7 +1105,6 @@
                 obmc(t, dst, f->cur.p.stride[0], b_dim, 0, bx4, by4, w4, h4);
         }
         if (b->interintra_type) {
-            const enum RectTxfmSize ii_tx = dav1d_max_txfm_size_for_bs[bs][0];
             pixel tl_edge_px[65], *const tl_edge = &tl_edge_px[32];
             enum IntraPredMode m = b->interintra_mode == II_SMOOTH_PRED ?
                                    SMOOTH_PRED : b->interintra_mode;
@@ -1117,7 +1121,8 @@
                                                   ts->tiling.col_end, ts->tiling.row_end,
                                                   0, dst, f->cur.p.stride[0], top_sb_edge,
                                                   m, &angle, bw4, bh4, tl_edge);
-            dsp->ipred.intra_pred[ii_tx][m](tmp, 4 * bw4 * sizeof(pixel), tl_edge, 0);
+            dsp->ipred.intra_pred[m](tmp, 4 * bw4 * sizeof(pixel),
+                                     tl_edge, bw4 * 4, bh4 * 4, 0);
             const uint8_t *const ii_mask =
                 b->interintra_type == INTER_INTRA_BLEND ?
                      dav1d_ii_masks[bs][0][b->interintra_mode] :
@@ -1210,8 +1215,6 @@
                 // FIXME for 8x32 with 4:2:2 subsampling, this probably does
                 // the wrong thing since it will select 4x16, not 4x32, as a
                 // transform size...
-                const enum RectTxfmSize ii_tx =
-                    dav1d_max_txfm_size_for_bs[bs][f->cur.p.p.layout];
                 const uint8_t *const ii_mask =
                     b->interintra_type == INTER_INTRA_BLEND ?
                          dav1d_ii_masks[bs][chr_layout_idx][b->interintra_mode] :
@@ -1242,7 +1245,8 @@
                                                           0, uvdst, f->cur.p.stride[1],
                                                           top_sb_edge, m,
                                                           &angle, cbw4, cbh4, tl_edge);
-                    dsp->ipred.intra_pred[ii_tx][m](tmp, cbw4 * 4 * sizeof(pixel), tl_edge, 0);
+                    dsp->ipred.intra_pred[m](tmp, cbw4 * 4 * sizeof(pixel),
+                                             tl_edge, cbw4 * 4, cbh4 * 4, 0);
                     dsp->mc.blend(uvdst, f->cur.p.stride[1], tmp, cbw4 * 4 * sizeof(pixel),
                                   cbw4 * 4, cbh4 * 4, ii_mask, cbw4 * 4);
                 }
--- a/src/tables.c
+++ b/src/tables.c
@@ -719,3 +719,113 @@
     // dummy (replicate row index 191)
     { 0, 0, 0,   0,   2, 127, - 1, 0 },
 };
+
+const uint8_t dav1d_sm_weights[128] = {
+    // Unused, because we always offset by bs, which is at least 2.
+      0,   0,
+    // bs = 2
+    255, 128,
+    // bs = 4
+    255, 149,  85,  64,
+    // bs = 8
+    255, 197, 146, 105,  73,  50,  37,  32,
+    // bs = 16
+    255, 225, 196, 170, 145, 123, 102,  84,
+     68,  54,  43,  33,  26,  20,  17,  16,
+    // bs = 32
+    255, 240, 225, 210, 196, 182, 169, 157,
+    145, 133, 122, 111, 101,  92,  83,  74,
+     66,  59,  52,  45,  39,  34,  29,  25,
+     21,  17,  14,  12,  10,   9,   8,   8,
+    // bs = 64
+    255, 248, 240, 233, 225, 218, 210, 203,
+    196, 189, 182, 176, 169, 163, 156, 150,
+    144, 138, 133, 127, 121, 116, 111, 106,
+    101,  96,  91,  86,  82,  77,  73,  69,
+     65,  61,  57,  54,  50,  47,  44,  41,
+     38,  35,  32,  29,  27,  25,  22,  20,
+     18,  16,  15,  13,  12,  10,   9,   8,
+      7,   6,   6,   5,   5,   4,   4,   4
+};
+
+const int16_t dav1d_dr_intra_derivative[90] = {
+    // More evenly spread out angles and limited to 10-bit
+    // Values that are 0 will never be used
+       0, 0, 0,       // Approx angle
+    1023, 0, 0,       // 3, ...
+     547, 0, 0,       // 6, ...
+     372, 0, 0, 0, 0, // 9, ...
+     273, 0, 0,       // 14, ...
+     215, 0, 0,       // 17, ...
+     178, 0, 0,       // 20, ...
+     151, 0, 0,       // 23, ... (113 & 203 are base angles)
+     132, 0, 0,       // 26, ...
+     116, 0, 0,       // 29, ...
+     102, 0, 0, 0,    // 32, ...
+      90, 0, 0,       // 36, ...
+      80, 0, 0,       // 39, ...
+      71, 0, 0,       // 42, ...
+      64, 0, 0,       // 45, ... (45 & 135 are base angles)
+      57, 0, 0,       // 48, ...
+      51, 0, 0,       // 51, ...
+      45, 0, 0, 0,    // 54, ...
+      40, 0, 0,       // 58, ...
+      35, 0, 0,       // 61, ...
+      31, 0, 0,       // 64, ...
+      27, 0, 0,       // 67, ... (67 & 157 are base angles)
+      23, 0, 0,       // 70, ...
+      19, 0, 0,       // 73, ...
+      15, 0, 0, 0, 0, // 76, ...
+      11, 0, 0,       // 81, ...
+       7, 0, 0,       // 84, ...
+       3, 0, 0,       // 87, ...
+};
+
+const int8_t dav1d_filter_intra_taps[5][8][8] = {
+    {
+        {  -6, 10,  0,  0,  0, 12,  0,  0 },
+        {  -5,  2, 10,  0,  0,  9,  0,  0 },
+        {  -3,  1,  1, 10,  0,  7,  0,  0 },
+        {  -3,  1,  1,  2, 10,  5,  0,  0 },
+        {  -4,  6,  0,  0,  0,  2, 12,  0 },
+        {  -3,  2,  6,  0,  0,  2,  9,  0 },
+        {  -3,  2,  2,  6,  0,  2,  7,  0 },
+        {  -3,  1,  2,  2,  6,  3,  5,  0 },
+    }, {
+        { -10, 16,  0,  0,  0, 10,  0,  0 },
+        {  -6,  0, 16,  0,  0,  6,  0,  0 },
+        {  -4,  0,  0, 16,  0,  4,  0,  0 },
+        {  -2,  0,  0,  0, 16,  2,  0,  0 },
+        { -10, 16,  0,  0,  0,  0, 10,  0 },
+        {  -6,  0, 16,  0,  0,  0,  6,  0 },
+        {  -4,  0,  0, 16,  0,  0,  4,  0 },
+        {  -2,  0,  0,  0, 16,  0,  2,  0 },
+    }, {
+        {  -8,  8,  0,  0,  0, 16,  0,  0 },
+        {  -8,  0,  8,  0,  0, 16,  0,  0 },
+        {  -8,  0,  0,  8,  0, 16,  0,  0 },
+        {  -8,  0,  0,  0,  8, 16,  0,  0 },
+        {  -4,  4,  0,  0,  0,  0, 16,  0 },
+        {  -4,  0,  4,  0,  0,  0, 16,  0 },
+        {  -4,  0,  0,  4,  0,  0, 16,  0 },
+        {  -4,  0,  0,  0,  4,  0, 16,  0 },
+    }, {
+        {  -2,  8,  0,  0,  0, 10,  0,  0 },
+        {  -1,  3,  8,  0,  0,  6,  0,  0 },
+        {  -1,  2,  3,  8,  0,  4,  0,  0 },
+        {   0,  1,  2,  3,  8,  2,  0,  0 },
+        {  -1,  4,  0,  0,  0,  3, 10,  0 },
+        {  -1,  3,  4,  0,  0,  4,  6,  0 },
+        {  -1,  2,  3,  4,  0,  4,  4,  0 },
+        {  -1,  2,  2,  3,  4,  3,  3,  0 },
+    }, {
+        { -12, 14,  0,  0,  0, 14,  0,  0 },
+        { -10,  0, 14,  0,  0, 12,  0,  0 },
+        {  -9,  0,  0, 14,  0, 11,  0,  0 },
+        {  -8,  0,  0,  0, 14, 10,  0,  0 },
+        { -10, 12,  0,  0,  0,  0, 14,  0 },
+        {  -9,  1, 12,  0,  0,  0, 12,  0 },
+        {  -8,  0,  0, 12,  0,  1, 11,  0 },
+        {  -7,  0,  0,  1, 12,  1,  9,  0 },
+    }
+};
--- a/src/tables.h
+++ b/src/tables.h
@@ -113,4 +113,8 @@
 extern const int8_t dav1d_mc_subpel_filters[5][15][8];
 extern const int8_t dav1d_mc_warp_filter[][8];
 
+extern const uint8_t dav1d_sm_weights[128];
+extern const int16_t dav1d_dr_intra_derivative[90];
+extern const int8_t dav1d_filter_intra_taps[5][8][8];
+
 #endif /* __DAV1D_SRC_TABLES_H__ */