Refuse late-attach if a device is already active

RegisterExistingDevice deduped against D3D9Hooks.cpp's own g_devices map,
but the cold Direct3DCreate9(Ex) path (D3D9Wrappers.cpp) never touches that
map. If gMod is early-injected and something (e.g. GWToolbox adopting a
pre-loaded gMod) also calls SetDevice on the resulting wrapper device,
RegisterExistingDevice would treat it as new: MinHook-patch the wrapper's
own vtable on top, and construct a second TextureClient, hitting its
single-instance ASSERT. Check TextureClient::CurrentClient() first so any
already-active device (via either path) is a no-op.
This commit is contained in:
GWToolbox Bot
2026-07-07 10:55:30 +00:00
parent 2b2a817c15
commit 2705ceda7b
+5
View File
@@ -357,6 +357,11 @@ void InstallD3D9Hooks(IDirect3D9* d3d9, const bool is_ex)
bool RegisterExistingDevice(IDirect3DDevice9* device)
{
if (device == nullptr) return false;
// Already active, whether registered via this path before or already wrapped by the
// cold Direct3DCreate9(Ex) path (D3D9Wrappers.cpp) - that path never touches g_devices,
// so without this check we'd double-hook the wrapper's own vtable and construct a second
// TextureClient, hitting its single-instance ASSERT.
if (TextureClient::CurrentClient() != nullptr) return false;
{
std::lock_guard lk(g_devices_mutex);
if (g_devices.contains(device)) return false; // already known