https://bugs.winehq.org/show_bug.cgi?id=47767
Paul Gofman gofmanp@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |gofmanp@gmail.com
--- Comment #1 from Paul Gofman gofmanp@gmail.com --- I have tested the game trial.
The immediate workaround to get the speed to normal is to disable CSMT (set HKCU\Software\Wine\Direct3D\csmt to 0).
The other workaround is to set process affinity for AirportMania.RWG process after the game is started to default, like 'taskset -p 0xffffffff <pid>', where pid is process id of 'AirportMania.RWG' process which game creates. This will help if there is more than one CPU core present.
Yet another workaround is set WINED3D_CS_SPIN_COUNT to 0 in dlls/wined3d/wined3d_private.h.
The game sets process affinity mask to 1 for the process. Here are related calls (all that relates to process 'AirportMania.RWG', which is started from game launcher):
--- 002c:Call KERNEL32.GetProcessAffinityMask(ffffffff,0032fad8,0032fac0) ret=00477314 002c:Ret KERNEL32.GetProcessAffinityMask() retval=00000001 ret=00477314 002c:Call KERNEL32.SetProcessAffinityMask(ffffffff,00000001) ret=0047744d 002c:Ret KERNEL32.SetProcessAffinityMask() retval=00000001 ret=0047744d 002c:Call KERNEL32.SetThreadAffinityMask(00000114,0000003e) ret=00477480 002c:Ret KERNEL32.SetThreadAffinityMask() retval=00000000 ret=00477480 ---
I have no idea what the game is trying to achieve by its inventive thread affinity masks, but I verified that process affinity mask end up being 1 both under Wine and Windows 7, so that process is bound to a single logical CPU.
Having done that, the game constantly locks and unlocks ddraw7 surfaces, that's the main load it creates. The most of the CPU spent in wined3d_cs_run() in CS thread, which is spinning waiting for task to be queued. Mapping of surfaces has to go through map queue, and also spins waiting while the CS thread does the actual mapping. Those spins create enough load for an effective single core execution to leave a very little time for anything else. Removing spin locking in wined3d_cs_run() (going to wined3d_cs_wait_event() every time) gets normal performance (while this is not a general improvement to CS thread locking logic of course).