arkavo-org / arkavo-org/VRMMetalKit
Model lock serializes animation threads during full render encode
- Dominant language
- Swift
- Stars
- 6
- Forks
- 2
- Avg merge
- 18h 51m
- Merged PRs (30d)
- 26
Description
## Summary
`drawCore()` acquires `model.lock` at entry and holds it for the entire function duration (~lines 1230–3557 in `VRMRenderer.swift`) via `defer { model.lock.unlock() }`.
## Impact
If skinning, morph compute, or spring-bone physics is expensive, background animation threads (e.g. `AnimationPlayer`) stall until the render encoder finishes. This serializes CPU work that could otherwise run in parallel.
## Location
- `Sources/VRMMetalKit/Renderer/VRMRenderer.swift:1230`
- `Sources/VRMMetalKit/Renderer/VRMRenderer.swift:3557`
## Evidence
```swift
model.lock.lock()
defer { model.lock.unlock() }
// ... entire drawCore: morph compute, spring bone, skinning, render loop ...
```
## Suggested Fix
Shrink the critical section to only the data that must be coherent between animation and rendering:
1. Snapshot node transforms under the lock.
2. Release the lock.
3. Perform all encoding work lock-free using the snapshot.
## Related
- Triple-buffered uniforms already prevent GPU race conditions.
- `skipPreDrawTransformUpdate` exists but does not address the lock scope.
Contributor guide
Research direction
Read Sources/VRMMetalKit/Renderer/VRMRenderer.swift around drawCore() at lines 1230–3557, including the model.lock scope and skipPreDrawTransformUpdate. Identify which transform data must be snapshotted before encoding and verify that animation threads no longer wait for the full render encode while coherent render data and triple-buffered uniforms remain intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- computer-graphics, performance
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100