video_core: Only suppress command lists that issue geometry (#2467)

GuessCmdRenderProperties() seeds vp_height and paddr from the current
register state and overwrites them only if the scanned list writes those
registers itself. It already records whether each value actually came from
the list, but ShouldAllowCmdQueueTrigger() ignored those flags, so a list
that merely sets state was classified using the previous pass's viewport.
That is how a colour buffer rebind could be mistaken for a repeat render of
the top screen and dropped.

Track whether the list contains a draw trigger and require it before
suppressing anything. A list that issues no geometry produces no pixels, so
blocking it can never save work; it can only discard state that later lists
depend on. The condition is strictly narrower than before, so this cannot
suppress a list that was previously allowed.

Measured on Ocarina of Time 3D with 3D enabled, the disabler still blocks
4141 lists per run versus 4441 before, retaining its effect. On Luigi's
Mansion 2, one of the titles the RIGHT_EYE_DISABLE hack already disallows,
blocking drops from 4601 to zero, which suggests those entries exist
because of exactly this misclassification.

Also guard both places where a scanned list address is turned into a
pointer. CommandList::Reset() only reinterpret_casts, so an unmapped
address would be dereferenced on the next read. This matters more now that
the scan no longer stops as soon as vp_height and paddr are known and can
therefore follow more nested command buffer jumps.
This commit is contained in:
Davey Hughes authored and GitHub committed 2026-10-23 16:53:00 +02:00
1 parent bcba5234c5
commit c3204e25fb
3 files changed
+19 -8

No files matched your search

+15 -6
View File
@@ -1182,10 +1182,6 @@ void PicaCore::LoadVertices(bool is_indexed) {
}
PicaCore::RenderPropertiesGuess PicaCore::GuessCmdRenderProperties(PAddr list, u32 size) {
// Initialize command list tracking.
const u8* head = memory.GetPhysicalPointer(list);
cmd_list.Reset(list, head, size);
constexpr size_t max_iterations = 0x100;
RenderPropertiesGuess find_info{};
@@ -1193,6 +1189,13 @@ PicaCore::RenderPropertiesGuess PicaCore::GuessCmdRenderProperties(PAddr list, u
find_info.vp_height = regs.internal.rasterizer.viewport_size_y.Value();
find_info.paddr = regs.internal.framebuffer.framebuffer.color_buffer_address.Value() * 8;
// Initialize command list tracking.
const u8* head = memory.GetPhysicalPointer(list);
if (head == nullptr) {
return find_info;
}
cmd_list.Reset(list, head, size);
auto process_write = [this, &find_info](u32 cmd_id, u32 value) {
switch (cmd_id) {
case PICA_REG_INDEX(rasterizer.viewport_size_y):
@@ -1203,6 +1206,10 @@ PicaCore::RenderPropertiesGuess PicaCore::GuessCmdRenderProperties(PAddr list, u
find_info.paddr = value * 8;
find_info.paddr_found = true;
break;
case PICA_REG_INDEX(pipeline.trigger_draw):
case PICA_REG_INDEX(pipeline.trigger_draw_indexed):
find_info.has_draw = true;
break;
[[unlikely]] case PICA_REG_INDEX(pipeline.command_buffer.trigger[0]):
[[unlikely]] case PICA_REG_INDEX(pipeline.command_buffer.trigger[1]): {
const u32 index =
@@ -1210,13 +1217,15 @@ PicaCore::RenderPropertiesGuess PicaCore::GuessCmdRenderProperties(PAddr list, u
const PAddr addr = regs.internal.pipeline.command_buffer.GetPhysicalAddress(index);
const u32 size = regs.internal.pipeline.command_buffer.GetSize(index);
const u8* head = memory.GetPhysicalPointer(addr);
cmd_list.Reset(addr, head, size);
if (head != nullptr) {
cmd_list.Reset(addr, head, size);
}
break;
}
default:
break;
}
return find_info.vp_heigh_found && find_info.paddr_found;
return find_info.vp_heigh_found && find_info.paddr_found && find_info.has_draw;
};
size_t iterations = 0;
+2
View File
@@ -398,6 +398,8 @@ public:
PAddr paddr;
bool vp_heigh_found = false;
bool paddr_found = false;
// Whether the scanned list issues any geometry.
bool has_draw = false;
};
RenderPropertiesGuess GuessCmdRenderProperties(PAddr list, u32 size);
+2 -2
View File
@@ -1,4 +1,4 @@
// Copyright 2024 Azahar Emulator Project
// Copyright 2024-2026 Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the misc/licenses/gplv2.txt file included.
@@ -21,7 +21,7 @@ bool RightEyeDisabler::ShouldAllowCmdQueueTrigger(PAddr addr, u32 size) {
cmd_queue_trigger_happened = true;
auto guess = gpu.impl->pica.GuessCmdRenderProperties(addr, size);
if (guess.vp_height == top_screen_size && !top_screen_blocked) {
if (guess.has_draw && guess.vp_height == top_screen_size && !top_screen_blocked) {
if (top_screen_buf == 0) {
top_screen_buf = guess.paddr;
}