diff --git a/code/duffle/gen/macs.h b/code/duffle/gen/macs.h index 8784c04..3afc8cc 100644 --- a/code/duffle/gen/macs.h +++ b/code/duffle/gen/macs.h @@ -171,18 +171,27 @@ WORD_COUNT(mac_load_word_imm, 2) , shift_aright(dt_z, dt_z, shift_amount) WORD_COUNT(mac_shift_aright_v3_self, 3) +#define mac_shift_aright_v3s4_self(dt, shift) \ + mac_shift_aright_v3_self(dt.x, dt.y, dt.z, shift) +WORD_COUNT(mac_shift_aright_v3s4_self, 3) + #define mac_shift_aright_var_v3(rd_v0, rd_v1, rd_v2, rs_v0, rs_v1, rs_v2, r_shift) \ shift_aright_var(rd_v0, rs_v0, r_shift) \ , shift_aright_var(rd_v1, rs_v1, r_shift) \ , shift_aright_var(rd_v2, rs_v2, r_shift) WORD_COUNT(mac_shift_aright_var_v3, 3) +/* atom_dbg_skip */ #define mac_shift_aright_var_v3_self(rds_v0, rds_v1, rds_v2, r_shift) \ shift_aright_var(rds_v0, rds_v0, r_shift) \ , shift_aright_var(rds_v1, rds_v1, r_shift) \ , shift_aright_var(rds_v2, rds_v2, r_shift) WORD_COUNT(mac_shift_aright_var_v3_self, 3) +#define mac_shift_aright_var_v3s4_self(ds, shift) \ + mac_shift_aright_var_v3_self(ds.x, ds.y, ds.z, shift) +WORD_COUNT(mac_shift_aright_var_v3s4_self, 3) + /* atom_dbg_skip */ #define mac_load_tri_indices(r_face_cusor, r_i0, r_i1, r_i2) \ load_half_u(r_i0, r_face_cusor, 0 * S_(S2)) \ @@ -190,6 +199,18 @@ WORD_COUNT(mac_shift_aright_var_v3_self, 3) , load_half_u(r_i2, r_face_cusor, 2 * S_(S2)) WORD_COUNT(mac_load_tri_indices, 3) +#define mac_gte_mv_to_cr_diag_v3s4(v) \ + gte_mv_to_ctrl_r(v.y, gte_cr_RT13) \ +, gte_mv_to_ctrl_r(v.z, gte_cr_RT22) \ +, gte_mv_to_ctrl_r(v.x, gte_cr_RT11) +WORD_COUNT(mac_gte_mv_to_cr_diag_v3s4, 3) + +#define mac_gte_ld_ir123_v3s4(v) \ + gte_mv_to_data_r(v.x, C2_IR1) \ +, gte_mv_to_data_r(v.y, C2_IR2) \ +, gte_mv_to_data_r(v.z, C2_IR3) +WORD_COUNT(mac_gte_ld_ir123_v3s4, 3) + /* atom_dbg_skip */ #define mac_gte_store_f3(r_primitive_cursor) \ gte_sw(C2_SXY0, r_primitive_cursor, O_(Poly_F3,p0)) \ diff --git a/code/duffle/gte.atom.c b/code/duffle/gte.atom.c index 1a75426..5ed9384 100644 --- a/code/duffle/gte.atom.c +++ b/code/duffle/gte.atom.c @@ -18,6 +18,18 @@ atom_dbg_skip MipsAtomComp_Proc_(ab, { load_half_u(r_i2, r_face_cusor, 2 * S_(S2)), }) +FI_ Slice_MipsCode ac_gte_mv_to_cr_diag_v3s4(AtomBuilder_R ab, Reg_(V3_S4) v) MipsAtomComp_Proc_(ab, { + gte_mv_to_ctrl_r(v.y, gte_cr_RT13), + gte_mv_to_ctrl_r(v.z, gte_cr_RT22), + gte_mv_to_ctrl_r(v.x, gte_cr_RT11), +}) + +FI_ Slice_MipsCode ac_gte_ld_ir123_v3s4(AtomBuilder_R ab, Reg_(V3_S4) v) MipsAtomComp_Proc_(ab, { + gte_mv_to_data_r(v.x, C2_IR1), + gte_mv_to_data_r(v.y, C2_IR2), + gte_mv_to_data_r(v.z, C2_IR3), +}) + /* Words: 3; Stores the 3 transformed (V2_S2 screen) vertices to the F3. * PIPELINE: post-RTPT (SXY0=v0.screen, SXY1=v1.screen, SXY2=v2.screen). */ FI_ Slice_MipsCode ac_gte_store_f3(AtomBuilder_R ab, U4 r_primitive_cursor) atom_dbg_skip MipsAtomComp_Proc_(ab, { @@ -319,6 +331,35 @@ MipsAtom_Proc_(aa, { mac_yield() }) +typedef Struct_(Binds_gte_cross_v3s4) { V3_S4* src_a; V3_S4* src_b; V3_S4* out; }; +typedef Struct_(RegUse_gte_cross_v3s4) { + Reg_(V3_S4) a; + Reg_(V3_S4) b; + union { Reg t0, out; }; + union { Reg t1, src_a, rt11; }; + union { Reg t2, src_b, rt22; }; +}; +internal MipsAtom* gte_cross_v3s4(AtomArena_R aa, RegUse_gte_cross_v3s4 r) +atom_info(atom_bind(Binds_gte_cross_v3s4)) MipsAtom_Proc_(aa, { + load_word(r.src_a, R_TapePtr, O_(Binds_gte_cross_v3s4,src_a)), + load_word(r.src_b, R_TapePtr, O_(Binds_gte_cross_v3s4,src_b)), + load_word(r.out, R_TapePtr, O_(Binds_gte_cross_v3s4,out)), + LdSlot_ add_ui_self(R_TapePtr, S_(Binds_gte_cross_v3s4)), + + mac_load_v3s4(r.a, r.src_a, 0), LdSlot_ + mac_load_v3s4(r.b, r.src_b, 0), LdSlot_ + + mac_gte_mv_to_cr_diag_v3s4(r.a), GteDelay_ /* RT diagonal: D1 = a.x, D2 = a.y, D3 = a.z. */ + mac_gte_ld_ir123_v3s4(r.b), GteDelay_ /* IR: second operand. */ + gte_cmdw_cross, /* MAC1/2/3 = a × b */ + mac_gte_mv_from_data_r_mac123(r.a.x, r.a.y, r.a.z), GteDelay_ //nop, + + mac_shift_aright_v3s4_self(r.a, 12), + mac_store_v3s4(r.a, r.out, 0), + + mac_yield() +}) + #pragma endregion Atom Procs #pragma region Baked Atoms diff --git a/code/duffle/gte.h b/code/duffle/gte.h index 6e3899d..ea31cc4 100644 --- a/code/duffle/gte.h +++ b/code/duffle/gte.h @@ -101,20 +101,20 @@ enum { /* Semantic Aliases for GTE Data Registers */ enum { - gte_in_v0_xy = C2_VXY0, /* Input Vector 0 (X, Y) */ - gte_in_v0_z = C2_VZ0, /* Input Vector 0 (Z) */ - gte_in_v1_xy = C2_VXY1, /* Input Vector 1 (X, Y) */ - gte_in_v1_z = C2_VZ1, /* Input Vector 1 (Z) */ - gte_in_v2_xy = C2_VXY2, /* Input Vector 2 (X, Y) */ - gte_in_v2_z = C2_VZ2, /* Input Vector 2 (Z) */ - gte_in_rgb = C2_RGB, /* Input Color (R, G, B, MipsCode) */ - gte_out_scr_xy0 = C2_SXY0, /* Output Screen Coord 0 (X, Y) */ - gte_out_scr_xy1 = C2_SXY1, /* Output Screen Coord 1 (X, Y) */ - gte_out_scr_xy2 = C2_SXY2, /* Output Screen Coord 2 (X, Y) */ - gte_out_depth = C2_OTZ, /* Output Ordering Table Z (Depth) */ - gte_math_accum0 = C2_MAC0, /* Math Accumulator 0 */ - gte_math_accum1 = C2_MAC1, /* Math Accumulator 1 */ - gte_math_accum2 = C2_MAC2, /* Math Accumulator 2 */ + C2_InV0_XY = C2_VXY0, /* Input Vector 0 (X, Y) */ + C2_InV0_Z = C2_VZ0, /* Input Vector 0 (Z) */ + C2_InV1_XY = C2_VXY1, /* Input Vector 1 (X, Y) */ + C2_InV1_Z = C2_VZ1, /* Input Vector 1 (Z) */ + C2_InV2_XY = C2_VXY2, /* Input Vector 2 (X, Y) */ + C2_InV2_Z = C2_VZ2, /* Input Vector 2 (Z) */ + C2_In_RGB = C2_RGB, /* Input Color (R, G, B, MipsCode) */ + C2_OutSrc_XY0 = C2_SXY0, /* Output Screen Coord 0 (X, Y) */ + C2_OutSrc_XY1 = C2_SXY1, /* Output Screen Coord 1 (X, Y) */ + C2_OutSrc_XY2 = C2_SXY2, /* Output Screen Coord 2 (X, Y) */ + C2_OutDepth = C2_OTZ, /* Output Ordering Table Z (Depth) */ + C2_MathAccu0 = C2_MAC0, /* Math Accumulator 0 */ + C2_MathAccu1 = C2_MAC1, /* Math Accumulator 1 */ + C2_MathAccu2 = C2_MAC2, /* Math Accumulator 2 */ }; /* --- GTE Command Semantics (The Bitfield Meanings) --- diff --git a/code/duffle/lottes_tape.h b/code/duffle/lottes_tape.h index 8bdab79..01ddd6f 100644 --- a/code/duffle/lottes_tape.h +++ b/code/duffle/lottes_tape.h @@ -110,7 +110,7 @@ typedef Slice_(MipsAtom); // Sometimes a user will define a bundle of atoms that represent a procedure of work as: // MipsAtom* [...]; // Unfortuantely if using slice_from_array it will make the slice's pointer: MipsAtom** so this enforce its defined as MipsAtom* -// TODO(Ed): Alternatively we can make the MipsAtom an opaque pointer to the atom... so that the blow returns 'MipsAtom'. +// TODO(Ed): Alternatively we can make the MipsAtom an opaque pointer to the atom... so that the proc returns 'MipsAtom'. #define atombundle_from_array(array) (Slice_MipsAtom){.ptr=array[0],.len=Array_len(array)} // Underlying type to an ptr to an array of mips asm words that must terminate with an ac_yield. diff --git a/code/duffle/mips.atom.c b/code/duffle/mips.atom.c index 98d2f5b..f99296e 100644 --- a/code/duffle/mips.atom.c +++ b/code/duffle/mips.atom.c @@ -23,6 +23,8 @@ MipsAtomComp_Proc_( ab, { shift_aright(dt_z, dt_z, shift_amount), }) +FI_ Slice_MipsCode ac_shift_aright_v3s4_self(AtomBuilder_R ab, Reg_(V3_S4) dt, U2 shift) MipsAtomComp_ProcMap_(ab, mac_shift_aright_v3_self(dt.x, dt.y, dt.z, shift)) + FI_ Slice_MipsCode ac_shift_aright_var_v3(AtomBuilder_R ab , Reg rd_v0, Reg rd_v1, Reg rd_v2 , Reg rs_v0, Reg rs_v1, Reg rs_v2 @@ -33,15 +35,15 @@ MipsAtomComp_Proc_(ab, { shift_aright_var(rd_v2, rs_v2, r_shift), }) -FI_ Slice_MipsCode ac_shift_aright_var_v3_self(AtomBuilder_R ab - , Reg rds_v0, Reg rds_v1, Reg rds_v2 - , Reg r_shift) -MipsAtomComp_Proc_(ab, { +FI_ Slice_MipsCode ac_shift_aright_var_v3_self(AtomBuilder_R ab, Reg rds_v0, Reg rds_v1, Reg rds_v2, Reg r_shift) +atom_dbg_skip MipsAtomComp_Proc_(ab, { shift_aright_var(rds_v0, rds_v0, r_shift), shift_aright_var(rds_v1, rds_v1, r_shift), shift_aright_var(rds_v2, rds_v2, r_shift), }) +FI_ Slice_MipsCode ac_shift_aright_var_v3s4_self(AtomBuilder_R ab, Reg_(V3_S4) ds, Reg shift) MipsAtomComp_ProcMap_(ab, mac_shift_aright_var_v3_self(ds.x, ds.y, ds.z, shift)) + #pragma endregion MACs (Mips Atom Components) #pragma region Baked Atoms diff --git a/code/duffle/word_count.metadata.h b/code/duffle/word_count.metadata.h index a454402..ff15774 100644 --- a/code/duffle/word_count.metadata.h +++ b/code/duffle/word_count.metadata.h @@ -55,6 +55,7 @@ WORD_COUNT(gte_mv_to_ctrl_r, 1) WORD_COUNT(gte_sw, 1) WORD_COUNT(gte_cmdw_rtpt, 1) WORD_COUNT(gte_cmdw_nclip, 1) +WORD_COUNT(gte_cmdw_op, 1) WORD_COUNT(gte_avg_sort_z3, 1) WORD_COUNT(gte_cmdw_sqr, 1) WORD_COUNT(gte_cmdw_gpf, 1) diff --git a/code/hello_camera/hello_camera.atom.c b/code/hello_camera/hello_camera.atom.c index 2242213..9e021da 100644 --- a/code/hello_camera/hello_camera.atom.c +++ b/code/hello_camera/hello_camera.atom.c @@ -104,9 +104,9 @@ MipsAtomComp_Proc_(ab, { typedef AtomBundle_(resolve_look_at) { MipsAtom* input_and_sub, normalize_fwd_uz, - cross_uz_up_into_right, + cross_to_right, normalize_right_ux, - cross_uz_ux_to_up, + cross_to_up, normalize_up_uy, populate, set_gte_mt3s2s4, @@ -178,141 +178,6 @@ atom_info(atom_bind(Binds_ResolveLookAtSub)) MipsAtom_Proc_(aa, { mac_yield() }) -typedef Struct_(RegUse_resolve_look_at_cross_uz_up_into_right) { - Reg scratch; - Reg a; Reg b; Reg c; /* load a.x/y/z; result out.x/y/z */ - Reg d; /* load b.x */ - Reg f; /* r_f = &right (out ptr), r_g = &uz, r_h = &up_in */ - - union { Reg t1, g, target0; }; - union { Reg t2, h, target1; }; - Reg t0; -}; -/* Atom 2: cross uz × up_in → right. */ -// internal MipsAtom* AtomBundleEntry_(resolve_look_at, cross_uz_up_to_right)(AtomArena_R aa, -internal MipsAtom* resolve_look_at_cross_uz_up_into_right(AtomArena_R aa, - RegUse_resolve_look_at_cross_uz_up_into_right r -) MipsAtom_Proc_(aa, { - /* FIX: build packed RT22+RT33 with proper sign extension. */ - add_si(r.g, r.scratch, O_(ResolveLookAtScratch,uz)), /* r_g = &uz */ - add_si(r.h, r.scratch, O_(ResolveLookAtScratch,up_in)), /* r_h = &up_in */ - add_si(r.f, r.scratch, O_(ResolveLookAtScratch,right)), /* r_f = &right (out) */ - nop, - - /* Load a (uz).x/y/z into r_a/r_b/r_c. */ - mac_load_word_v3(r.a, r.b, r.c, r.g, 0), LdSlot_ - /* Load b (up_in).x/y/z into r_d + R_AT/R_V0 (R_AT/R_V0 are hardcoded scratch). */ - mac_load_word_v3(r.d, R_AT, r.t0, r.h, 0), LdSlot_ // (taken by gte_mv_from_ctrl_r) - - /* Save the two RT control-register slots OP will clobber. We reuse r_g/r_h (scratch pointers, no longer needed) as the save targets. */ - gte_mv_from_ctrl_r(r.target0, gte_cr_RT11), /* r_g = C2 r0 (RT11|RT12) */ - gte_mv_from_ctrl_r(r.target1, gte_cr_RT22), /* r_h = C2 r4 (RT22|RT33) */ - /* Load uz.x/uz.y/uz.z into COP2 control registers. - * OP reads D1 = RT11 from $0.low, D2 = RT22 from $2.high, D3 = RT33 from $4.high. - * RT22 is in BOTH $2.high AND $4.low (shared bit position). OP reads from $2.high. - * So set RT22 via ctc2 r_b, $2 (sets $2.high = a.y.high = RT22, $2.low = a.y.low = RT13). - * Then set RT33 via ctc2 r_c, $4 (sets $4.high = a.z.high = RT33, $4.low = a.z.low). - * The $2 and $4 writes don't clobber each other (separate registers). - * The 2nd ctc2 DOES clobber $4.low (becomes a.z.low, NOT a.y.high), but since OP - * reads RT22 from $2.high (which the 2nd ctc2 doesn't touch), D2 is still a.y.high. - * This is libpsyx's OuterProduct12 convention. */ - gte_mv_to_ctrl_r(r.b, gte_cr_RT13), /* $2 = r_b = a.y. RT13=a.y.low, RT22=a.y.high. */ - gte_mv_to_ctrl_r(r.c, gte_cr_RT22), /* $4 = r_c = a.z. RT22=a.z.low, RT33=a.z.high. */ - - /* Load uz into the RT diagonal. */ - gte_mv_to_ctrl_r(r.a, gte_cr_RT11), /* D1 = RT11 = uz.x. */ - GteDelay_ nop2, /* CTC2 retirement */ - - /* Load up_in into IR (the second operand for OP). */ - gte_mv_to_data_r(r.d, C2_IR1), /* IR1 = up_in.x */ - gte_mv_to_data_r(R_AT, C2_IR2), /* IR2 = up_in.y */ - gte_mv_to_data_r(r.t0, C2_IR3), /* IR3 = up_in.z */ - GteDelay_ nop2, /* MTC2 retirement */ - - gte_cmdw_cross, /* OP: MAC1/2/3 = uz × up_in - * MAC1 = IR3*D2 - IR2*D3 = up_in.z*uz.y.high - up_in.y*uz.z.high - * MAC2 = IR1*D3 - IR3*D1 = up_in.x*uz.z.high - up_in.z*uz.x - * MAC3 = IR2*D1 - IR1*D2 = up_in.y*uz.x - up_in.x*uz.y.high - * For up_in = (0, -fp_one, 0): - * MAC1 = 0 - (-fp_one)*uz.z.high = fp_one*uz.z.high - * MAC2 = 0 - 0 = 0 - * MAC3 = (-fp_one)*uz.x - 0 = -fp_one*uz.x */ - - /* Restore the RT slots we clobbered. */ - gte_mv_to_ctrl_r(r.target0, gte_cr_RT11), /* restore C2 r0 (RT11|RT12) */ - gte_mv_to_ctrl_r(r.target1, gte_cr_RT22), /* restore C2 r4 (RT22|RT33) */ - - /* mfc2 MAC1/2/3 → r_a/r_b/r_c (out.x/y/z). */ - mac_gte_mv_from_data_r_mac123(r.a, r.b, r.c), - GteDelay_ nop, /* MFC2 retirement */ - - /* Right-shift MAC by 12 to convert from GTE's S12.20 fixed-point scale back to libpsyx OuterProduct12 convention (S12.0, fp_one=4096=1<<12). - * Without this, MAC values (~16M for unit-vector cross products) overflow the GTE's 16-bit IR registers when atom 3 normalizes via mtc2. */ - mac_shift_aright_v3_self(r.a, r.b, r.c, 12), - /* Store out.x/y/z to r_f (out ptr = scratch+32). */ - mac_store_word_v3(r.a, r.b, r.c, r.f, 0), - - mac_yield() -}) - -typedef Struct_(RegUse_resolve_look_at__cross_uz_ux_to_up_proc) { - Reg const scratch; /* pinned T4 */ - Reg_(V3_S4) a; /* uz components, then MAC / out */ - Reg_(V3_S4) b; /* ux components */ - union { Reg t0, up; }; /* &up, dedicated */ - union { Reg t1, uz, rt11; }; /* &uz, then RT11 save */ - union { Reg t2, ux, rt22; }; /* &ux, then RT22 save */ -}; -/* Atom 4: cross uz × ux → up. */ -internal MipsAtom* resolve_look_at__cross_uz_ux_to_up_proc(AtomArena_R aa, - RegUse_resolve_look_at__cross_uz_ux_to_up_proc r -) MipsAtom_Proc_(aa, { - add_si(r.uz, r.scratch, O_(ResolveLookAtScratch,uz)), /* r.uz = &uz */ - add_si(r.ux, r.scratch, O_(ResolveLookAtScratch,ux)), /* r.ux = &ux */ - add_si(r.up, r.scratch, O_(ResolveLookAtScratch,up)), /* r.up = &up (out) */ - - mac_load_v3s4(r.a, r.uz, 0), LdSlot_ - mac_load_v3s4(r.b, r.ux, 0), LdSlot_ /* taken by gte_mv_from_ctrl_r */ - - /* OP reads D1/D2/D3 from RT11/RT22/RT33 ($0/$2/$4), not V0/V1/V2. - * Mirror atom 1: cfc2 RT save, ctc2 RT diagonal from uz, mtc2 IR from ux, ctc2 RT restore. */ - - /* Save the two RT control-register slots OP will clobber (reusing r.uz/r.ux — they're no longer needed as scratch pointers). */ - gte_mv_from_ctrl_r(r.rt11, gte_cr_RT11), /* r.rt11 = C2 $0 (RT11|RT12) */ - gte_mv_from_ctrl_r(r.rt22, gte_cr_RT22), /* r.rt22 = C2 $4 (RT22|RT33) */ - - /* Load uz into the RT diagonal — same packing as atom 1. - * OP reads D1 = RT11 from $0.low, D2 = RT22 from $2.high, D3 = RT33 from $4.high. - * RT22 is shared between $2.high and $4.low — the ctc2 sequence to $2 then $4 - * sets RT22 to uz.y.high (via $2), then to uz.z.low (via $4). - * OP reads RT22 from $2.high which the second ctc2 doesn't touch, so D2 stays uz.y.high. */ - gte_mv_to_ctrl_r(r.a.y, gte_cr_RT13), /* $2 = uz.y. RT13=uz.y.low, RT22=uz.y.high. */ - gte_mv_to_ctrl_r(r.a.z, gte_cr_RT22), /* $4 = uz.z. RT22=uz.z.low, RT33=uz.z.high. */ - gte_mv_to_ctrl_r(r.a.x, gte_cr_RT11), /* $0 = uz.x. RT11=uz.x. */ - GteDelay_ nop2, /* CTC2 retirement (CPU→COP2 2-slot delay) */ - - /* Load ux into the IR registers (the second operand for OP). */ - gte_mv_to_data_r(r.b.x, C2_IR1), /* IR1 = ux.x */ - gte_mv_to_data_r(r.b.y, C2_IR2), /* IR2 = ux.y */ - gte_mv_to_data_r(r.b.z, C2_IR3), /* IR3 = ux.z */ - GteDelay_ nop2, /* MTC2 retirement (CPU→COP2 2-slot delay) */ - - gte_cmdw_cross, - - /* Restore the RT slots we clobbered. */ - gte_mv_to_ctrl_r(r.rt11, gte_cr_RT11), /* restore C2 $0 (RT11|RT12) */ - gte_mv_to_ctrl_r(r.rt22, gte_cr_RT22), /* restore C2 $4 (RT22|RT33) */ - - mac_gte_mv_from_data_r_mac123(r.a.x, r.a.y, r.a.z), - GteDelay_ nop, - - /* Right-shift MAC by 12 to convert from GTE's S12.20 scale back to libpsyx - * OuterProduct12 convention (S12.0, fp_one=4096). See atom 1 for rationale. */ - mac_shift_aright_v3_self(r.a.x, r.a.y, r.a.z, 12), - mac_store_v3s4(r.a, r.up, 0), - - mac_yield() -}) typedef Struct_(Binds_ResolveLookAtPopAndTrans) { U4 look_at; /* U4 (MT3_S2S4* — destination matrix address) */ @@ -407,7 +272,7 @@ internal MipsAtom* resolve_look_at__matrix_vector_proc(AtomArena_R aa, * * Pool cost: r_look_at (1) + r_scratch (carrier) + r_off_ptr + 1 clobber = 4 GPRs. */ -I_ MipsAtom* resolve_look_at__trans_matrix_proc(AtomArena_R aa +I_ MipsAtom* AtomBundleEntry_(resolve_look_at,trans_matrix)(AtomArena_R aa , U4 r_look_at, U4 r_scratch, U4 r_off_ptr , U4 r_tmp0, U4 r_tmp1, U4 r_tmp2 ) MipsAtom_Proc_(aa, { diff --git a/code/hello_camera/hello_camera.c b/code/hello_camera/hello_camera.c index 89a83ad..fa0ddbd 100644 --- a/code/hello_camera/hello_camera.c +++ b/code/hello_camera/hello_camera.c @@ -186,21 +186,16 @@ internal void compile_resolve_look_at(void) { }); regfile_reset_to_mask(& rf, pin_mask); - /* === ATOM 2: cross uz×up_in→right === */ - // smem.resolve_look_at_bundle[2] = AtomBundleEntry_(resolve_look_at,cross_uz_up_to_right)(& ab, - smem.resolve_look_at_bundle[2] = resolve_look_at_cross_uz_up_into_right(& ab, - RegUse_(resolve_look_at_cross_uz_up_into_right) { - .scratch = R_ResolveScratch, - .a = ralloc(), - .b = ralloc(), - .c = ralloc(), - .d = ralloc(), - .f = ralloc(), + /* === ATOM 2: cross uz×up_in→right (Binds_gte_cross_v3s4) === */ + smem.resolve_look_at_bundle[2] = gte_cross_v3s4(& ab, + RegUse_(gte_cross_v3s4) { + .a = ralloc_v3(), + .b = ralloc_v3(), + .t0 = ralloc(), .t1 = ralloc(), .t2 = ralloc(), - .t0 = ralloc(), }); - regfile_reset_to_mask(& rf, pin_mask); + regfile_reset_to_mask(& rf, pin_mask); /* === ATOM 3: normalize right→ux === */ src_offset = O_(ResolveLookAtScratch, right); @@ -220,17 +215,16 @@ internal void compile_resolve_look_at(void) { }); regfile_reset_to_mask(& rf, pin_mask); - /* === ATOM 4: cross uz×ux→up === */ - smem.resolve_look_at_bundle[4] = resolve_look_at__cross_uz_ux_to_up_proc(& ab, - RegUse_(resolve_look_at__cross_uz_ux_to_up_proc){ - .scratch = R_ResolveScratch, - .a = ralloc_v3(), /* T0 T1 T2 */ - .b = ralloc_v3(), /* T3 T5 T6 */ - .t0 = ralloc(), /* T7 = up */ - .t1 = ralloc(), /* V0 = uz / rt11 */ - .t2 = ralloc(), /* V1 = ux / rt22 */ + /* === ATOM 4: cross uz×ux→up (Binds_gte_cross_v3s4) === */ + smem.resolve_look_at_bundle[4] = gte_cross_v3s4(& ab, + RegUse_(gte_cross_v3s4) { + .a = ralloc_v3(), + .b = ralloc_v3(), + .t0 = ralloc(), + .t1 = ralloc(), + .t2 = ralloc(), }); - regfile_reset_to_mask(& rf, pin_mask); + regfile_reset_to_mask(& rf, pin_mask); /* === ATOM 5: normalize up→uy === */ src_offset = O_(ResolveLookAtScratch, up); @@ -280,8 +274,13 @@ internal void compile_resolve_look_at(void) { U4 r_scratch_6c = R_ResolveScratch; U4 r_off_ptr_6c = R_T1; /* &scratch.eye (= off dst) */ U4 r_tmp0_6c = R_T2; - smem.resolve_look_at_bundle[9] = resolve_look_at__trans_matrix_proc(& ab, - r_look_at_6c, r_scratch_6c, r_off_ptr_6c, r_tmp0_6c, R_T3, R_T4); + smem.resolve_look_at_bundle[9] = AtomBundleEntry_(resolve_look_at,trans_matrix)(& ab, + r_look_at_6c, + r_scratch_6c, + r_off_ptr_6c, + r_tmp0_6c, + R_T3, + R_T4); /* Sanity check: arena didn't overflow. */ assert(ab.used <= ResolveLookAtArena_Size); @@ -295,6 +294,9 @@ I_ void resolve_look_at(TapeBuilder_R tb , P3_S4* target , V3_S4* up_in ){ + /* Typed view of the scratchpad for field-address arithmetic. */ + ResolveLookAtScratch* sp = C_scratch(ResolveLookAtScratch*); + tb_emit(tb, smem.resolve_look_at_bundle[0]); { tb_data(tb, u4_(target)); tb_data(tb, u4_(eye)); @@ -302,15 +304,25 @@ I_ void resolve_look_at(TapeBuilder_R tb tb_data(tb, u4_(smem.scratchpad)); } - tb_emit(tb, smem.resolve_look_at_bundle[1]); { + tb_emit(tb, smem.resolve_look_at_bundle[1]); { // tb_data(tb, u4_(Scratchpad_Loc)); } - tb_emit(tb, smem.resolve_look_at_bundle[2]); { } - tb_emit(tb, smem.resolve_look_at_bundle[3]); { + tb_emit(tb, smem.resolve_look_at_bundle[2]); { + /* Binds_gte_cross_v3s4: src_a, src_b, out (3 pointers). */ + tb_data(tb, u4_(& sp->uz)); /* src_a */ + tb_data(tb, u4_(& sp->up_in)); /* src_b */ + tb_data(tb, u4_(& sp->right)); /* out */ + } + tb_emit(tb, smem.resolve_look_at_bundle[3]); { // tb_data(tb, u4_(Scratchpad_Loc)); } - tb_emit(tb, smem.resolve_look_at_bundle[4]); { } - tb_emit(tb, smem.resolve_look_at_bundle[5]); { + tb_emit(tb, smem.resolve_look_at_bundle[4]); { + /* Binds_gte_cross_v3s4: src_a, src_b, out (3 pointers). */ + tb_data(tb, u4_(& sp->uz)); /* src_a */ + tb_data(tb, u4_(& sp->ux)); /* src_b */ + tb_data(tb, u4_(& sp->up)); /* out */ + } + tb_emit(tb, smem.resolve_look_at_bundle[5]); { // tb_data(tb, u4_(Scratchpad_Loc)); }