For reasons I'm not really sure about, I have been unable to use MacGruber's SuperShot with any reliability for a while. VAM would fairly quickly come to a crawl and it would require a whole system restart to fix. This MIGHT be just related to the Oculus VR (OVRServer_x64.exe). If you have no issues with the original, then go with that one. But if you're a Meta/Oculus VR user and take your shots in VR, this update might be of interest. (See Full Technical description of the original issue at bottom of Post)
SuperShot Plugin — Updates & Improvements
Original Issue in Technical Terms for Meta/Oculus Users
When a screenshot was triggered, the original plugin called Texture2D.ReadPixels() to copy the captured image from VRAM to system RAM. For a large render texture — especially at high resolution with MSAA — this is a synchronous operation. The CPU submits the copy command to the GPU and then blocks, waiting for the GPU to finish before execution can continue.
With a texture large enough (8K, high MSAA, or complex shaders like fur adding significant per-pixel cost), the GPU could take well over 2 seconds to complete that single operation. Windows monitors the GPU continuously and if it goes more than 2 seconds without responding — the default TDR timeout — Windows assumes the GPU has hung, forcibly resets the driver, and logs a TDR event.
The Oculus runtime submits its own work to the GPU every frame at 90Hz. When the TDR fired mid-frame, the Oculus compositor was in the middle of compositing a VR frame. The driver reset tore that frame and left the compositor's internal state — its frame timing, its reprojection pipeline, its swapchain synchronization — in an inconsistent condition it couldn't self-recover from.
Since the Oculus service is a separate Windows process that persists independently of VaM, closing and relaunching VaM had no effect. The corrupted state lived in OVRServer_x64.exe. Only a full system reboot, which restarts all services including the Oculus runtime, cleared it.
SuperShot Plugin — Updates & Improvements
- Switched to async GPU readback — pixel data is now transferred from VRAM to RAM in the background over 1–3 frames rather than all at once, keeping the GPU pipeline free during screenshots
- PNG/JPG encoding moved to a background thread — image compression no longer runs on the main thread, keeping VaM's frame loop responsive during saves
- Disk writes moved to a background thread — file saving now runs alongside encoding off the main thread, preventing any frame hitching on large files
- Screenshots now survive scene changes — the entire save pipeline completing on the background thread means files are written even if the plugin is disabled mid-process during a scene transition
- Removed a redundant GPU upload step — pixel data no longer gets re-uploaded to VRAM prior to encoding since encoding only needs the CPU-side copy
- Added duplicate camera hook protection — any existing camera hook is now cleaned up before a new one is added, preventing stacking across plugin reloads
- Controller selection restored after readback — the selected controller is now restored only after the GPU transfer completes, guaranteeing it won't appear in the captured image
- PNG transparency now preserves skin correctly — VaM's skin shader uses the alpha channel internally for lighting calculations; any rendered pixel with visible color is now marked as opaque so skin appears correctly in transparent PNGs while the background remains genuinely see-through
- Added post-shot render time logging — after each screenshot, if the render took over 1 second the plugin logs a warning with advice on which settings to reduce
- Added pre-shot GPU load indicator — the plugin UI now shows a warning line when the combination of resolution, multiplier, and MSAA is likely to be demanding
- Added scene shader scanner — a "Scan Scene for Shader Risk" button (and auto-scan on load) checks every material in the scene for known GPU-intensive shader types such as fur and shell shaders, giving a more informed risk assessment than settings alone
- VR and Desktop modes use separate risk thresholds — in VR the GPU is simultaneously running stereo rendering at 90Hz for the headset, so the warning threshold reflects that reduced headroom; Desktop mode uses a much more lenient threshold since no compositor is competing for GPU time
- Shader warnings are context-aware — fur and shell shaders show a strong warning in VR where compositor contention is a real concern, and a softer advisory in Desktop mode where that specific risk doesn't apply
Original Issue in Technical Terms for Meta/Oculus Users
When a screenshot was triggered, the original plugin called Texture2D.ReadPixels() to copy the captured image from VRAM to system RAM. For a large render texture — especially at high resolution with MSAA — this is a synchronous operation. The CPU submits the copy command to the GPU and then blocks, waiting for the GPU to finish before execution can continue.
With a texture large enough (8K, high MSAA, or complex shaders like fur adding significant per-pixel cost), the GPU could take well over 2 seconds to complete that single operation. Windows monitors the GPU continuously and if it goes more than 2 seconds without responding — the default TDR timeout — Windows assumes the GPU has hung, forcibly resets the driver, and logs a TDR event.
The Oculus runtime submits its own work to the GPU every frame at 90Hz. When the TDR fired mid-frame, the Oculus compositor was in the middle of compositing a VR frame. The driver reset tore that frame and left the compositor's internal state — its frame timing, its reprojection pipeline, its swapchain synchronization — in an inconsistent condition it couldn't self-recover from.
Since the Oculus service is a separate Windows process that persists independently of VaM, closing and relaunching VaM had no effect. The corrupted state lived in OVRServer_x64.exe. Only a full system reboot, which restarts all services including the Oculus runtime, cleared it.