Commit 2ea0085
Add draw Lua bindings + raise static GPU buffer pool sizes (#31)
* Raise static GPU buffer pool sizes (configurable)
Adds two user-configurable pool-size patches applied at DLL attach:
"Pool Sizes" / "Static Vertex Pool (MB)" default 128 (game: 64)
"Pool Sizes" / "Static Index Pool (MB)" default 64 (game: 32)
Both bound via big::config::general->bind(...) so users can tune
them from the H2M config UI. Applied at my_main() time, so changes
require a game restart to take effect.
The patches rewrite the `mov qword [rsp+X], imm32` instructions
that push the pool-size argument in sgg::addShaderEffect (vertex
pool, per shader effect) and sgg::addStaticVertexBuffers (index
pool, single global). Writing the full imm32 (not just the high
byte) lets any size up to 2 GB be set from config; the operand is
sign-extended to 64 bits by the mov.
Both pools live in the DX12 upload heap (system RAM, not VRAM), so
the extra capacity costs system memory only. Default values were
picked to be generous without being wasteful; users with many mods
installed can raise further in the UI.
Each patch logs [OK ] or [SKIP] at attach with the reason:
SKIP if the configured value matches the game default (no-op)
SKIP if the configured value is below the game default (refused)
SKIP if the scan pattern didn't match (game update?)
SKIP if the expected imm32 isn't at the site (game update?)
OK on successful write, with from->to MB shown
This surfaces post-game-update regressions immediately instead of
letting mods silently degrade.
Without these patches, mods that add many character mesh entries
overflow the default budgets and later-loaded meshes (weapons,
enemies) fall back to the placeholder "blank mesh" prop.
* Add draw-path hooks + rom.data.set_draw_visible + rom.data.dump_pool_stats
Creates src/lua_extensions/bindings/hades/draw.cpp under the
lua::hades::draw namespace. The file holds:
- Detour hooks on DoDraw3D / DoDrawShadow3D / DoDraw3DThumbnail
(all three share the PDB signature `static void(const
vector<RenderMesh*>&, uint, int, HashGuid)`).
- A code cave for DoDrawShadowCast3D (different signature, no
HashGuid parameter). All four hooks check a shared hidden-set
and skip the draw iteration when the entry's name hash is in it.
- SEH-protected pointer-read helpers used by later bindings that
walk the game's mModelData hash-bucket structure.
New Lua bindings:
rom.data.set_draw_visible(entry_name, visible)
Entry-level visibility gate. Instant toggle, no mModelData
mutation. State: one static std::unordered_set<uint32_t>
guarded by a single std::shared_mutex.
rom.data.dump_pool_stats()
Diagnostic companion to the static-pool-size patches from the
previous commit. Walks sgg::gStaticDrawBuffers + the single
sgg::gStaticIndexBuffers and logs each pool's cursor and
capacity, plus an estimated %-used at 40 B/vert (the character-
mesh stride).
* Add rom.data.set_mesh_visible — per-mesh visibility inside an entry
set_draw_visible (previous commit) hides an entire entry — useful
for whole-character toggles but too coarse when a mod merged a new
mesh into a stock entry and wants to hide just that one mesh
without hiding the body.
set_mesh_visible walks the entry's GrannyMeshData vector, finds
the target mesh by name hash, and flips its mesh_type byte
(GMD+0x4C) between its original value and 2 (shadow). DoDraw3D's
per-mesh switch treats type 2 as "skip to next iteration", so no
cmdDrawIndexed fires for that mesh while other meshes in the same
entry continue to render.
The binding saves the original mesh_type on first hide so a later
show-call can restore the precise value rather than blindly
writing 0 (some meshes ship with type=1 for outline, etc.). The
saved state lives in a function-scope std::map keyed by
(entry_hash, mesh_hash, mesh_index) guarded by its own mutex.
* Add variant-switching Lua APIs: swap_to_variant, restore_stock, populate_entry_textures
Extends draw.cpp with three bindings that redirect a stock entry's
draw calls to a variant entry — outfit switching without reload.
rom.data.swap_to_variant(stock_entry, variant_entry)
Pre-populates the variant's texture handles via
sgg::GameAssetManager::GetTexture (mirrors what
ModelAnimation::PrepDraw does for the stock entry) then installs
a hash remap so hook_DoDraw3D reads the variant's
GrannyMeshData whenever a draw command queues the stock entry.
rom.data.restore_stock(stock_entry)
Removes the remap entry for the stock hash.
rom.data.populate_entry_textures(entry_name)
Standalone version of the texture pre-populate step, for
callers who want to resolve an entry's textures without
installing a remap (e.g. warming up variants at startup).
State: one std::unordered_map<uint32_t, uint32_t> guarded by the
file's shared mutex. hook_DoDraw3D learns to consult this map
before the hidden-set check and rewrite the draw command's hash
in-place when a remap exists; the hash is read under a shared
lock and the map is written under unique lock. check_draw_entry
(used by the shadow-cast code cave) gains a matching remap branch
and now returns 2 + *out_hash to the cave when a remap applies.
Shadow and thumbnail paths continue to honour only the hidden-set
— remapping them while ShadowCast stays on stock (its signature
has no HashGuid, so it can't participate cleanly) produces
inconsistent per-entry state that wedges the render thread. The
main DoDraw3D swap carries the visual change on its own.
Header doc comment extended to list the new bindings.
* Review pass: structs, shared helpers, draw_ prefix, cleanups
Addresses the review feedback on PR #31 in one commit.
Game structs with static_assert offsets
---------------------------------------
- ModelDataHashTable / ModelDataNode / GrannyMeshData: partial layouts
covering exactly the fields we touch; unnamed regions stay `char
pad[]` so sizeof + offsetof match the engine.
- ForgeBuffer / ForgeGeometryBuffers / EastlVector<T>: same treatment
for draw_dump_pool_stats' ForgeRenderer reads.
- Every scattered `mdata + 0x08` / `node + 0x10` / `gmd + 0x4C`
style read is now struct field access.
Shared hashtable walker
-----------------------
- `find_model_data_node(entry_hash)` replaces the EASTL mix + bucket
walk that populate_entry_textures, set_mesh_visible, and
swap_to_variant each inlined separately.
- `get_entry_meshes(node, ...)` factors out the vector-range resolve.
- Named the mixing constants (kEastlHashMix1/2) and annotated the
multiply-xor-shift finalizer pattern they come from.
- `0x50` is now `sizeof(GrannyMeshData)`, the `0x7feb352d` /
`0x846ca68b` and `128` / `32` / `0x100000` bounds are named.
LUA_DOC blocks
--------------
- Trimmed engine-internal prose out of every binding's LUA_DOC block
(set_mesh_visible's GMD hash flip, swap_to_variant's PrepDraw
reasoning, populate_entry_textures' walk explanation,
dump_pool_stats' +0x38 / +0x40 layout). The RE notes live inline
in the function body where they matter.
- Dropped the top-of-file @file doxygen block entirely. If a
binding ever needs a "why this exists" comment it goes right
above that binding.
Type-safe return
----------------
- check_draw_entry now returns `enum class DrawEntryDecision : int
{ PassThrough = 0, Hidden = 1, Remapped = 2 }`. Backing type and
numeric values are preserved because the manual code cave compares
the returned eax against 1 and 2 directly.
Lua naming
----------
- All new rom.data.* draw bindings prefixed with draw_:
set_draw_visible -> draw_set_visible
set_mesh_visible -> draw_set_mesh_visible
swap_to_variant -> draw_swap_to_variant
restore_stock -> draw_restore_stock
populate_entry_textures -> draw_populate_entry_textures
dump_pool_stats -> draw_dump_pool_stats
User-facing messages
--------------------
- draw_set_visible's "hash=0" warning now names the two concrete
causes (engine hash table not yet populated, or the entry name
isn't registered) and tells the user what to do.
- draw_set_visible's LUA_DOC one-liner trimmed to "Takes effect
immediately." per reviewer preference.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: enderclem <enderclem@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 26512ed commit 2ea0085
5 files changed
Lines changed: 914 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
0 commit comments