mirror of
https://github.com/Kravickas/PS4-apps.git
synced 2026-10-17 16:01:46 +02:00
341 lines
25 KiB
Python
341 lines
25 KiB
Python
#!/usr/bin/env python3
|
|
"""Generates shaders/ps_clock.s: clock mode's UI pass: the edge-lit frosted glass slab and
|
|
its glass text, per pixel; ends like ps_ui (clamp, sRGB, dither)."""
|
|
import struct, os
|
|
hx = lambda x: "0x%08x" % struct.unpack('<I', struct.pack('<f', x))[0]
|
|
L2E = 1.4426950408889634
|
|
IOR = (1.514, 1.517, 1.522); ABS = (0.0010, 0.0005, 0.0008)
|
|
out = []
|
|
def e(*ls): out.extend(ls)
|
|
class RA:
|
|
def __init__(s, lo, hi): s.free = list(range(lo, hi)); s.used = set(); s.maxv = 0
|
|
def get(s, n=1):
|
|
for i in range(len(s.free) - n + 1):
|
|
blk = s.free[i:i + n]
|
|
if blk == list(range(blk[0], blk[0] + n)) and (n == 1 or blk[0] % 1 == 0):
|
|
for r in blk: s.free.remove(r)
|
|
s.maxv = max(s.maxv, blk[-1]); return blk[0] if n == 1 else blk
|
|
raise RuntimeError("out of VGPRs")
|
|
def put(s, *rs):
|
|
for r in rs:
|
|
if isinstance(r, list): s.put(*r)
|
|
else: s.free.append(r); s.free.sort()
|
|
R = RA(22, 128)
|
|
S = lambda k: "s%d" % (44 + k - 40) # table dword k (>= 40) -> SGPR
|
|
CX, CY, HW, HH, RCK, IW, IH, STR = S(40), S(41), S(42), S(43), S(44), S(45), S(46), S(47)
|
|
COL = (S(48), S(49), S(50)); FILL, L2X, L2Y, OX0, OY0, ITW, ITH = S(51), S(52), S(53), S(54), S(55), S(56), S(57)
|
|
|
|
def expneg_sq(dst, x, scale, bias):
|
|
"""dst = exp(-((x + bias) / scale)^2)"""
|
|
e("v_add_f32 v%d, %s, v%d" % (dst, hx(bias), x), "v_mul_f32 v%d, %s, v%d" % (dst, hx(1.0 / scale), dst),
|
|
"v_mul_f32 v%d, v%d, v%d" % (dst, dst, dst), "v_mul_f32 v%d, %s, v%d" % (dst, hx(-L2E), dst), "v_exp_f32 v%d, v%d" % (dst, dst))
|
|
def band(dst, x, bias, width):
|
|
"""dst = max(0, 1 - |x + bias| / width)"""
|
|
e("v_add_f32 v%d, %s, v%d" % (dst, hx(bias), x), "v_and_b32 v%d, 0x7fffffff, v%d" % (dst, dst),
|
|
"v_mul_f32 v%d, %s, v%d" % (dst, hx(1.0 / width), dst), "v_sub_f32 v%d, 1.0, v%d" % (dst, dst), "v_max_f32 v%d, 0, v%d" % (dst, dst))
|
|
def powi(dst, x, n):
|
|
"""dst = x^n for n in (5, 6, 20, 40): repeated products"""
|
|
t = R.get()
|
|
e("v_mul_f32 v%d, v%d, v%d" % (t, x, x)) # x^2
|
|
if n == 6:
|
|
e("v_mul_f32 v%d, v%d, v%d" % (dst, t, x), "v_mul_f32 v%d, v%d, v%d" % (dst, dst, dst)) # x^3 ^2
|
|
else:
|
|
e("v_mul_f32 v%d, v%d, v%d" % (t, t, t), "v_mul_f32 v%d, v%d, v%d" % (dst, t, x)) # x^5
|
|
for _ in range({5: 0, 20: 2, 40: 3}[n]): e("v_mul_f32 v%d, v%d, v%d" % (dst, dst, dst))
|
|
R.put(t)
|
|
def rrect(d, gx, gy, ox, oy):
|
|
"""rounded rect SDF d at (X - ox, Y - oy) and (gx, gy) its gradient (gx, gy may be None)"""
|
|
qx, qy, mx, my, t = R.get(), R.get(), R.get(), R.get(), R.get()
|
|
e("v_add_f32 v%d, %s, v2" % (qx, hx(-ox)), "v_subrev_f32 v%d, %s, v%d" % (qx, CX, qx))
|
|
if gx is not None:
|
|
e("v_cmp_gt_f32 vcc, 0, v%d" % qx, "v_cndmask_b32 v%d, 1.0, -1.0, vcc" % gx)
|
|
e("v_and_b32 v%d, 0x7fffffff, v%d" % (qx, qx), "v_subrev_f32 v%d, %s, v%d" % (qx, HW, qx), "v_add_f32 v%d, %s, v%d" % (qx, RCK, qx))
|
|
e("v_add_f32 v%d, %s, v3" % (qy, hx(-oy)), "v_subrev_f32 v%d, %s, v%d" % (qy, CY, qy))
|
|
if gy is not None:
|
|
e("v_cmp_gt_f32 vcc, 0, v%d" % qy, "v_cndmask_b32 v%d, 1.0, -1.0, vcc" % gy)
|
|
e("v_and_b32 v%d, 0x7fffffff, v%d" % (qy, qy), "v_subrev_f32 v%d, %s, v%d" % (qy, HH, qy), "v_add_f32 v%d, %s, v%d" % (qy, RCK, qy))
|
|
e("v_max_f32 v%d, 0, v%d" % (mx, qx), "v_max_f32 v%d, 0, v%d" % (my, qy),
|
|
"v_mul_f32 v%d, v%d, v%d" % (t, mx, mx), "v_mac_f32 v%d, v%d, v%d" % (t, my, my), "v_sqrt_f32 v%d, v%d" % (t, t),
|
|
"v_max_f32 v%d, v%d, v%d" % (d, qx, qy), "v_min_f32 v%d, 0, v%d" % (d, d), "v_add_f32 v%d, v%d, v%d" % (d, d, t),
|
|
"v_subrev_f32 v%d, %s, v%d" % (d, RCK, d))
|
|
if gx is not None:
|
|
# L > 0: (mx, my) / L; else the larger of qx, qy picks the axis
|
|
r_ = R.get()
|
|
e("v_rcp_f32 v%d, v%d" % (r_, t), "v_mul_f32 v%d, v%d, v%d" % (mx, mx, r_), "v_mul_f32 v%d, v%d, v%d" % (my, my, r_),
|
|
"v_cmp_gt_f32 vcc, v%d, v%d" % (qx, qy), "v_cndmask_b32 v%d, 0, 1.0, vcc" % r_, "v_cmp_lt_f32 vcc, 0, v%d" % t,
|
|
"v_cndmask_b32 v%d, v%d, v%d, vcc" % (r_, r_, mx), "v_mul_f32 v%d, v%d, v%d" % (gx, gx, r_))
|
|
e("v_cmp_gt_f32 vcc, v%d, v%d" % (qx, qy), "v_cndmask_b32 v%d, 1.0, 0, vcc" % r_, "v_cmp_lt_f32 vcc, 0, v%d" % t,
|
|
"v_cndmask_b32 v%d, v%d, v%d, vcc" % (r_, r_, my), "v_mul_f32 v%d, v%d, v%d" % (gy, gy, r_))
|
|
R.put(r_)
|
|
R.put(qx, qy, mx, my, t)
|
|
def bevel(nx, ny, nz, h, s, bev, gx, gy):
|
|
"""bevel_normal: u = clamp(s / bev, 0.02, 1), slope (s < bev), n = normalize(slope g, 1), h"""
|
|
u, sl, t = R.get(), R.get(), R.get()
|
|
e("v_mul_f32 v%d, %s, v%d" % (u, hx(1.0 / bev), s), "v_max_f32 v%d, %s, v%d" % (u, hx(0.02), u), "v_min_f32 v%d, 1.0, v%d" % (u, u),
|
|
"v_sub_f32 v%d, 1.0, v%d" % (u, u), "v_mul_f32 v%d, v%d, v%d" % (t, u, u), "v_sub_f32 v%d, 1.0, v%d" % (t, t),
|
|
"v_max_f32 v%d, 0, v%d" % (t, t), "v_sqrt_f32 v%d, v%d" % (t, t), "v_mul_f32 v%d, %s, v%d" % (h, hx(bev), t),
|
|
"v_rcp_f32 v%d, v%d" % (sl, t), "v_mul_f32 v%d, v%d, v%d" % (sl, sl, u),
|
|
"v_cmp_gt_f32 vcc, %s, v%d" % (hx(bev), s), "v_cndmask_b32 v%d, 0, v%d, vcc" % (sl, sl),
|
|
"v_mul_f32 v%d, v%d, v%d" % (nx, sl, gx), "v_mul_f32 v%d, v%d, v%d" % (ny, sl, gy),
|
|
"v_mul_f32 v%d, v%d, v%d" % (t, nx, nx), "v_mac_f32 v%d, v%d, v%d" % (t, ny, ny), "v_add_f32 v%d, 1.0, v%d" % (t, t),
|
|
"v_rsq_f32 v%d, v%d" % (nz, t), "v_mul_f32 v%d, v%d, v%d" % (nx, nx, nz), "v_mul_f32 v%d, v%d, v%d" % (ny, ny, nz))
|
|
R.put(u, sl, t)
|
|
def refract_path(nx, ny, nz, h, c, rx, ry, lp, tirm):
|
|
"""view ray (0,0,-1) into n with 1/IOR_c: r = eta (0,0,-1) + (eta nz - sqrt(k)) n; tirm = 1 if k < 0;
|
|
Lp = h / max(|rz|, 1e-3)"""
|
|
eta = 1.0 / IOR[c]; k, f, rz = R.get(), R.get(), R.get()
|
|
e("v_mul_f32 v%d, v%d, v%d" % (k, nz, nz), "v_sub_f32 v%d, 1.0, v%d" % (k, k), "v_mul_f32 v%d, %s, v%d" % (k, hx(-eta * eta), k),
|
|
"v_add_f32 v%d, 1.0, v%d" % (k, k), "v_cmp_gt_f32 vcc, 0, v%d" % k, "v_cndmask_b32 v%d, 0, 1.0, vcc" % tirm,
|
|
"v_max_f32 v%d, 0, v%d" % (k, k), "v_sqrt_f32 v%d, v%d" % (k, k),
|
|
"v_mul_f32 v%d, %s, v%d" % (f, hx(eta), nz), "v_sub_f32 v%d, v%d, v%d" % (f, f, k),
|
|
"v_mul_f32 v%d, v%d, v%d" % (rx, f, nx), "v_mul_f32 v%d, v%d, v%d" % (ry, f, ny),
|
|
"v_mul_f32 v%d, v%d, v%d" % (rz, f, nz), "v_add_f32 v%d, %s, v%d" % (rz, hx(-eta), rz),
|
|
"v_and_b32 v%d, 0x7fffffff, v%d" % (rz, rz), "v_max_f32 v%d, %s, v%d" % (rz, hx(1e-3), rz),
|
|
"v_rcp_f32 v%d, v%d" % (rz, rz), "v_mul_f32 v%d, v%d, v%d" % (lp, h, rz))
|
|
R.put(k, f, rz)
|
|
|
|
e("; ps_clock: clock mode's UI pass (generated by tools/gen_ps_clock.py): the edge-lit frosted glass slab (bevel",
|
|
"; refraction per channel, frost, grain, Fresnel, the internal light, exit glow, glints, its shadow)",
|
|
"; and the glass text lying on it; then clamp, sRGB and dither like ps_ui. Table: [0] frame T#, [8]",
|
|
"; bilinear clamp S#, [12] heavy frost T# (60 x 34), [20] internal light T# (480 x 270), [28] text",
|
|
"; T# (RG8 1152 x 648), [36] point S#; [40] slab centre x, y, half w, h, corner radius, 1/1920,",
|
|
"; 1/1080, strength | light colour RGB, fill, l2 x, y, slab origin x, y | 1/1152, 1/648 | the clock",
|
|
"; source's dot: centre x, y, radius (off: -100), linear RGB - an antialiased disc over a shadow",
|
|
"; (0.449 black at +2.8 px, the time panel's scaled), after everything else.",
|
|
"s_load_dwordx8 s[4:11], s[0:1], 0x0", "s_load_dwordx4 s[12:15], s[0:1], 0x8", "s_load_dwordx8 s[16:23], s[0:1], 0xc",
|
|
"s_load_dwordx8 s[24:31], s[0:1], 0x14", "s_load_dwordx8 s[32:39], s[0:1], 0x1c", "s_load_dwordx4 s[40:43], s[0:1], 0x24",
|
|
"s_load_dwordx16 s[44:59], s[0:1], 0x28", "s_load_dwordx2 s[60:61], s[0:1], 0x38",
|
|
"s_load_dwordx4 s[68:71], s[0:1], 0x3a", "s_load_dwordx2 s[72:73], s[0:1], 0x3e",
|
|
"s_mov_b32 s62, 0x046f4f3d", "s_mov_b32 s63, 0x0127409f", "s_mov_b32 s64, 0x4bf14f21", "s_waitcnt lgkmcnt(0)")
|
|
# frame and light field at the pixel
|
|
uv = R.get(2); e("v_mul_f32 v%d, %s, v2" % (uv[0], IW), "v_mul_f32 v%d, %s, v3" % (uv[1], IH))
|
|
fr = R.get(3); lf = R.get(3); fq = R.get(3)
|
|
e("image_sample_lz v[%d:%d], v[%d:%d], s[4:11], s[12:15] dmask:0x7" % (fr[0], fr[2], uv[0], uv[1]),
|
|
"image_sample_lz v[%d:%d], v[%d:%d], s[24:31], s[12:15] dmask:0x7" % (lf[0], lf[2], uv[0], uv[1]),
|
|
"image_sample_lz v[%d:%d], v[%d:%d], s[16:23], s[12:15] dmask:0x7" % (fq[0], fq[2], uv[0], uv[1]))
|
|
# slab SDF, gradient, coverage, bevel
|
|
d, gx, gy = R.get(), R.get(), R.get(); rrect(d, gx, gy, 0.0, 0.0)
|
|
m = R.get(); e("v_sub_f32 v%d, 0.5, v%d" % (m, d), "v_max_f32 v%d, 0, v%d" % (m, m), "v_min_f32 v%d, 1.0, v%d" % (m, m))
|
|
s_ = R.get(); e("v_sub_f32 v%d, 0, v%d" % (s_, d), "v_max_f32 v%d, 0, v%d" % (s_, s_))
|
|
nx, ny, nz, h = R.get(), R.get(), R.get(), R.get(); bevel(nx, ny, nz, h, s_, 40.0, gx, gy); R.put(s_)
|
|
tab = R.get(3)
|
|
e("s_waitcnt vmcnt(0)")
|
|
res = R.get(3)
|
|
for c in range(3): e("v_mov_b32 v%d, v%d" % (res[c], fr[c]))
|
|
e("; waves entirely > 100 px outside the slab: the frame (the slab's shadow there is < 1e-7)",
|
|
"v_cmp_gt_f32 vcc, %s, v%d" % (hx(100.0), d), "s_or_b32 s65, vcc_lo, vcc_hi", "s_cbranch_scc0 clock_done")
|
|
for c in range(3):
|
|
(rx, ry), lp, tm = R.get(2), R.get(), R.get()
|
|
refract_path(nx, ny, nz, h, c, rx, ry, lp, tm)
|
|
ex, ey, e2, ez = R.get(), R.get(), R.get(), R.get()
|
|
e("v_mul_f32 v%d, %s, v%d" % (ex, hx(IOR[c]), rx), "v_mul_f32 v%d, %s, v%d" % (ey, hx(IOR[c]), ry),
|
|
"v_mul_f32 v%d, v%d, v%d" % (e2, ex, ex), "v_mac_f32 v%d, v%d, v%d" % (e2, ey, ey),
|
|
"v_cmp_le_f32 vcc, 1.0, v%d" % e2, "v_cndmask_b32 v%d, v%d, 1.0, vcc" % (tm, tm),
|
|
"v_sub_f32 v%d, 1.0, v%d" % (ez, e2), "v_max_f32 v%d, %s, v%d" % (ez, hx(1e-4), ez), "v_rsq_f32 v%d, v%d" % (ez, ez),
|
|
"v_mul_f32 v%d, %s, v%d" % (ez, hx(300.0), ez),
|
|
"v_mul_f32 v%d, v%d, v%d" % (rx, rx, lp), "v_mac_f32 v%d, v%d, v%d" % (rx, ex, ez),
|
|
"v_mul_f32 v%d, v%d, v%d" % (ry, ry, lp), "v_mac_f32 v%d, v%d, v%d" % (ry, ey, ez),
|
|
"v_add_f32 v%d, v%d, v2" % (rx, rx), "v_add_f32 v%d, v%d, v3" % (ry, ry),
|
|
"v_mul_f32 v%d, %s, v%d" % (rx, IW, rx), "v_mul_f32 v%d, %s, v%d" % (ry, IH, ry))
|
|
R.put(ex, ey, e2, ez)
|
|
smp = R.get(3)
|
|
e("image_sample_lz v[%d:%d], v[%d:%d], s[16:23], s[12:15] dmask:0x7" % (smp[0], smp[2], rx, ry), "s_waitcnt vmcnt(0)")
|
|
q = R.get()
|
|
e("v_mul_f32 v%d, %s, v%d" % (q, hx(0.35), fq[c]), "v_cmp_lt_f32 vcc, 0, v%d" % tm,
|
|
"v_cndmask_b32 v%d, v%d, v%d, vcc" % (tab[c], smp[c], q),
|
|
"v_mul_f32 v%d, %s, v%d" % (q, hx(-ABS[c] * L2E), lp), "v_exp_f32 v%d, v%d" % (q, q),
|
|
"v_mul_f32 v%d, v%d, v%d" % (tab[c], tab[c], q))
|
|
R.put(q, rx, ry, lp, tm); R.put(*smp)
|
|
# Fresnel with the key light
|
|
F, kr, t = R.get(), R.get(), R.get()
|
|
e("v_sub_f32 v%d, 1.0, v%d" % (F, nz), "v_mul_f32 v%d, v%d, v%d" % (t, F, F), "v_mul_f32 v%d, v%d, v%d" % (t, t, t),
|
|
"v_mul_f32 v%d, v%d, v%d" % (F, F, t), "v_mul_f32 v%d, %s, v%d" % (F, hx(0.96), F), "v_add_f32 v%d, %s, v%d" % (F, hx(0.04), F),
|
|
"v_mul_f32 v%d, %s, v%d" % (kr, hx(0.45), nx), "v_mac_f32 v%d, %s, v%d" % (kr, hx(0.89), ny), "v_max_f32 v%d, 0, v%d" % (kr, kr))
|
|
powi(t, kr, 6); e("v_mul_f32 v%d, %s, v%d" % (t, hx(1.6), t), "v_add_f32 v%d, %s, v%d" % (t, hx(0.10), t), "v_mul_f32 v%d, v%d, v%d" % (t, t, F),
|
|
"v_sub_f32 v%d, 1.0, v%d" % (F, F))
|
|
for c in range(3): e("v_mul_f32 v%d, v%d, v%d" % (tab[c], tab[c], F), "v_add_f32 v%d, v%d, v%d" % (tab[c], tab[c], t))
|
|
R.put(F, kr, t, nx, ny, nz, h)
|
|
# internal light: I, T = normalize(field.gb)
|
|
I, tx, ty = lf[0], lf[1], lf[2]; t = R.get()
|
|
e("v_mul_f32 v%d, v%d, v%d" % (t, tx, tx), "v_mac_f32 v%d, v%d, v%d" % (t, ty, ty), "v_add_f32 v%d, %s, v%d" % (t, hx(1e-18), t),
|
|
"v_rsq_f32 v%d, v%d" % (t, t), "v_mul_f32 v%d, v%d, v%d" % (tx, tx, t), "v_mul_f32 v%d, v%d, v%d" % (ty, ty, t))
|
|
Ic = R.get(); e("v_max_f32 v%d, 0, v%d" % (Ic, I), "v_min_f32 v%d, 2.0, v%d" % (Ic, Ic), "v_mul_f32 v%d, v%d, v%d" % (Ic, Ic, m),
|
|
"v_mul_f32 v%d, %s, v%d" % (Ic, FILL, Ic), "v_mul_f32 v%d, %s, v%d" % (Ic, STR, Ic))
|
|
for c in range(3): e("v_mac_f32 v%d, %s, v%d" % (tab[c], COL[c], Ic))
|
|
# exit glow and glints on the rim
|
|
b3, wd, ndT, ndl = R.get(), R.get(), R.get(), R.get()
|
|
band(b3, d, 3.0, 3.0); expneg_sq(wd, d, 7.0, 3.0)
|
|
e("v_mul_f32 v%d, v%d, v%d" % (ndT, gx, tx), "v_mac_f32 v%d, v%d, v%d" % (ndT, gy, ty), "v_max_f32 v%d, 0, v%d" % (ndT, ndT),
|
|
"v_mul_f32 v%d, s%s, v%d" % (ndl, L2X[1:], gx), "v_mac_f32 v%d, s%s, v%d" % (ndl, L2Y[1:], gy), "v_sub_f32 v%d, 0, v%d" % (ndl, ndl), "v_max_f32 v%d, 0, v%d" % (ndl, ndl))
|
|
ex_ = R.get(); e("v_mul_f32 v%d, %s, v%d" % (ex_, hx(0.9), b3), "v_mac_f32 v%d, %s, v%d" % (ex_, hx(0.4), wd),
|
|
"v_max_f32 v%d, 0, v%d" % (t, I), "v_min_f32 v%d, %s, v%d" % (t, hx(1.5), t), "v_mul_f32 v%d, v%d, v%d" % (ex_, ex_, t),
|
|
"v_mul_f32 v%d, v%d, v%d" % (ex_, ex_, ndT), "v_mul_f32 v%d, %s, v%d" % (ex_, STR, ex_))
|
|
p40, p20, gw = R.get(), R.get(), R.get()
|
|
powi(p40, ndl, 40); powi(p20, ndl, 20); expneg_sq(gw, d, 16.0, 3.0)
|
|
e("v_mul_f32 v%d, v%d, v%d" % (p40, p40, b3), "v_mul_f32 v%d, %s, v%d" % (p40, hx(2.2), p40),
|
|
"v_mul_f32 v%d, v%d, v%d" % (p20, p20, gw), "v_mac_f32 v%d, %s, v%d" % (p40, hx(1.2), p20), "v_mul_f32 v%d, %s, v%d" % (p40, STR, p40))
|
|
for c in range(3):
|
|
e("v_mac_f32 v%d, %s, v%d" % (tab[c], COL[c], ex_), "v_mul_f32 v%d, 0.5, %s" % (t, COL[c]) if False else "v_mov_b32 v%d, %s" % (t, COL[c]),
|
|
"v_mul_f32 v%d, 0.5, v%d" % (t, t), "v_add_f32 v%d, 0.5, v%d" % (t, t), "v_mac_f32 v%d, v%d, v%d" % (tab[c], p40, t))
|
|
R.put(b3, wd, ndT, ndl, ex_, p40, p20, gw, Ic)
|
|
ng = R.get(3)
|
|
for c in range(3): e("v_mov_b32 v%d, v%d" % (ng[c], tab[c]))
|
|
# grain: an integer hash of the pixel, uniform with unit variance, x 0.035 x coverage
|
|
hs, h2 = R.get(), R.get()
|
|
e("v_cvt_u32_f32 v%d, v2" % hs, "v_cvt_u32_f32 v%d, v3" % h2, "v_mul_lo_u32 v%d, v%d, s62" % (hs, hs),
|
|
"v_mul_lo_u32 v%d, v%d, s63" % (h2, h2), "v_xor_b32 v%d, v%d, v%d" % (hs, hs, h2),
|
|
"v_lshrrev_b32 v%d, 13, v%d" % (h2, hs), "v_xor_b32 v%d, v%d, v%d" % (hs, hs, h2), "v_mul_lo_u32 v%d, v%d, s64" % (hs, hs),
|
|
"v_lshrrev_b32 v%d, 16, v%d" % (h2, hs), "v_xor_b32 v%d, v%d, v%d" % (hs, hs, h2), "v_cvt_f32_u32 v%d, v%d" % (hs, hs),
|
|
"v_mul_f32 v%d, %s, v%d" % (hs, hx(2.0 / 4294967295.0), hs), "v_add_f32 v%d, -1.0, v%d" % (hs, hs),
|
|
"v_mul_f32 v%d, %s, v%d" % (hs, hx(1.7320508 * 0.035), hs), "v_mul_f32 v%d, v%d, v%d" % (hs, hs, m), "v_add_f32 v%d, 1.0, v%d" % (hs, hs))
|
|
for c in range(3): e("v_mul_f32 v%d, v%d, v%d" % (tab[c], tab[c], hs))
|
|
R.put(hs, h2)
|
|
# the slab's shadow on the scene outside and its faint caustic
|
|
ds = R.get(); rrect(ds, None, None, 8.0, 16.0)
|
|
sh, ca = R.get(), R.get()
|
|
expneg_sq(sh, ds, 24.0, 14.0); e("v_cmp_lt_f32 vcc, %s, v%d" % (hx(-60.0), ds), "v_cndmask_b32 v%d, 0, v%d, vcc" % (sh, sh))
|
|
expneg_sq(ca, ds, 9.0, 36.0)
|
|
om = R.get(); e("v_sub_f32 v%d, 1.0, v%d" % (om, m), "v_mul_f32 v%d, v%d, v%d" % (sh, sh, om), "v_mul_f32 v%d, %s, v%d" % (sh, hx(-0.55 * 0.55), sh),
|
|
"v_add_f32 v%d, 1.0, v%d" % (sh, sh), "v_mul_f32 v%d, v%d, v%d" % (ca, ca, om), "v_mul_f32 v%d, %s, v%d" % (ca, hx(0.10 * 0.6), ca))
|
|
for c, cc in enumerate((1.0, 0.93, 0.8)):
|
|
e("v_mul_f32 v%d, v%d, v%d" % (res[c], fr[c], sh), "v_mac_f32 v%d, %s, v%d" % (res[c], hx(cc), ca),
|
|
"v_sub_f32 v%d, v%d, v%d" % (t, tab[c], res[c]), "v_mac_f32 v%d, v%d, v%d" % (res[c], t, m))
|
|
R.put(ds, sh, ca, om); R.put(*fr); R.put(*tab); R.put(*fq)
|
|
# ---- text: the pieces' distance field (slab coords), groups by point loads
|
|
def tex_at(dd, gg, dxs, dys, want_g=True):
|
|
"""dd = distance at (X - ox0 + dx, Y - oy0 + dy) (bilinear R), gg = group there (point load G)"""
|
|
c2 = R.get(2)
|
|
e("v_subrev_f32 v%d, %s, v2" % (c2[0], OX0), "v_subrev_f32 v%d, %s, v3" % (c2[1], OY0))
|
|
for k, (reg, dv) in enumerate(((c2[0], dxs), (c2[1], dys))):
|
|
if isinstance(dv, str): e("v_add_f32 v%d, v%d, v%d" % (reg, reg, int(dv[1:])))
|
|
elif dv: e("v_add_f32 v%d, %s, v%d" % (reg, hx(dv), reg))
|
|
if want_g:
|
|
ic = R.get(4)
|
|
e("v_add_f32 v%d, -0.5, v%d" % (ic[0], c2[0]), "v_add_f32 v%d, -0.5, v%d" % (ic[1], c2[1]),
|
|
"v_rndne_f32 v%d, v%d" % (ic[0], ic[0]), "v_rndne_f32 v%d, v%d" % (ic[1], ic[1]),
|
|
"v_cvt_i32_f32 v%d, v%d" % (ic[0], ic[0]), "v_cvt_i32_f32 v%d, v%d" % (ic[1], ic[1]), "v_mov_b32 v%d, 0" % ic[2])
|
|
g2 = R.get(2)
|
|
e("image_load v[%d:%d], v[%d:%d], s[32:39] dmask:0x3 unorm" % (g2[0], g2[1], ic[0], ic[2]))
|
|
e("v_mul_f32 v%d, %s, v%d" % (c2[0], ITW, c2[0]), "v_mul_f32 v%d, %s, v%d" % (c2[1], ITH, c2[1]))
|
|
e("image_sample_lz v%d, v[%d:%d], s[32:39], s[12:15] dmask:0x1" % (dd, c2[0], c2[1]), "s_waitcnt vmcnt(0)",
|
|
"v_mul_f32 v%d, %s, v%d" % (dd, hx(255.0 / 8.0), dd), "v_add_f32 v%d, %s, v%d" % (dd, hx(-16.0), dd))
|
|
if want_g:
|
|
e("v_mul_f32 v%d, %s, v%d" % (gg, hx(255.0), g2[1]), "v_rndne_f32 v%d, v%d" % (gg, gg))
|
|
R.put(*ic); R.put(*g2)
|
|
R.put(*c2)
|
|
dt, gt = R.get(), R.get(); tex_at(dt, gt, 0.0, 0.0); R.put(gt)
|
|
e("; waves with no lane within 15 px of the text: nothing of it reaches them (shadows need d < 5.6",
|
|
"; within 7 px, caustics d < 0 within 9.1 px, the contact line d < 2.4, the letters d < 0.5)",
|
|
"v_cmp_gt_f32 vcc, %s, v%d" % (hx(15.0), dt), "s_or_b32 s65, vcc_lo, vcc_hi", "s_cbranch_scc0 clock_text_done")
|
|
shade, caus = R.get(), R.get(); e("v_mov_b32 v%d, 0" % shade, "v_mov_b32 v%d, 0" % caus)
|
|
offx, offy = R.get(), R.get()
|
|
for g, th in ((1, 1.0), (2, 0.55), (3, 0.33)):
|
|
for kind in ("shade", "caus"):
|
|
off = 7.0 * th * (1.3 if kind == "caus" else 1.0)
|
|
e("v_mov_b32 v%d, s%s" % (offx, L2X[1:]), "v_mul_f32 v%d, %s, v%d" % (offx, hx(-off), offx),
|
|
"v_mov_b32 v%d, s%s" % (offy, L2Y[1:]), "v_mul_f32 v%d, %s, v%d" % (offy, hx(-off), offy))
|
|
dd, gg = R.get(), R.get(); tex_at(dd, gg, "v%d" % offx, "v%d" % offy)
|
|
v = R.get()
|
|
if kind == "shade":
|
|
sg = 1.5 + 3.0 * th
|
|
e("v_mul_f32 v%d, %s, v%d" % (v, hx(-1.0 / (2.5 * sg)), dd), "v_add_f32 v%d, 0.5, v%d" % (v, v),
|
|
"v_max_f32 v%d, 0, v%d" % (v, v), "v_min_f32 v%d, 1.0, v%d" % (v, v),
|
|
"v_cmp_eq_f32 vcc, %s, v%d" % (hx(float(g)), gg), "v_cndmask_b32 v%d, 0, v%d, vcc" % (v, v), "v_max_f32 v%d, v%d, v%d" % (shade, shade, v))
|
|
else:
|
|
wr = 3.0 * th + 1.0 + 2.5 * th
|
|
expneg_sq(v, dd, wr, 3.0 * th)
|
|
e("v_cmp_gt_f32 vcc, 0, v%d" % dd, "v_cndmask_b32 v%d, 0, v%d, vcc" % (v, v),
|
|
"v_cmp_eq_f32 vcc, %s, v%d" % (hx(float(g)), gg), "v_cndmask_b32 v%d, 0, v%d, vcc" % (v, v), "v_add_f32 v%d, v%d, v%d" % (caus, caus, v))
|
|
R.put(dd, gg, v)
|
|
R.put(offx, offy)
|
|
e("v_mul_f32 v%d, %s, v%d" % (shade, hx(-0.40), shade), "v_mul_f32 v%d, %s, v%d" % (caus, hx(0.30), caus), "v_mul_f32 v%d, %s, v%d" % (caus, STR, caus))
|
|
# the letters' normal: the text distance's gradient by central differences over +-1.5 px (smooth
|
|
# around the glyphs' corners - rounded glass)
|
|
a1, a2, b1, b2, junk = R.get(), R.get(), R.get(), R.get(), R.get()
|
|
tex_at(a1, junk, 1.5, 0.0, want_g=False); tex_at(a2, junk, -1.5, 0.0, want_g=False)
|
|
tex_at(b1, junk, 0.0, 1.5, want_g=False); tex_at(b2, junk, 0.0, -1.5, want_g=False); R.put(junk)
|
|
grx, gry = a1, b1
|
|
e("v_sub_f32 v%d, v%d, v%d" % (grx, a1, a2), "v_mul_f32 v%d, %s, v%d" % (grx, hx(1.0 / 3.0), grx),
|
|
"v_sub_f32 v%d, v%d, v%d" % (gry, b1, b2), "v_mul_f32 v%d, %s, v%d" % (gry, hx(1.0 / 3.0), gry))
|
|
R.put(a2, b2)
|
|
lgx, lgy = R.get(), R.get()
|
|
e("v_mul_f32 v%d, v%d, v%d" % (t, grx, grx), "v_mac_f32 v%d, v%d, v%d" % (t, gry, gry), "v_sqrt_f32 v%d, v%d" % (t, t),
|
|
"v_add_f32 v%d, %s, v%d" % (t, hx(1e-6), t), "v_rcp_f32 v%d, v%d" % (t, t), "v_mul_f32 v%d, v%d, v%d" % (lgx, grx, t), "v_mul_f32 v%d, v%d, v%d" % (lgy, gry, t))
|
|
# per pixel: the light escaping the table into the letters, and the rims' direction terms
|
|
ie, lgl, lge = R.get(), R.get(), R.get()
|
|
e("v_max_f32 v%d, %s, v%d" % (ie, hx(0.35), I), "v_min_f32 v%d, %s, v%d" % (ie, hx(1.6), ie), "v_mul_f32 v%d, %s, v%d" % (ie, hx(0.55), ie), "v_mul_f32 v%d, %s, v%d" % (ie, STR, ie),
|
|
"v_mul_f32 v%d, s%s, v%d" % (lge, L2X[1:], lgx), "v_mac_f32 v%d, s%s, v%d" % (lge, L2Y[1:], lgy),
|
|
"v_sub_f32 v%d, 0, v%d" % (lgl, lge), "v_max_f32 v%d, 0, v%d" % (lgl, lgl), "v_max_f32 v%d, 0, v%d" % (lge, lge))
|
|
p6 = R.get(); powi(p6, lgl, 6)
|
|
# 4 rotated-grid sub-samples: d_k = d + g . o_k; each composited (shadow, caustic, contact line,
|
|
# the letter) and clamped to 0..1, then averaged (the display's view of the pixel)
|
|
acc = R.get(3)
|
|
for c in range(3): e("v_mov_b32 v%d, 0" % acc[c])
|
|
for (ox, oy) in ((-0.125, -0.375), (0.375, -0.125), (0.125, 0.375), (-0.375, 0.125)):
|
|
dk, mi, omi = R.get(), R.get(), R.get()
|
|
e("v_mul_f32 v%d, %s, v%d" % (dk, hx(ox), grx), "v_mac_f32 v%d, %s, v%d" % (dk, hx(oy), gry), "v_add_f32 v%d, v%d, v%d" % (dk, dk, dt),
|
|
"v_sub_f32 v%d, 0.5, v%d" % (mi, dk), "v_max_f32 v%d, 0, v%d" % (mi, mi), "v_min_f32 v%d, 1.0, v%d" % (mi, mi), "v_sub_f32 v%d, 1.0, v%d" % (omi, mi))
|
|
sm, cm, cn = R.get(), R.get(), R.get()
|
|
e("v_mul_f32 v%d, v%d, v%d" % (sm, shade, omi), "v_add_f32 v%d, 1.0, v%d" % (sm, sm), "v_mul_f32 v%d, v%d, v%d" % (cm, caus, omi))
|
|
band(cn, dk, -1.2, 1.2)
|
|
e("v_mul_f32 v%d, v%d, v%d" % (cn, cn, omi), "v_mul_f32 v%d, %s, v%d" % (cn, hx(-0.40), cn), "v_add_f32 v%d, 1.0, v%d" % (cn, cn))
|
|
r = R.get(3)
|
|
for c in range(3):
|
|
e("v_mul_f32 v%d, v%d, v%d" % (r[c], res[c], sm), "v_mac_f32 v%d, %s, v%d" % (r[c], COL[c], cm), "v_mul_f32 v%d, v%d, v%d" % (r[c], r[c], cn))
|
|
R.put(sm, cm, cn)
|
|
ls_ = R.get(); e("v_sub_f32 v%d, 0, v%d" % (ls_, dk), "v_max_f32 v%d, 0, v%d" % (ls_, ls_))
|
|
lnx, lny, lnz, lh = R.get(), R.get(), R.get(), R.get(); bevel(lnx, lny, lnz, lh, ls_, 9.0, lgx, lgy); R.put(ls_)
|
|
let = R.get(3)
|
|
for c in range(3):
|
|
rx, ry, lp, tm = R.get(), R.get(), R.get(), R.get()
|
|
refract_path(lnx, lny, lnz, lh, c, rx, ry, lp, tm) # entering glass from air: no total reflection
|
|
e("v_mul_f32 v%d, %s, v%d" % (lp, hx(-ABS[c] * L2E), lp), "v_exp_f32 v%d, v%d" % (lp, lp), "v_mul_f32 v%d, v%d, v%d" % (let[c], ng[c], lp))
|
|
R.put(rx, ry, lp, tm)
|
|
F, kr = R.get(), R.get()
|
|
e("v_sub_f32 v%d, 1.0, v%d" % (F, lnz), "v_mul_f32 v%d, v%d, v%d" % (t, F, F), "v_mul_f32 v%d, v%d, v%d" % (t, t, t),
|
|
"v_mul_f32 v%d, v%d, v%d" % (F, F, t), "v_mul_f32 v%d, %s, v%d" % (F, hx(0.96), F), "v_add_f32 v%d, %s, v%d" % (F, hx(0.04), F),
|
|
"v_mul_f32 v%d, %s, v%d" % (kr, hx(0.45), lnx), "v_mac_f32 v%d, %s, v%d" % (kr, hx(0.89), lny), "v_max_f32 v%d, 0, v%d" % (kr, kr))
|
|
powi(t, kr, 6); e("v_mul_f32 v%d, %s, v%d" % (t, hx(1.6), t), "v_add_f32 v%d, %s, v%d" % (t, hx(0.10), t), "v_mul_f32 v%d, v%d, v%d" % (t, t, F), "v_sub_f32 v%d, 1.0, v%d" % (F, F))
|
|
for c in range(3): e("v_mul_f32 v%d, v%d, v%d" % (let[c], let[c], F), "v_add_f32 v%d, v%d, v%d" % (let[c], let[c], t))
|
|
R.put(F, kr, lnx, lny, lnz, lh)
|
|
lb, gw, rm = R.get(), R.get(), R.get()
|
|
band(lb, dk, 1.5, 1.5); expneg_sq(gw, dk, 3.0, 1.5)
|
|
e("v_mul_f32 v%d, v%d, v%d" % (rm, lb, p6), "v_mul_f32 v%d, %s, v%d" % (rm, hx(1.1), rm),
|
|
"v_mul_f32 v%d, v%d, v%d" % (lb, lb, lge), "v_mac_f32 v%d, %s, v%d" % (rm, hx(0.55), lb),
|
|
"v_mul_f32 v%d, v%d, v%d" % (gw, gw, p6), "v_mac_f32 v%d, 0.5, v%d" % (rm, gw), "v_mul_f32 v%d, %s, v%d" % (rm, STR, rm),
|
|
"v_add_f32 v%d, v%d, v%d" % (rm, rm, ie), "v_mul_f32 v%d, v%d, v%d" % (mi, mi, m))
|
|
for c in range(3):
|
|
e("v_mac_f32 v%d, %s, v%d" % (let[c], COL[c], rm), "v_sub_f32 v%d, v%d, v%d" % (t, let[c], r[c]), "v_mac_f32 v%d, v%d, v%d" % (r[c], t, mi),
|
|
"v_max_f32 v%d, 0, v%d" % (r[c], r[c]), "v_min_f32 v%d, 1.0, v%d" % (r[c], r[c]), "v_add_f32 v%d, v%d, v%d" % (acc[c], acc[c], r[c]))
|
|
R.put(lb, gw, rm, dk, mi, omi); R.put(*let); R.put(*r)
|
|
for c in range(3): e("v_mul_f32 v%d, %s, v%d" % (res[c], hx(0.25), acc[c]))
|
|
e("clock_text_done:")
|
|
e("clock_done:")
|
|
# the clock source's dot: shadow, then the disc (coverage clamp(0.5 - (|p - c| - r)), as ui_disc)
|
|
ddx, ddy, dd, cv = R.get(), R.get(), R.get(), R.get()
|
|
e("v_subrev_f32 v%d, s68, v2" % ddx, "v_subrev_f32 v%d, s69, v3" % ddy)
|
|
e("v_subrev_f32 v%d, %s, v%d" % (dd, hx(2.8), ddx), "v_mul_f32 v%d, v%d, v%d" % (dd, dd, dd),
|
|
"v_subrev_f32 v%d, %s, v%d" % (cv, hx(2.8), ddy), "v_mac_f32 v%d, v%d, v%d" % (dd, cv, cv),
|
|
"v_sqrt_f32 v%d, v%d" % (dd, dd), "v_sub_f32 v%d, s70, v%d" % (cv, dd), "v_add_f32 v%d, 0.5, v%d" % (cv, cv),
|
|
"v_max_f32 v%d, 0, v%d" % (cv, cv), "v_min_f32 v%d, 1.0, v%d" % (cv, cv),
|
|
"v_mul_f32 v%d, %s, v%d" % (cv, hx(-115.0 / 256.0), cv), "v_add_f32 v%d, 1.0, v%d" % (cv, cv))
|
|
for c in range(3): e("v_mul_f32 v%d, v%d, v%d" % (res[c], res[c], cv))
|
|
e("v_mul_f32 v%d, v%d, v%d" % (dd, ddx, ddx), "v_mac_f32 v%d, v%d, v%d" % (dd, ddy, ddy), "v_sqrt_f32 v%d, v%d" % (dd, dd),
|
|
"v_sub_f32 v%d, s70, v%d" % (cv, dd), "v_add_f32 v%d, 0.5, v%d" % (cv, cv),
|
|
"v_max_f32 v%d, 0, v%d" % (cv, cv), "v_min_f32 v%d, 1.0, v%d" % (cv, cv))
|
|
for c in range(3):
|
|
e("v_sub_f32 v%d, s%d, v%d" % (dd, 71 + c, res[c]), "v_mac_f32 v%d, v%d, v%d" % (res[c], dd, cv))
|
|
R.put(ddx, ddy, dd, cv)
|
|
# ---- ps_ui's end: clamp, sRGB, dither
|
|
e("v_mov_b32 v8, v%d" % res[0], "v_mov_b32 v9, v%d" % res[1], "v_mov_b32 v10, v%d" % res[2],
|
|
"v_mul_f32 v20, 0x3d897143, v2", "v_mac_f32 v20, 0x3bbf4590, v3", "v_fract_f32 v20, v20", "v_mul_f32 v20, 0x4253ee82, v20",
|
|
"v_fract_f32 v20, v20", "v_subrev_f32 v20, 0.5, v20", "v_mul_f32 v20, 0x3b808081, v20")
|
|
for a, o in ((8, 16), (9, 17), (10, 18)):
|
|
e("v_max_f32 v%d, 0, v%d" % (a, a), "v_min_f32 v%d, 1.0, v%d" % (a, a), "v_log_f32 v%d, v%d" % (o, a), "v_mul_f32 v%d, 0x3ed55555, v%d" % (o, o),
|
|
"v_exp_f32 v%d, v%d" % (o, o), "v_mul_f32 v%d, 0x3f870a3d, v%d" % (o, o), "v_subrev_f32 v%d, 0x3d6147ae, v%d" % (o, o),
|
|
"v_mul_f32 v21, 0x414eb852, v%d" % a, "v_cmp_ge_f32 vcc, 0x3b4d2e1c, v%d" % a, "v_cndmask_b32 v%d, v%d, v21, vcc" % (o, o))
|
|
e("v_add_f32 v16, v16, v20", "v_add_f32 v17, v17, v20", "v_add_f32 v18, v18, v20", "v_mov_b32 v19, 1.0",
|
|
"exp mrt0 v16, v17, v18, v19 done vm", "s_endpgm")
|
|
p = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "shaders", "ps_clock.s")
|
|
open(p, "w").write("\n".join(out) + "\n"); print("ps_clock.s: %d lines, VGPRs up to v%d" % (len(out), R.maxv))
|