aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/native_qmd.h
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 00:24:14 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 00:24:14 -0400
commita5e528e2d0bc784ebf24850e5913cece912c685e (patch)
tree8a0323e46528f768dc9fd0b0843419be2892de95 /src/video_core/native_qmd.h
parentf8c8b809e64c57d34837b09cce3b6a7fd8e5295a (diff)
nx2: get title 4 past the difficulty confirm
- MME: implement MME_DMA_READ / MME_DMA_READ_FIFOED (Turing macros read query results into their load FIFO; the conditional-render macro at 0x142 needs it). - vi2 present waits up to 4 s for the frame fence (was 250 ms) so shader compile stalls don't let the game lap its equal-value gate semaphores. - Native QMD: fire the third release slot at word 52, which NVN2 patches for queue-to-queue syncs (compute queue releasing a gate the 3D queue waits on). - Compute class SET_REPORT_SEMAPHORE (0x6c0-0x6c3) releases. - Ampere lowering: AOFFI, any LOP3 truth table, STG RZ, LDG 0x981, IABS, I2FP rounding, IMAD negated addend, SHFL 0x989 (all 77 title-4 shaders lower). - Debug: EDEN_NX2_SEM_WATCH=<addr> traces acquires, releases, method arguments and compute macro emits for one semaphore block; EDEN_NX2_KEY_SCRIPT scripted key presses; per-submit logs moved to TRACE.
Diffstat (limited to 'src/video_core/native_qmd.h')
-rw-r--r--src/video_core/native_qmd.h20
1 files changed, 12 insertions, 8 deletions
diff --git a/src/video_core/native_qmd.h b/src/video_core/native_qmd.h
index c9ae3b8cc0..c06f14e6b2 100644
--- a/src/video_core/native_qmd.h
+++ b/src/video_core/native_qmd.h
@@ -61,9 +61,9 @@ public:
if (!read(request.address, state.descriptor)) return "unmapped QMD";
const auto qmd = state.descriptor;
if ((qmd[18] & 0xff) != 0x30 || (qmd[4] & 0x100)) return "unsupported QMD version or queue";
- // Validate both release slots before making either visible.
- for (Word slot = 0; slot < 2; ++slot) {
- const Word flags = qmd[25 + slot * 4];
+ // Validate the release slots before making any visible.
+ for (const Word base : ReleaseSlots) {
+ const Word flags = qmd[base + 1];
if (!(flags & (1U << 23))) continue;
const bool add = (flags & (1U << 26)) != 0;
if ((flags & (0x3bU << 24)) || (flags >> 30) != 1 ||
@@ -76,15 +76,15 @@ public:
if (qmd[12] && (qmd[13] & 0xffff) && (qmd[14] & 0xffff) && !dispatch(qmd))
return "native shader dispatch required";
state.completed = true;
- for (Word slot = 0; slot < 2; ++slot) {
- const Word flags = qmd[25 + slot * 4];
+ for (const Word base : ReleaseSlots) {
+ const Word flags = qmd[base + 1];
if (!(flags & (1U << 23))) continue;
- const Address destination = (Address{flags & 0xff} << 32) | qmd[24 + slot * 4];
+ const Address destination = (Address{flags & 0xff} << 32) | qmd[base];
bool released{};
if constexpr (std::is_invocable_r_v<bool, Release, Address, Word, Word>) {
- released = release(destination, qmd[26 + slot * 4], flags);
+ released = release(destination, qmd[base + 2], flags);
} else {
- released = release(destination, qmd[26 + slot * 4]);
+ released = release(destination, qmd[base + 2]);
}
if (!released) return "unmapped QMD release";
}
@@ -99,6 +99,10 @@ public:
return {};
}
private:
+ // Release slots (address low, flags | address high, payload). NVN2 patches a third one at
+ // word 52 for queue syncs (e.g. a compute queue releasing a semaphore another queue waits on).
+ static constexpr std::array<Word, 3> ReleaseSlots{24, 28, 52};
+
struct State {
Descriptor descriptor{};
std::int32_t dependencies{};