Skip to content

Commit

Permalink
Remove mutex from bridge Server
Browse files Browse the repository at this point in the history
- Move `IDirect3D9Ex_CreateDevice` from server module -> main (device) thread
- Get rid of mutexes server-side
- Get rid of `extern`ed `unordered_map`s in Server module thread
  • Loading branch information
nv-nfreybler committed Sep 18, 2024
2 parents 2dd0a0e + bfac594 commit 1ef3843
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 85 deletions.
10 changes: 5 additions & 5 deletions src/client/d3d9_device_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ BaseDirect3DDevice9Ex_LSS::BaseDirect3DDevice9Ex_LSS(const bool bExtended,

UID currentUID = 0;
{
ModuleClientCommand c(m_ex ? Commands::IDirect3D9Ex_CreateDeviceEx : Commands::IDirect3D9Ex_CreateDevice, getId());
ClientMessage c(m_ex ? Commands::IDirect3D9Ex_CreateDeviceEx : Commands::IDirect3D9Ex_CreateDevice, getId());
currentUID = c.get_uid();
c.send_many( createParams.AdapterOrdinal,
createParams.DeviceType,
Expand All @@ -90,18 +90,18 @@ BaseDirect3DDevice9Ex_LSS::BaseDirect3DDevice9Ex_LSS(const bool bExtended,
Logger::debug("...server-side D3D9 device creation command sent...");

Logger::debug("...waiting for create device ack response from server...");
if (Result::Success != ModuleBridge::waitForCommand(Commands::Bridge_Response, 0, nullptr, true, currentUID)) {
if (Result::Success != DeviceBridge::waitForCommand(Commands::Bridge_Response, 0, nullptr, true, currentUID)) {
Logger::err("...server-side D3D9 device creation failed with: no response from server.");
removeWinProc(getWinProcHwnd());
hresultOut = D3DERR_DEVICELOST;
return;
}
Logger::debug("...create device response received from server...");
const auto header = ModuleBridge::pop_front();
const auto header = DeviceBridge::pop_front();

// Grab hresult from server
hresultOut = (HRESULT) ModuleBridge::get_data();
assert(ModuleBridge::get_data_pos() == header.dataOffset);
hresultOut = (HRESULT) DeviceBridge::get_data();
assert(DeviceBridge::get_data_pos() == header.dataOffset);

if (FAILED(hresultOut)) {
Logger::err(format_string("...server-side D3D9 device creation failed with %x.", hresultOut));
Expand Down
69 changes: 66 additions & 3 deletions src/server/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,6 @@ std::unordered_map<uint32_t, IDirect3DSwapChain9*> gpD3DSwapChains;
std::unordered_map<uint32_t, IDirect3DQuery9*> gpD3DQuery;
std::unordered_map<uint32_t, void*> gMapRemixApi;

std::mutex gLock;

// Global state
bool gbBridgeRunning = true;
HANDLE hWait;
Expand Down Expand Up @@ -306,9 +304,74 @@ void ProcessDeviceCommandQueue() {
Logger::info("Device Processing: " + toString(rpcHeader.command) + " UID: " + std::to_string(currentUID));
}
#endif
std::unique_lock<std::mutex> lock(gLock);
// The mother of all switch statements - every call in the D3D9 interface is mapped here...
switch (rpcHeader.command) {
case IDirect3D9Ex_CreateDeviceEx:
{
GET_HND(pHandle);
PULL_U(Adapter);
PULL(D3DDEVTYPE, DeviceType);
PULL(uint32_t, hFocusWindow);
PULL_D(BehaviorFlags);
D3DDISPLAYMODEEX* pFullscreenDisplayMode = nullptr;
PULL_DATA(sizeof(D3DDISPLAYMODEEX), pFullscreenDisplayMode);

uint32_t* rawPresentationParameters = nullptr;
DeviceBridge::get_data((void**) &rawPresentationParameters);
D3DPRESENT_PARAMETERS PresentationParameters = getPresParamFromRaw(rawPresentationParameters);

IDirect3DDevice9Ex* pD3DDevice = nullptr;
const auto hresult = ((IDirect3D9Ex*) gpD3D)->CreateDeviceEx(IN Adapter, IN DeviceType, IN TRUNCATE_HANDLE(HWND, hFocusWindow), IN BehaviorFlags, IN OUT & PresentationParameters, IN pFullscreenDisplayMode, OUT & pD3DDevice);
if (!SUCCEEDED(hresult)) {
std::stringstream ss;
ss << format_string("CreateDeviceEx() call failed with error code 0x%x", hresult) << std::endl;
Logger::err(ss.str());
} else {
Logger::info("Server side D3D9 DeviceEx created successfully!");
gpD3DDevices[pHandle] = pD3DDevice;
remixapi::g_device = pD3DDevice;
}

// Send response back to the client
Logger::debug("Sending CreateDevice ack response back to client.");
{
ServerMessage c(Commands::Bridge_Response, currentUID);
c.send_data(hresult);
}
break;
}
case IDirect3D9Ex_CreateDevice:
{
GET_HND(pHandle);
PULL_U(Adapter);
PULL(D3DDEVTYPE, DeviceType);
PULL(uint32_t, hFocusWindow);
PULL_D(BehaviorFlags);

uint32_t* rawPresentationParameters = nullptr;
DeviceBridge::get_data((void**) &rawPresentationParameters);
D3DPRESENT_PARAMETERS PresentationParameters = getPresParamFromRaw(rawPresentationParameters);

IDirect3DDevice9* pD3DDevice = nullptr;
const auto hresult = gpD3D->CreateDevice(IN Adapter, IN DeviceType, IN TRUNCATE_HANDLE(HWND, hFocusWindow), IN BehaviorFlags, IN OUT & PresentationParameters, OUT & pD3DDevice);
if (!SUCCEEDED(hresult)) {
std::stringstream ss;
ss << format_string("CreateDevice() call failed with error code 0x%x", hresult) << std::endl;
Logger::err(ss.str());
} else {
Logger::info("Server side D3D9 Device created successfully!");
gpD3DDevices[pHandle] = (IDirect3DDevice9Ex*) pD3DDevice;
remixapi::g_device = (IDirect3DDevice9Ex*) pD3DDevice;
}

// Send response back to the client
Logger::debug("Sending CreateDevice ack response back to client.");
{
ServerMessage c(Commands::Bridge_Response, currentUID);
c.send_data(hresult);
}
break;
}
case IDirect3DDevice9Ex_GetDisplayModeEx:
{
GET_RES(pD3DDevice, gpD3DDevices);
Expand Down
77 changes: 0 additions & 77 deletions src/server/module_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,6 @@ using namespace Commands;

// Mapping between client and server pointer addresses
extern LPDIRECT3D9 gpD3D;
extern std::unordered_map<uint32_t, IDirect3DDevice9*> gpD3DDevices;
extern std::unordered_map<uint32_t, IDirect3DResource9*> gpD3DResources; // For Textures, Buffers, and Surfaces
extern std::unordered_map<uint32_t, IDirect3DVolume9*> gpD3DVolumes;
extern std::unordered_map<uint32_t, IDirect3DVertexDeclaration9*> gpD3DVertexDeclarations;
extern std::unordered_map<uint32_t, IDirect3DStateBlock9*> gpD3DStateBlocks;
extern std::unordered_map<uint32_t, IDirect3DVertexShader9*> gpD3DVertexShaders;
extern std::unordered_map<uint32_t, IDirect3DPixelShader9*> gpD3DPixelShaders;
extern std::unordered_map<uint32_t, IDirect3DSwapChain9*> gpD3DSwapChains;

extern std::mutex gLock;

#define PULL(type, name) const auto& name = (type)ModuleBridge::get_data()
#define PULL_I(name) PULL(INT, name)
Expand Down Expand Up @@ -94,7 +84,6 @@ void processModuleCommandQueue(std::atomic<bool>* const pbSignalEnd) {
Logger::info("Module Processing: " + toString(rpcHeader.command) + " UID: " + std::to_string(currentUID));
}
#endif
std::unique_lock<std::mutex> lock(gLock);
// The mother of all switch statements - every call in the D3D9 interface is mapped here...
switch (rpcHeader.command) {
/*
Expand Down Expand Up @@ -345,72 +334,6 @@ void processModuleCommandQueue(std::atomic<bool>* const pbSignalEnd) {
}
break;
}
case IDirect3D9Ex_CreateDeviceEx:
{
GET_HND(pHandle);
PULL_U(Adapter);
PULL(D3DDEVTYPE, DeviceType);
PULL(uint32_t, hFocusWindow);
PULL_D(BehaviorFlags);
D3DDISPLAYMODEEX* pFullscreenDisplayMode = nullptr;
PULL_DATA(sizeof(D3DDISPLAYMODEEX), pFullscreenDisplayMode);

uint32_t* rawPresentationParameters = nullptr;
ModuleBridge::get_data((void**) &rawPresentationParameters);
D3DPRESENT_PARAMETERS PresentationParameters = getPresParamFromRaw(rawPresentationParameters);

IDirect3DDevice9Ex* pD3DDevice = nullptr;
const auto hresult = ((IDirect3D9Ex*) gpD3D)->CreateDeviceEx(IN Adapter, IN DeviceType, IN TRUNCATE_HANDLE(HWND, hFocusWindow), IN BehaviorFlags, IN OUT & PresentationParameters, IN pFullscreenDisplayMode, OUT & pD3DDevice);
if (!SUCCEEDED(hresult)) {
std::stringstream ss;
ss << format_string("CreateDeviceEx() call failed with error code 0x%x", hresult) << std::endl;
Logger::err(ss.str());
} else {
Logger::info("Server side D3D9 DeviceEx created successfully!");
gpD3DDevices[pHandle] = pD3DDevice;
remixapi::g_device = pD3DDevice;
}

// Send response back to the client
Logger::debug("Sending CreateDevice ack response back to client.");
{
ModuleServerCommand c(Commands::Bridge_Response, currentUID);
c.send_data(hresult);
}
break;
}
case IDirect3D9Ex_CreateDevice:
{
GET_HND(pHandle);
PULL_U(Adapter);
PULL(D3DDEVTYPE, DeviceType);
PULL(uint32_t, hFocusWindow);
PULL_D(BehaviorFlags);

uint32_t* rawPresentationParameters = nullptr;
ModuleBridge::get_data((void**) &rawPresentationParameters);
D3DPRESENT_PARAMETERS PresentationParameters = getPresParamFromRaw(rawPresentationParameters);

IDirect3DDevice9* pD3DDevice = nullptr;
const auto hresult = gpD3D->CreateDevice(IN Adapter, IN DeviceType, IN TRUNCATE_HANDLE(HWND, hFocusWindow), IN BehaviorFlags, IN OUT & PresentationParameters, OUT & pD3DDevice);
if (!SUCCEEDED(hresult)) {
std::stringstream ss;
ss << format_string("CreateDevice() call failed with error code 0x%x", hresult) << std::endl;
Logger::err(ss.str());
} else {
Logger::info("Server side D3D9 Device created successfully!");
gpD3DDevices[pHandle] = (IDirect3DDevice9Ex*) pD3DDevice;
remixapi::g_device = (IDirect3DDevice9Ex*) pD3DDevice;
}

// Send response back to the client
Logger::debug("Sending CreateDevice ack response back to client.");
{
ModuleServerCommand c(Commands::Bridge_Response, currentUID);
c.send_data(hresult);
}
break;
}
}
}
// Check if we exited the command processing loop unexpectedly while the bridge is still enabled
Expand Down

0 comments on commit 1ef3843

Please sign in to comment.