Skip to content

Commit

Permalink
Use offsets instead of pointers for intra_edge child nodes
Browse files Browse the repository at this point in the history
Reduces the table size by around 2.5 kB on 64-bit systems.
  • Loading branch information
gramner-twoorioles authored and Frank Bossen committed Mar 20, 2024
1 parent 77f7d21 commit 07b9ebb
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 36 deletions.
21 changes: 9 additions & 12 deletions src/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2329,7 +2329,7 @@ static int decode_sb(Dav1dTaskContext *const t, const enum BlockLevel bl,

if (!have_h_split && !have_v_split) {
assert(bl < BL_8X8);
return decode_sb(t, bl + 1, ((const EdgeBranch *) node)->split[0]);
return decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 0));
}

uint16_t *pc;
Expand Down Expand Up @@ -2417,18 +2417,17 @@ static int decode_sb(Dav1dTaskContext *const t, const enum BlockLevel bl,
}
#endif
} else {
const EdgeBranch *const branch = (const EdgeBranch *) node;
if (decode_sb(t, bl + 1, branch->split[0]))
if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 0)))
return 1;
t->bx += hsz;
if (decode_sb(t, bl + 1, branch->split[1]))
if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 1)))
return 1;
t->bx -= hsz;
t->by += hsz;
if (decode_sb(t, bl + 1, branch->split[2]))
if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 2)))
return 1;
t->bx += hsz;
if (decode_sb(t, bl + 1, branch->split[3]))
if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 3)))
return 1;
t->bx -= hsz;
t->by -= hsz;
Expand Down Expand Up @@ -2538,11 +2537,10 @@ static int decode_sb(Dav1dTaskContext *const t, const enum BlockLevel bl,

assert(bl < BL_8X8);
if (is_split) {
const EdgeBranch *const branch = (const EdgeBranch *) node;
bp = PARTITION_SPLIT;
if (decode_sb(t, bl + 1, branch->split[0])) return 1;
if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 0))) return 1;
t->bx += hsz;
if (decode_sb(t, bl + 1, branch->split[1])) return 1;
if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 1))) return 1;
t->bx -= hsz;
} else {
bp = PARTITION_H;
Expand All @@ -2569,11 +2567,10 @@ static int decode_sb(Dav1dTaskContext *const t, const enum BlockLevel bl,

assert(bl < BL_8X8);
if (is_split) {
const EdgeBranch *const branch = (const EdgeBranch *) node;
bp = PARTITION_SPLIT;
if (decode_sb(t, bl + 1, branch->split[0])) return 1;
if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 0))) return 1;
t->by += hsz;
if (decode_sb(t, bl + 1, branch->split[2])) return 1;
if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 2))) return 1;
t->by -= hsz;
} else {
bp = PARTITION_V;
Expand Down
52 changes: 29 additions & 23 deletions src/intra_edge.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,17 @@ struct ModeSelMem {
EdgeTip *nt;
};

static EdgeBranch branch_sb128[1 + 4 + 16 + 64];
static EdgeBranch branch_sb64[1 + 4 + 16];
static EdgeTip tip_sb128[256];
static EdgeTip tip_sb64[64];
/* Because we're using 16-bit offsets to refer to other nodes those arrays
* are placed in a struct to ensure they're consecutive in memory. */
static struct {
EdgeBranch branch_sb128[1 + 4 + 16 + 64];
EdgeTip tip_sb128[256];
EdgeBranch branch_sb64[1 + 4 + 16];
EdgeTip tip_sb64[64];
} ALIGN(nodes, 16);

const EdgeNode *dav1d_intra_edge_tree[2] = {
(EdgeNode*)branch_sb128, (EdgeNode*)branch_sb64
(EdgeNode*)nodes.branch_sb128, (EdgeNode*)nodes.branch_sb64
};

static COLD void init_edges(EdgeNode *const node,
Expand Down Expand Up @@ -87,6 +91,8 @@ static COLD void init_edges(EdgeNode *const node,
}
}

#define PTR_OFFSET(a, b) ((uint16_t)((uintptr_t)(b) - (uintptr_t)(a)))

static COLD void init_mode_node(EdgeBranch *const nwc,
const enum BlockLevel bl,
struct ModeSelMem *const mem,
Expand All @@ -99,7 +105,7 @@ static COLD void init_mode_node(EdgeBranch *const nwc,
if (bl == BL_16X16) {
for (int n = 0; n < 4; n++) {
EdgeTip *const nt = mem->nt++;
nwc->split[n] = &nt->node;
nwc->split_offset[n] = PTR_OFFSET(nwc, nt);
init_edges(&nt->node, bl + 1,
((n == 3 || (n == 1 && !top_has_right)) ? 0 :
EDGE_ALL_TOP_HAS_RIGHT) |
Expand All @@ -109,7 +115,7 @@ static COLD void init_mode_node(EdgeBranch *const nwc,
} else {
for (int n = 0; n < 4; n++) {
EdgeBranch *const nwc_child = mem->nwc[bl]++;
nwc->split[n] = &nwc_child->node;
nwc->split_offset[n] = PTR_OFFSET(nwc, nwc_child);
init_mode_node(nwc_child, bl + 1, mem,
!(n == 3 || (n == 1 && !top_has_right)),
n == 0 || (n == 2 && left_has_bottom));
Expand All @@ -121,22 +127,22 @@ COLD void dav1d_init_intra_edge_tree(void) {
// This function is guaranteed to be called only once
struct ModeSelMem mem;

mem.nwc[BL_128X128] = &branch_sb128[1];
mem.nwc[BL_64X64] = &branch_sb128[1 + 4];
mem.nwc[BL_32X32] = &branch_sb128[1 + 4 + 16];
mem.nt = tip_sb128;
init_mode_node(branch_sb128, BL_128X128, &mem, 1, 0);
assert(mem.nwc[BL_128X128] == &branch_sb128[1 + 4]);
assert(mem.nwc[BL_64X64] == &branch_sb128[1 + 4 + 16]);
assert(mem.nwc[BL_32X32] == &branch_sb128[1 + 4 + 16 + 64]);
assert(mem.nt == &tip_sb128[256]);
mem.nwc[BL_128X128] = &nodes.branch_sb128[1];
mem.nwc[BL_64X64] = &nodes.branch_sb128[1 + 4];
mem.nwc[BL_32X32] = &nodes.branch_sb128[1 + 4 + 16];
mem.nt = nodes.tip_sb128;
init_mode_node(nodes.branch_sb128, BL_128X128, &mem, 1, 0);
assert(mem.nwc[BL_128X128] == &nodes.branch_sb128[1 + 4]);
assert(mem.nwc[BL_64X64] == &nodes.branch_sb128[1 + 4 + 16]);
assert(mem.nwc[BL_32X32] == &nodes.branch_sb128[1 + 4 + 16 + 64]);
assert(mem.nt == &nodes.tip_sb128[256]);

mem.nwc[BL_128X128] = NULL;
mem.nwc[BL_64X64] = &branch_sb64[1];
mem.nwc[BL_32X32] = &branch_sb64[1 + 4];
mem.nt = tip_sb64;
init_mode_node(branch_sb64, BL_64X64, &mem, 1, 0);
assert(mem.nwc[BL_64X64] == &branch_sb64[1 + 4]);
assert(mem.nwc[BL_32X32] == &branch_sb64[1 + 4 + 16]);
assert(mem.nt == &tip_sb64[64]);
mem.nwc[BL_64X64] = &nodes.branch_sb64[1];
mem.nwc[BL_32X32] = &nodes.branch_sb64[1 + 4];
mem.nt = nodes.tip_sb64;
init_mode_node(nodes.branch_sb64, BL_64X64, &mem, 1, 0);
assert(mem.nwc[BL_64X64] == &nodes.branch_sb64[1 + 4]);
assert(mem.nwc[BL_32X32] == &nodes.branch_sb64[1 + 4 + 16]);
assert(mem.nt == &nodes.tip_sb64[64]);
}
5 changes: 4 additions & 1 deletion src/intra_edge.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ enum EdgeFlags {
EDGE_ALL_LEFT_HAS_BOTTOM,
};

#define INTRA_EDGE_SPLIT(n, i) \
((const EdgeNode*)((uintptr_t)(n) + ((const EdgeBranch*)(n))->split_offset[i]))

typedef struct EdgeNode {
uint8_t /* enum EdgeFlags */ o, h[2], v[2];
} EdgeNode;
Expand All @@ -59,7 +62,7 @@ typedef struct EdgeTip {
typedef struct EdgeBranch {
EdgeNode node;
uint8_t /* enum EdgeFlags */ h4, v4;
const EdgeNode *split[4];
uint16_t split_offset[4]; /* relative to the address of this node */
} EdgeBranch;

/* Tree to keep track of which edges are available. */
Expand Down

0 comments on commit 07b9ebb

Please sign in to comment.