skip to content
==> include/pathtrace/t_tile.h <==
1/* Template (included once per instantiation after t_math, t_intersect, t_sample and t_tonemap; see
2 * pathtrace/real.h): a tile's columns (one column a lane of a warp, or 32 columns in a loop on one
3 * CPU or wasm thread) and whole tiles. A column is PT_TILE_H pixels, top to bottom; a tile's pixels
4 * are PT_TILE_PIX, row-major. Digests are FNV-1a 64 (@ajax/pathtrace-digest). */
5#include "pathtrace/digest.h"
6#include "pathtrace/real.h"
7#include "pathtrace/scene.h"
8
9/* FNV-1a 64 over a column's r g b words, rows top to bottom. */
10PT_API uint64_t PT_FN(col_digest)(const pt_v c[PT_TILE_H]) {
11    uint64_t h = PT_FNV_OFFSET;
12    for (uint32_t r = 0; r < PT_TILE_H; r++) h = pt_fnv(pt_fnv(pt_fnv(h, pt_to_bits(c[r].x)), pt_to_bits(c[r].y)), pt_to_bits(c[r].z));
13    return h;
14}
15
16/* Pass p of column cx of tile t: each pixel's pass sum (a work item's payload) into part; its digest. */
17PT_API uint64_t PT_FN(column_pass)(const uint32_t *sc, const pt_layout *l, uint32_t t, uint32_t cx, uint32_t p,
18                                   pt_v part[PT_TILE_H]) {
19    uint32_t x0, y0;
20    pt_tile_origin(sc, t, &x0, &y0);
21    for (uint32_t row = 0; row < PT_TILE_H; row++) part[row] = PT_FN(pixel_pass)(sc, l, x0 + cx, y0 + row, p);
22    return PT_FN(col_digest)(part);
23}
24
25/* Tone maps a column of accumulators (n = passes x S samples) into rgb; (acc digest, rgb digest). */
26PT_API void PT_FN(retone)(const uint32_t *sc, uint32_t passes, uint32_t op, const pt_v acc[PT_TILE_H],
27                          uint32_t rgb[PT_TILE_H], uint64_t *acc_digest, uint64_t *rgb_digest) {
28    uint32_t n = passes * sc[PT_H_SPP];
29    float exposure = PT_FN(ldr)(sc, PT_H_EXPOSURE);
30    uint64_t hr = PT_FNV_OFFSET;
31    for (uint32_t row = 0; row < PT_TILE_H; row++) {
32        rgb[row] = PT_FN(tonemap)(acc[row], n, exposure, op);
33        hr = pt_fnv(hr, rgb[row]);
34    }
35    *acc_digest = PT_FN(col_digest)(acc);
36    *rgb_digest = hr;
37}
38
39/* One pass folded into a column's accumulators (acc + part; the caller keeps pass order), then the
40 * tone map with n = passes S samples: (acc digest, rgb digest). */
41PT_API void PT_FN(fold_column)(const uint32_t *sc, uint32_t passes, uint32_t op, pt_v acc[PT_TILE_H],
42                               const pt_v part[PT_TILE_H], uint32_t rgb[PT_TILE_H], uint64_t *acc_digest,
43                               uint64_t *rgb_digest) {
44    for (uint32_t row = 0; row < PT_TILE_H; row++) acc[row] = PT_FN(vadd)(acc[row], part[row]);
45    PT_FN(retone)(sc, passes, op, acc, rgb, acc_digest, rgb_digest);
46}
47
48static inline void PT_FN(col_of)(const pt_v *px, uint32_t cx, pt_v c[PT_TILE_H]) {
49    for (uint32_t row = 0; row < PT_TILE_H; row++) c[row] = px[row * PT_TILE_W + cx];
50}
51static inline void PT_FN(put_col)(pt_v *px, uint32_t cx, const pt_v c[PT_TILE_H]) {
52    for (uint32_t row = 0; row < PT_TILE_H; row++) px[row * PT_TILE_W + cx] = c[row];
53}
54
55/* Pass p of tile t into part (PT_TILE_PIX pixels): the tile's pass-sum digest. */
56PT_API uint64_t PT_FN(tile_pass)(const uint32_t *sc, uint32_t t, uint32_t p, pt_v *part) {
57    pt_layout l = pt_layout_of(sc);
58    uint64_t d[32];
59    for (uint32_t cx = 0; cx < PT_TILE_W; cx++) {
60        pt_v c[PT_TILE_H];
61        d[cx] = PT_FN(column_pass)(sc, &l, t, cx, p, c);
62        PT_FN(put_col)(part, cx, c);
63    }
64    return pt_fold(d);
65}
66
67/* acc += part over the tile, tone mapped with n = passes S into rgb: the tile digests (acc, rgb). */
68PT_API void PT_FN(tile_fold)(const uint32_t *sc, uint32_t passes, uint32_t op, pt_v *acc, const pt_v *part,
69                             uint32_t *rgb, uint64_t *acc_digest, uint64_t *rgb_digest) {
70    uint64_t ca[32], cr[32];
71    for (uint32_t cx = 0; cx < PT_TILE_W; cx++) {
72        pt_v a[PT_TILE_H], pc[PT_TILE_H];
73        uint32_t r[PT_TILE_H];
74        PT_FN(col_of)(acc, cx, a);
75        PT_FN(col_of)(part, cx, pc);
76        PT_FN(fold_column)(sc, passes, op, a, pc, r, &ca[cx], &cr[cx]);
77        PT_FN(put_col)(acc, cx, a);
78        for (uint32_t row = 0; row < PT_TILE_H; row++) rgb[row * PT_TILE_W + cx] = r[row];
79    }
80    *acc_digest = pt_fold(ca);
81    *rgb_digest = pt_fold(cr);
82}
83
84/* Re-tones a tile's accumulators into rgb: its rgb digest. */
85PT_API uint64_t PT_FN(tile_retone)(const uint32_t *sc, uint32_t passes, uint32_t op, const pt_v *acc, uint32_t *rgb) {
86    uint64_t cr[32];
87    for (uint32_t cx = 0; cx < PT_TILE_W; cx++) {
88        pt_v a[PT_TILE_H];
89        uint32_t r[PT_TILE_H];
90        uint64_t ignored;
91        PT_FN(col_of)(acc, cx, a);
92        PT_FN(retone)(sc, passes, op, a, r, &ignored, &cr[cx]);
93        for (uint32_t row = 0; row < PT_TILE_H; row++) rgb[row * PT_TILE_W + cx] = r[row];
94    }
95    return pt_fold(cr);
96}