Vulkan: write-back page map hashed by the page number itself #908

Merged
klimovich008 merged 1 commit from perf-identity-hash-wb-pages into main 2026-11-09 08:47:09 +00:00
klimovich008 commented 2026-11-09 01:10:39 +00:00 (Migrated from github.com)

What

The write-back page map wb_pages (gpu/vk/vk_memory.cpp, uint32_t page → value) now uses Common::FastHash<uint32_t>, which is already in gpu/vk/compat/common/container_hash.h. That hashes a page number by its own value. This is a one-line declaration change plus an include.

Why

On Windows (MSVC's STL), std::hash<uint32_t> is a byte-wise FNV-1a. It scatters the run of neighbouring pages that one wb_pages_note call writes across the whole bucket array, so every page is a cache miss on its bucket and node. With identity hashing, neighbouring pages land in neighbouring buckets. container_hash.h gives the same reason for the GPU thread's other page maps.

On a profile of Hyrule Field with the camera rotating (v2.0.2, RX 9070 XT, Ryzen 7 5700X3D), wb_pages_note and its lookups are 3.2% of the Presentation (render) thread, matched against the inlined FNV sites in hookshot_vk.dll.

On Linux (libstdc++) and llvm-mingw (libc++), std::hash of an integer is already the identity, so nothing changes there.

Testing

  • R-stub of the real code. wb_pages_note and memory_writeback_value were extracted from source and driven with the profile's patterns. ns per page, median of 5:

    workload FNV (today) FastHash
    note, steady 100k pages 34.5 20.7 (−40%)
    note, map growing to ~190k pages 79.0 49.9 (−37%)
    lookup (memory_writeback_value) 31.1 23.4 (−25%)
  • Identical results. Every lookup answer and the final map contents, including the prune pass, are byte-identical across 43 million answers. That includes a run with a hash that always returns 0, so equality still compares the full key.

  • Expected gain: about 1.2–1.5% of the render thread on Windows.

  • Game A/B. This change was part of a batch: v2.0.3 plus this, three lifter-side changes and a renderer-only change. Against stock v2.0.3, median of 3 runs each, with equally warm pipeline caches, Hyrule Field rotating went from 69.7 to 68.0 CPU ms per frame. fps, p99 and frames over 50 ms showed no regression. The game A/B did not isolate this change.

  • Compile. vk_memory.cpp compiles on current main with the renderer's flags.

Not done: a separate A/B of this change alone, and a run on Linux (no change is expected there).

The same identity hash could also go on the texture_answer slot cache in vk_shader.cpp (~1% of the render thread). I left it out because vk_shader.cpp feeds the shader-cache stamp, so changing it would invalidate everyone's prepared shaders once.

🤖 Generated with Claude Code

## What The write-back page map `wb_pages` (`gpu/vk/vk_memory.cpp`, `uint32_t` page → value) now uses `Common::FastHash<uint32_t>`, which is already in `gpu/vk/compat/common/container_hash.h`. That hashes a page number by its own value. This is a one-line declaration change plus an include. ## Why On Windows (MSVC's STL), `std::hash<uint32_t>` is a byte-wise FNV-1a. It scatters the run of neighbouring pages that one `wb_pages_note` call writes across the whole bucket array, so every page is a cache miss on its bucket and node. With identity hashing, neighbouring pages land in neighbouring buckets. `container_hash.h` gives the same reason for the GPU thread's other page maps. On a profile of Hyrule Field with the camera rotating (v2.0.2, RX 9070 XT, Ryzen 7 5700X3D), `wb_pages_note` and its lookups are **3.2% of the Presentation (render) thread**, matched against the inlined FNV sites in `hookshot_vk.dll`. On Linux (libstdc++) and llvm-mingw (libc++), `std::hash` of an integer is already the identity, so nothing changes there. ## Testing - **R-stub of the real code.** `wb_pages_note` and `memory_writeback_value` were extracted from source and driven with the profile's patterns. ns per page, median of 5: | workload | FNV (today) | FastHash | |---|---|---| | note, steady 100k pages | 34.5 | 20.7 (−40%) | | note, map growing to ~190k pages | 79.0 | 49.9 (−37%) | | lookup (`memory_writeback_value`) | 31.1 | 23.4 (−25%) | - **Identical results.** Every lookup answer and the final map contents, including the prune pass, are byte-identical across 43 million answers. That includes a run with a hash that always returns 0, so equality still compares the full key. - **Expected gain:** about 1.2–1.5% of the render thread on Windows. - **Game A/B.** This change was part of a batch: v2.0.3 plus this, three lifter-side changes and a renderer-only change. Against stock v2.0.3, median of 3 runs each, with equally warm pipeline caches, Hyrule Field rotating went from 69.7 to 68.0 CPU ms per frame. fps, p99 and frames over 50 ms showed no regression. The game A/B did not isolate this change. - **Compile.** `vk_memory.cpp` compiles on current `main` with the renderer's flags. Not done: a separate A/B of this change alone, and a run on Linux (no change is expected there). The same identity hash could also go on the `texture_answer` slot cache in `vk_shader.cpp` (~1% of the render thread). I left it out because `vk_shader.cpp` feeds the shader-cache stamp, so changing it would invalidate everyone's prepared shaders once. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Commenting is not possible because the repository is archived.
No description provided.