Game: on Vulkan the game's occlusion culling never culls (every samples-passed count reads 4096) #122

Open
opened 2026-11-13 05:26:31 +00:00 by dyst · 0 comments
Member

Longshot version

Measured on Hookshot main 51da0464 (11 November 2026), whose renderer code Longshot carries unchanged here. The fix
is Longshot pull request 23 (WIP, opt-in).

What kind of problem

Low fps or stutter: GPU work the game means to skip

What happened

On the Vulkan renderer every samples-passed counter report reads 4096 (RX_VK_OCC_FIXED, since
NotRexed/Hookshot#487, which fixed a one-frame sun flicker). Ocarina of
Time uses those counts for its occlusion culling, so it never culls anything hidden behind something:

  • Its z-prepass draws each object between a samples-passed reset and a report into that object's slot.
  • It reads the counts back on the CPU a frame or two later and leaves out of its draw lists the objects whose count
    was 0. A dumped gameplay frame in Kokiri Forest has 491 such reports and no conditional rendering at all, so the counts
    only have to reach guest memory in time; no VK_EXT_conditional_rendering is needed.

Measured in Kokiri Forest (first save, standing still about 100 s after loading; headless; RTX 3080; 200 s per run, back
to back on a quiet machine):

Reports read Draws a frame GPU time a frame Frame rate Picture
4096 (today) ~1,570 ~11.5 ms 26-28 fps normal
0 (RX_VK_OCC_FIXED=0: the ceiling) ~1,010 ~7.5 ms ~30 fps nearly everything gone
the GPU's real counts (PR 23, RX_VK_OCC_QUERIES=1) ~1,330 ~11.0 ms 27.5-29 fps same as today

With real counts about 32% of the reports read 0, and each count reached the game's slot about one recording (a sixth
of a frame) after its report, well inside the frame or two the game waits. Until a count lands the slot keeps today's
4096, so a late count costs culling, never a missing object.

The Occlusion Off switch (no queries at all) gives the same picture, GPU time and frame rate as today on Vulkan, as
expected: nothing was culled before either.

Where in the game

Everywhere the game culls by occlusion. The gain grows with what is hidden: indoors, behind terrain, in dungeons.

How often

Always, on the Vulkan renderer (the default).

Graphics card and driver version

NVIDIA GeForce RTX 3080, driver 621.14

CPU, RAM and operating system

Windows 11

Changes from the defaults

Test runs with scripts/run-vk.ps1 (headless, scene at 1920x864).

Wanted

  • Runs of PR 23 with RX_VK_OCC_QUERIES=1 RX_VK_OCC_LOG=1 on AMD (RX 6000-9000), a Steam Deck and an integrated GPU,
    before it could be on by default: the log line reports how many counts were written, how many read 0, and how late.
  • A run with the camera turning and one indoors, to look for pop-in (an object coming out from behind cover is drawn
    again once its count says so).
  • The sun: with real counts its haze may now behave as on the Switch when it is hidden; worth a look in a cave or with
    the sun behind a mountain.
### Longshot version Measured on Hookshot `main` 51da0464 (11 November 2026), whose renderer code Longshot carries unchanged here. The fix is [Longshot pull request 23](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/23) (WIP, opt-in). ### What kind of problem Low fps or stutter: GPU work the game means to skip ### What happened On the Vulkan renderer every samples-passed counter report reads **4096** (`RX_VK_OCC_FIXED`, since [NotRexed/Hookshot#487](https://github.com/NotRexed/Hookshot/pull/487), which fixed a one-frame sun flicker). Ocarina of Time uses those counts for its occlusion culling, so **it never culls anything hidden behind something**: - Its z-prepass draws each object between a samples-passed reset and a report into that object's slot. - It reads the counts back **on the CPU a frame or two later** and leaves out of its draw lists the objects whose count was 0. A dumped gameplay frame in Kokiri Forest has 491 such reports and no conditional rendering at all, so the counts only have to reach guest memory in time; no `VK_EXT_conditional_rendering` is needed. Measured in Kokiri Forest (first save, standing still about 100 s after loading; headless; RTX 3080; 200 s per run, back to back on a quiet machine): | Reports read | Draws a frame | GPU time a frame | Frame rate | Picture | |---|---|---|---|---| | 4096 (today) | ~1,570 | ~11.5 ms | 26-28 fps | normal | | 0 (`RX_VK_OCC_FIXED=0`: the ceiling) | ~1,010 | ~7.5 ms | ~30 fps | nearly everything gone | | the GPU's real counts (PR 23, `RX_VK_OCC_QUERIES=1`) | ~1,330 | ~11.0 ms | 27.5-29 fps | same as today | With real counts about 32% of the reports read 0, and each count reached the game's slot about one recording (a sixth of a frame) after its report, well inside the frame or two the game waits. Until a count lands the slot keeps today's 4096, so a late count costs culling, never a missing object. The Occlusion Off switch (no queries at all) gives the same picture, GPU time and frame rate as today on Vulkan, as expected: nothing was culled before either. ### Where in the game Everywhere the game culls by occlusion. The gain grows with what is hidden: indoors, behind terrain, in dungeons. ### How often Always, on the Vulkan renderer (the default). ### Graphics card and driver version NVIDIA GeForce RTX 3080, driver 621.14 ### CPU, RAM and operating system Windows 11 ### Changes from the defaults Test runs with `scripts/run-vk.ps1` (headless, scene at 1920x864). ### Wanted - Runs of PR 23 with `RX_VK_OCC_QUERIES=1 RX_VK_OCC_LOG=1` on **AMD (RX 6000-9000), a Steam Deck and an integrated GPU**, before it could be on by default: the log line reports how many counts were written, how many read 0, and how late. - A run with the camera turning and one indoors, to look for pop-in (an object coming out from behind cover is drawn again once its count says so). - The sun: with real counts its haze may now behave as on the Switch when it is hidden; worth a look in a cave or with the sun behind a mountain.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot#122
No description provided.