Skip to content

Claude/merge master resolve conflicts f98 ty#78

Closed
jmquigs wants to merge 2 commits into
masterfrom
claude/merge-master-resolve-conflicts-f98TY
Closed

Claude/merge master resolve conflicts f98 ty#78
jmquigs wants to merge 2 commits into
masterfrom
claude/merge-master-resolve-conflicts-f98TY

Conversation

@jmquigs
Copy link
Copy Markdown
Owner

@jmquigs jmquigs commented May 13, 2026

No description provided.

claude added 2 commits May 7, 2026 22:40
Continues removing static muts. DEVICE_STATE was a `*mut DeviceState`
guarded by a separate marker `RwLock<()>` (DEVICE_STATE_LOCK), which
was used inconsistently and often skipped entirely. This collapses the
two into a single `RwLock<DeviceStatePtr>`, where DeviceStatePtr is a
Send/Sync wrapper around the raw pointer, so every read/write goes
through the same lock.

API changes in the device_state crate:
- `dev_state()` and `dev_state_d3d11_nolock()` are gone. Both used to
  hand out a `&'static mut`, which can't be reconciled with a guard
  lifetime, so every call site was migrated.
- `dev_state_write()` / `dev_state_read()` return `Option<(guard,
  &/&mut DeviceState)>`.
- `dev_state_d3d11_write()` and `dev_state_d3d11_read()` keep their
  shape, but `_read` now returns `&` instead of `&mut` (the previous
  `_read` was unsound).
- All accessors fail safely on lock poisoning by logging and returning
  None rather than panicking, so a poison can't take the game down.

Re-entrancy: `std::sync::RwLock` is not reentrant, so several call
sites had to be reworked to drop the guard before invoking real D3D
fns (which can re-enter our hooks on the same thread). Notably:

- D3D9 `hook_present`, `hook_release`, `hook_set_texture`,
  `hook_set_stream_source`, `hook_reset`, `hook_draw_indexed_primitive`,
  `hook_create_device`, `hook_CreateTexture`, `hook_UpdateTexture`,
  and `create_d3d9` now extract the real fn pointer under a brief
  read guard, drop the guard, then invoke. The release path also
  threads `ref_count` updates through scoped write guards.
- `HookDirect3D11Context` and friends now derive Copy so
  `get_hook_context` returns a copy and callers don't need to hold
  the dev_state lock to invoke the real fn pointers.
- DX11 `hook_draw_indexed` was restructured so dev_state guards are
  acquired only briefly: the geom check / vb_state snapshot under a
  read guard, mod work outside any guard, and metrics under a final
  write guard. `ensure_vb_checksum_dx11`, `hook_snapshot::take`, and
  `with_dev_ptr` are no longer called with the lock held.
- `init_device_state_once` now mutates the pointer through the write
  guard rather than via static mut. Tests serialize on a separate
  `TEST_DEV_STATE_LOCK` because the new init path takes the dev_state
  write lock internally.
The conflict was between this branch's RwLock-based dev_state access
pattern and master's new "needs refill for layout" mod reload logic
(#77). Resolution preserves the RwLock pattern (lock acquired/dropped
in narrow scopes) while integrating the refill logic: we precompute
the current input layout's semantic mask via a brief read lock before
calling check_and_render_mod, then pass scalars into the closure so it
no longer needs the dev_state lock.

needs_refill_for_layout was refactored to accept an Option<SemanticMask>
instead of taking a reference to the layouts hashmap, so callers can
look up the mask once under their read guard rather than holding the
lock across the closure.

The post_mod_check NotRenderedButLoadRequested arm now also calls
mod_load::reset_for_reload from master, while keeping the rwlock
pattern of reading current_input_layout via a brief dev_state guard
before taking the LOADED_MODS lock.
@jmquigs jmquigs closed this May 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants