<feed xmlns='http://www.w3.org/2005/Atom'>
<title>eglantine-cirakg/src/video_core/macro.cpp, branch nx2</title>
<subtitle>Mirror of github.com/cira0100/Eglantine-public nx2, a fork of Djihads80/Eglantine.</subtitle>
<id>https://git.cirakg.xyz/eglantine-cirakg/atom?h=nx2</id>
<link rel='self' href='https://git.cirakg.xyz/eglantine-cirakg/atom?h=nx2'/>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/'/>
<updated>2026-10-30T00:49:48+00:00</updated>
<entry>
<title>nx2: profile engine method calls and semaphore acquires; notes 140-141</title>
<updated>2026-10-30T00:49:48+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-29T13:45:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=24d3a1dbb3f2bb6dc5b8a515c1be1f7bad956b4b'/>
<id>urn:sha1:24d3a1dbb3f2bb6dc5b8a515c1be1f7bad956b4b</id>
<content type='text'>
EDEN_NX2_GPU_PROFILE now times engine method calls (the work a split GPU thread's back half
would run) and counts semaphore acquires and those that wait. Title 1: method calls ~343 ms
a second (6.9 million), front-half work (command parsing, macros) ~333 ms, acquires ~2,700 a
second of which ~220 wait. Notes 140 (macro compiler) and 141 (draw setup).
</content>
</entry>
<entry>
<title>video_core: compile Turing MME macro code to x86-64</title>
<updated>2026-10-30T00:49:48+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-29T13:39:25+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=c0643a675b1382cfa7357626a63a623b56a72666'/>
<id>urn:sha1:c0643a675b1382cfa7357626a63a623b56a72666</id>
<content type='text'>
Title 1 calls macros ~1.3 million times a second; most were replayed from the macro memo,
whose lookups missed the CPU caches inside the GPU thread (~8%), and the rest interpreted.
macro_turing_jit.h compiles all of the uploaded macro memory with Xbyak: each instruction a
block falling through to the next, branches and loops through a jump table, with the
interpreter's semantics (lanes reading operands before either writes, predication as two
variants, the END delay slot, loops, carry). Loop checks only where a loop can end, END
checks only after an END, the instruction limit counted on indirect jumps. Emits and register
reads call back into C++. It is recompiled when the macro code changes and used for 3D and
compute macros on x86-64; EDEN_NX2_MME_JIT=0 goes back to the memo and the interpreter.

Checked against the interpreter on 200,000 recorded calls (registers, data RAM, every
method write, FIFO use): identical. In the game: macro calls 148 ns instead of 174 (two
profiled runs each), no failures, 0 crashes in 3 runs. NX2_GPU_THREAD_SPLIT.md describes
the next step, splitting the GPU thread.
</content>
</entry>
<entry>
<title>video_core: compact the macro memo arena; download profiling counters</title>
<updated>2026-10-30T00:49:47+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-29T09:46:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=b905580202f0da5ca0a6268b176b4591e347fd8d'/>
<id>urn:sha1:b905580202f0da5ca0a6268b176b4591e347fd8d</id>
<content type='text'>
Calls stored again with another shape leave their old record in the memo's arena;
title 1 filled its 16 MiB every ~2 s and clearing it made the next ~20,000 calls
interpret again. The live records are now copied to a new arena (a clear only when
they alone fill three quarters of it). The memo statistics count hits on the last
call's slot and compactions. With EDEN_NX2_GPU_PROFILE the GPU thread also reports
how much downloaded buffer data lands on pages the native MME has DMA-read.
</content>
</entry>
<entry>
<title>nx2: macro memo tries each macro's last call first; FIFO filled only when interpreting</title>
<updated>2026-10-29T06:15:53+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-29T06:15:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=e8127c3759ae260bfae09e3a3a74853204bcd1ee'/>
<id>urn:sha1:e8127c3759ae260bfae09e3a3a74853204bcd1ee</id>
<content type='text'>
46% of title 1's macro calls repeat the previous call of the same
macro exactly: a per-start slot holding that record's offset skips the
hash and the map probe for them (the record is still in the CPU cache).
The interpreter's parameter FIFO was filled before the memo lookup; it
is now filled only for calls that are interpreted.

Checked against the previous interpreter on 200,000 recorded 3D-scene
calls: identical writes, registers and data RAM.
</content>
</entry>
<entry>
<title>nx2: macro memo hashes its keys as they are, rewrites re-stored calls in place</title>
<updated>2026-10-29T04:37:06+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-29T04:37:06+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=322a5afce3d6c5fbcf16ed9a8914805087b33a55'/>
<id>urn:sha1:322a5afce3d6c5fbcf16ed9a8914805087b33a55</id>
<content type='text'>
The flat map re-hashed the already mixed u64 keys with MSVC's byte-wise
FNV-1a (~1.4% of the GPU thread), and calls stored again after a data
RAM guard failed appended new records, so the arena filled with stale
copies and was cleared every few seconds. EDEN_NX2_MME_MEMO_STATS logs
the counters: in title 1, 97.3% of calls replay, 2.1% fail a guard.
</content>
</entry>
<entry>
<title>nx2: replay repeated native macro calls instead of interpreting them</title>
<updated>2026-10-29T04:27:35+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-29T04:27:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=863d3afa90f2dfde8e715b45f28fc75c1b472739'/>
<id>urn:sha1:863d3afa90f2dfde8e715b45f28fc75c1b472739</id>
<content type='text'>
Title 1 makes ~1,000,000 native macro calls a second in 3D scenes, 7
instructions each on average, and 96% repeat an earlier call exactly.
A call whose effects depend only on its start, its parameters and the
data RAM words it read (no MME_READ, no memory reads, no re-read of
its own data RAM writes, no code upload while it ran) is remembered
with those reads as guards; a later call with the same start and
parameters whose guards still hold replays its data RAM and method
writes. Uploading macro code clears the memo. EDEN_NX2_MME_MEMO=0
interprets every call.

Checked offline against the previous interpreter on 200,000 recorded
3D-scene calls (method writes, registers and data RAM all identical,
94% replayed, 1.9x faster); in the game the macro zone fell from ~0.26
to ~0.20 us per call.
</content>
</entry>
<entry>
<title>nx2: EDEN_NX2_MME_RECORD records macro calls for offline interpreter checks</title>
<updated>2026-10-29T03:46:54+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-29T03:46:54+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=0f99a77250d089d5ee9afe011564c71866c2dadd'/>
<id>urn:sha1:0f99a77250d089d5ee9afe011564c71866c2dadd</id>
<content type='text'>
Writes the first 200,000 native macro calls (start, parameters) and the
macro code, so an interpreter change can be replayed against the
previous interpreter (all 200,000 matched for the operand-slot rewrite,
which was then dropped as no faster).
</content>
</entry>
<entry>
<title>nx2: measure the TSC on AMD, no rethrows for rejected shaders, debug hooks off the hot path</title>
<updated>2026-10-29T03:07:49+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-29T03:07:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=25b674eabdb92212a6d8149d6616b2af59317695'/>
<id>urn:sha1:25b674eabdb92212a6d8149d6616b2af59317695</id>
<content type='text'>
- AMD CPUs have no CPUID leaf 0x15, so the TSC frequency stayed 0 and
  every guest CNTPCT read went through QueryPerformanceCounter (~10% of
  the game's main core in title 1). Measure it like Intel CPUs without
  a crystal frequency.
- A rejected native shader was rethrown (two C++ throws) every time it
  was bound; return false instead (~1-2% of the GPU thread).
- The semaphore watch, pushbuffer entry hashing, first-write trace and
  per-macro debug logs ran on every command word or macro call; they
  now cost a flag check unless their environment variable is set
  (~4% of the GPU thread). Also starts the macro engine's profile zone.
</content>
</entry>
<entry>
<title>Native MME: decode each instruction once; reuse the parameter FIFO</title>
<updated>2026-10-29T00:43:00+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-29T00:43:00+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=e4deef6ba4ea76aac997ed3102f8e9801fd170b9'/>
<id>urn:sha1:e4deef6ba4ea76aac997ed3102f8e9801fd170b9</id>
<content type='text'>
The Turing macro interpreter re-extracted every field of each 96-bit
instruction on every execution and copied the register file per
instruction; title 1's GPU thread spent about half its busy time there.
Instructions are now decoded once per PC (re-decoded when their words
change) and both lanes' operands are read up front instead of copying
the registers. The parameter FIFO is a member instead of a vector
allocated per macro call. Rendering checked unchanged on the attract
loop; the GPU thread went from ~68% to ~45-50% busy.
</content>
</entry>
<entry>
<title>Performance diagnostics and small wins for title 1</title>
<updated>2026-10-28T20:44:24+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-28T20:44:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=cc3d73762a41dba370aadd3468cb510dcbc2b74d'/>
<id>urn:sha1:cc3d73762a41dba370aadd3468cb510dcbc2b74d</id>
<content type='text'>
- eden-cli: SDL called SDL_AppIterate back to back, keeping a host core at
  100% polling input; run the main callbacks at 240 Hz.
- EDEN_NX2_IDLE_SPIN_US: optional spin before an idle core blocks (measured:
  no gain on title 1, so off by default).
- EDEN_NX2_SVC_TRACE=&lt;first&gt;:&lt;last&gt;: trace SVCs (with thread ids) for a range
  of presents only.
- MME DMA reads flush GPU-written memory first (never triggered on title 1,
  kept for correctness); render-enable override histogram instead of the
  first-400 log.

Measured on title 1's title screen (RTX 4070 Laptop): GPU ~20% busy, the six
emulated cores ~0.9 host cores in total, Eden's GPU thread 45-70% busy and
largely waiting: on host fences for semaphore acquires (GPU accuracy High
delays every release to host completion), on ASTC upload Finish(), and in a
1 ms poll sleep. gpu_accuracy=Low: ~12.5 -&gt; ~16 fps.
</content>
</entry>
</feed>
