From bebcc6a585c6123234d8a30e58a01046d3f877ec Mon Sep 17 00:00:00 2001 From: Ed_ Date: Tue, 11 Aug 2026 01:25:09 -0400 Subject: [PATCH] wip: going to incremnetally test this. --- code/duffle/lottes_tape.h | 13 ++++++++---- code/duffle/memory.h | 20 +++++++++--------- code/hello_camera/hello_camera.c | 36 +++++++++++++++++++++++++------- 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/code/duffle/lottes_tape.h b/code/duffle/lottes_tape.h index 72018e9..b40a356 100644 --- a/code/duffle/lottes_tape.h +++ b/code/duffle/lottes_tape.h @@ -186,14 +186,14 @@ FI_ void tape_run_a02_s07(Tape tape) { register U4* tape_ptr rgcc(R_TapePtr) = u typedef Relative_(FArena) Struct_(TapeBuilder) { U4 ptr; U4 capacity; U4 used; }; FI_ void tb_init(TapeBuilder* tb, FArena* arena) { tb->ptr = arena->start; tb->used = 0; } FI_ TapeBuilder tb_make_old( FArena* arena) { return (TapeBuilder){ arena->start, 0 }; } -FI_ TapeBuilder tb_make(Slice mem) { return (TapeBuilder){ mem.ptr, mem.len, 0 }; } +FI_ TapeBuilder tb_make(Slice mem) { return (TapeBuilder){ u4_(mem.ptr), mem.len, 0 }; } /* capacity in elements (matches used units) */ FI_ void tb_emit(TapeBuilder* tb, MipsAtom* atom) { u4_r(tb->ptr)[tb->used] = u4_(atom); ++ tb->used; } FI_ void tb_data(TapeBuilder* tb, U4 data) { u4_r(tb->ptr)[tb->used] = u4_(data); ++ tb->used; } #define tb_emit_(atom) tb_emit(& tb, atom) #define tb_data_(field, data) tb_data(& tb, u4_(data)) -FI_ void tb_emit_bundle(TapeBuilder_R tb, Slice_MipsAtom atoms) { mem_copy(u4_(tb->ptr), u4_(atoms.ptr), tb->used); tb->used += atoms.len; } +FI_ void tb_emit_bundle(TapeBuilder_R tb, Slice_MipsAtom atoms) { mem_copy(u4_(tb->ptr), u4_(atoms.ptr), S_slice(atoms)); tb->used += atoms.len; } FI_ Tape tb_end (TapeBuilder* tb) { tb_emit(tb,tape_exit); return (Tape){ C_(U4*,tb->ptr), tb->used }; } FI_ Tape tb_slice(TapeBuilder tb) { return (Tape){ C_(U4*,tb.ptr), tb.used }; } @@ -242,18 +242,23 @@ typedef Relative_(FArena) Struct_(MipsAtomBuilder) { U4 start; U4 capacity; U4 u // to something that can fit within instruction cache? FI_ void atombuilder_unroll(MipsAtomBuilder_R ab, Slice_MipsCode code) { + /* code.len is in ELEMENTS (per slice_from_array convention); ab->used is also in elements + * (the init uses `ab->used * sizeof(U4)` for byte offset arithmetic — sizeof(U4)==4==sizeof(MipsCode)). + * mem_copy needs BYTES, so we use S_slice(code) for the length. */ assert(ab->capacity - ab->used - code.len); U4* dest = (U4*)ab->start + ab->used; /* write at next-available slot (arena accumulation) */ - mem_copy(u4_(dest), u4_(code.ptr), code.len); + mem_copy(u4_(dest), u4_(code.ptr), S_slice(code)); mem_bump(ab->start, ab->capacity, & ab->used, code.len); } #define atombuilder_unroll_mac(ab, mac) atombuilder_unroll(ab, slice_arg_from_array(Slice_MipsCode, mac)) // When done authoring, utilize this to cap-off the atom (if not utilizing a MipsAtom_Proc). FI_ void atombuilder_end(MipsAtomBuilder_R ab) { + /* ac_yield is a MipsCode[] of 4 elements; S_(ac_yield)=bytes, array_len(ac_yield)=elements. + * ab->used is in elements, so mem_bump needs element count. */ U4* dest = (U4*)ab->start + ab->used; /* write at next-available slot */ mem_copy(u4_(dest), u4_(ac_yield), S_(ac_yield)); - mem_bump(ab->start, ab->capacity, & ab->used, S_(ac_yield)); + mem_bump(ab->start, ab->capacity, & ab->used, array_len(ac_yield)); } #define mipsatom_from_builder(ab) C_(MipsAtom*, (ab).start) diff --git a/code/duffle/memory.h b/code/duffle/memory.h index f7b432f..cb3be73 100644 --- a/code/duffle/memory.h +++ b/code/duffle/memory.h @@ -58,13 +58,13 @@ typedef Struct_(Str8) { UTF8* ptr; U4 len; }; typedef Struct_(Slice_Str8) { Str8* ptr; U4 len; }; #define slit(string_literal) (Str8){ (UTF8*) string_literal, S_(string_literal) - 1 } -typedef Struct_(Slice) { U4 ptr, len; }; // Untyped Slice -FI_ Slice slice_ut_(U4 ptr, U4 len) { return (Slice){ptr, len}; } +typedef Struct_(Slice) { B1* ptr; U4 len; }; // Untyped Slice (byte-addressable; .len in elements) +FI_ Slice slice_ut_(U4 ptr, U4 len) { return (Slice){(B1*)ptr, len}; } #define Slice_(type) Struct_(tmpl(Slice,type)) { type* ptr; U4 len; } typedef Slice_(B1); #define slice_assert(s) do { assert((s).ptr != 0); assert((s).len > 0); } while(0) -#define slice_end(slice) ((slice).ptr + (slice).len) +#define slice_end(slice) ((slice).ptr + S_slice(slice) / S_(B1)) /* byte-ptr arithmetic; .len is in elements per slice convention */ #define S_slice(s) ((s).len * S_((s).ptr[0])) #define slice_ut(ptr,len) slice_ut_(u4_(ptr), u4_(len)) @@ -73,16 +73,16 @@ typedef Slice_(B1); #define slice_iter(container, iter) (T_((container).ptr) iter = (container).ptr; iter != slice_end(container); ++ iter) #define slice_arg_from_array(type, ...) & (tmpl(Slice,type)) { .ptr = array_decl(type,__VA_ARGS__), .len = array_len( array_decl(type,__VA_ARGS__)) } -#define slice_from_array(type, array) (tmpl(Slice,type)) { .ptr = array, .len = S_(array) } +#define slice_from_array(type, array) (tmpl(Slice,type)) { .ptr = array, .len = S_(array) / S_(type) } /* .len in elements (matches S_slice/slice_arg_from_array convention) */ -FI_ void slice_zero_(Slice s) { slice_assert(s); mem_zero(s.ptr, s.len); } +FI_ void slice_zero_(Slice s) { slice_assert(s); mem_zero(u4_(s.ptr), S_slice(s)); } #define slice_zero(s) slice_zero_(slice_to_ut(s)) FI_ void slice_copy_(Slice dest, Slice src) { - assert(dest.len >= src.len); + assert(S_slice(dest) >= S_slice(src)); slice_assert(dest); slice_assert(src); - mem_copy(dest.ptr, src.ptr, src.len); + mem_copy(u4_(dest.ptr), u4_(src.ptr), S_slice(src)); } #define slice_copy(dest, src) do { \ static_assert(T_same(dest, src)); \ @@ -98,8 +98,8 @@ typedef Slice_(U4); typedef Opt_(farena) { U4 alignment, type_width; }; typedef Struct_(FArena) { U4 start, capacity, used; }; FI_ void farena_init(FArena_R arena, Slice mem) { assert(arena != nullptr); - arena->start = mem.ptr; - arena->capacity = mem.len; + arena->start = u4_(mem.ptr); + arena->capacity = S_slice(mem); /* FArena.used is in BYTES; capacity must be bytes too */ arena->used = 0; } FI_ FArena farena_make(Slice mem) { FArena a; farena_init(& a, mem); return a; } @@ -109,7 +109,7 @@ I_ Slice farena_push(FArena_R arena, U4 amount, Opt_farena o) { U4 to_commit = align_pow2(desired, o.alignment ? o.alignment : MEM_ALIGNMENT_DEFAULT); U4 ptr = arena->start + arena->used; mem_bump(arena->start, arena->capacity, & arena->used, to_commit); - return (Slice){ ptr, to_commit }; + return (Slice){ (B1*)ptr, to_commit }; } FI_ void farena_reset (FArena_R arena) { arena->used = 0; } FI_ void farena_rewind(FArena_R arena, U4 save_point) { diff --git a/code/hello_camera/hello_camera.c b/code/hello_camera/hello_camera.c index 8dfd960..cccef02 100644 --- a/code/hello_camera/hello_camera.c +++ b/code/hello_camera/hello_camera.c @@ -351,17 +351,38 @@ void update(PrimitiveArena* pa, U4* ordering_buf) A2_S2 p; //??? S4 flag; //???? - // Camera Look at + // Camera Look at (Tape) + inline C11 fallback — bundle runs, then C11 inlines the look_at. + // Currently: bundle's atom 0 (input_and_sub) runs + C11 does the rest. As bundle atoms + // are incrementally fixed, the corresponding C11 lines get commented out. if (1) - { - camera_look_at_c11(& smem.cam, & smem.cube.pos, & v3s4(0, -fp_one, 0)); - } - // Camera look at (Tape) - if (0) { tb.used = 0; tb_scope_run(& tb) { resolve_look_at(& tb, & smem.cam.look_at, & smem.cam.pos, & smem.cube.pos, & v3s4(0, -fp_one, 0)); } + + // RGA(Lengyel): Build matrix expansion of a rigid transformation. Corresponding motor is not constructed; we write the LA form for GTE. + // Preconditions: eye != target, up_in not collinear with (target - eye). + V3_S4 right, up, forward; + V3_S4 ux, uy, uz; + V3_S4 pos, off; + + forward = smem.cube.pos; sub_v3s4(& forward, smem.cam.pos); // RGA(Lengyel): Affine point - point = zero-weight direction. + normalize_v3s4(& forward, & uz); // RGA(Lengyel): Normalize the direction bulk. Not finite-point unitization. + + cross_v3s4(& uz, & v3s4(0, -fp_one, 0), & right); normalize_v3s4(& right, & ux); // RGA(Lengyel): Complement(Wedge(forward, up_in)) -> right axis. + cross_v3s4(& uz, & ux, & up); normalize_v3s4(& up, & uy); // RGA(Lengyel): Complement(Wedge(forward, right)) -> up axis. + + // RGA(Lengyel): matrix expansion of the world-to-camera rotation (basis rows). + smem.cam.look_at.m[0][0] = ux.x; smem.cam.look_at.m[0][1] = ux.y; smem.cam.look_at.m[0][2] = ux.z; + smem.cam.look_at.m[1][0] = uy.x; smem.cam.look_at.m[1][1] = uy.y; smem.cam.look_at.m[1][2] = uy.z; + smem.cam.look_at.m[2][0] = uz.x; smem.cam.look_at.m[2][1] = uz.y; smem.cam.look_at.m[2][2] = uz.z; + + pos = smem.cam.pos; mul_v3s4(& pos, v3s4(-1,-1,-1)); // RGA(Lengyel): -eye in world coordinates (spatial bulk only; implicit weight is dropped). + + // RGA(Lengyel): R * (-eye) is the full matrix translation column. + // Motor translator would store half this displacement in m.xyz; GTE consumes full column. + mul_m3s2_v3s4(& smem.cam.look_at, & pos, & off); + trans_m3s2( & smem.cam.look_at, & off); } // Draw cube @@ -492,8 +513,7 @@ int main(void) pad_bios_init_start(& smem.pad_raw[0], & smem.pad_raw[1]); /* Pre-build the resolve_look_at bundle atoms into the static arena. */ - // TODO(Ed): Investigate this, its causing a crash! - // resolve__look_at_init(); + resolve_look_at_init(); /* Pinned registers for the GPU init atom. */ register U4* io_base_addr rgcc(R_IO_BaseAddr) = u4_r(IO_BASE_ADDR);