Ds4windows: [TODO] Experiment with ViGEm Driver

Created on 8 Nov 2017  路  14Comments  路  Source: Ryochan7/DS4Windows

Unlike other releases of ViGEm, the current version works on my system; previously releases did not have an associated bus device appear in the Device Manager although Windows recognized that the driver was installed. I have been interested in ViGEm since InputMapper initially added support for it in IM 1.7 although none of the builds that I have tried have worked right on my system. Scp Virtual Bus has been, for the most part, unsupported for a while so it would be nice to have a currently maintained driver to replace it.

So far, VDX is the only application that I have tested that actually uses ViGEm.

enhancement

Most helpful comment

Due to some recent changes, I will consider ViGEm integration to be complete. Although ScpVBus has served as a good baseline while tweaking DS4Windows, ViGEm is more than ready to use regularly if you build from the current code base. The base build of DS4Windows will start to use ViGEm once a new version of ViGEmBus is published. I plan to use ViGEm regularly on my own system from now on.

https://github.com/ViGEm/ViGEmBus

All 14 comments

Finally got around to testing ViGEm. Adding minor support for ViGEm in DS4Windows was not very time consuming thanks to the ViGEmClient assembly. Overall, I like the API that is provided by the assembly for interacting with the bus driver. However, there is a good increase in input lag when using ViGEm. It was almost usable but it feels like there is more input lag when using a 4 ms BT poll rate and ViGEm than when using a 16 ms BT poll rate and ScpVBus.

@nefarius Looking at the source code, there is one major red flag that I see. The CreateFile call does not include a couple of flags that remove extra system provided buffers. I would suggest including the flags FILE_FLAG_NO_BUFFERING and FILE_FLAG_WRITE_THROUGH. Using those flags when opening the ScpVBus device has made a big difference in performance so I would assume that using those flags would help ViGEm as well. I will have to test that out on my end sometime.

https://github.com/nefarius/ViGEm/blob/master/Src/ViGEmClient/ViGEmClient.cpp#L150

https://www.nuget.org/packages/Nefarius.ViGEmClient/

Thank you very much for your input, I don't get much in-depth feedback currently so yours is especially precious 馃槃 The flags about the buffer is a great hint, I will test that. What else could I do to make development more comfortable (besides better docs ofc. 馃槢)? How do you measure latency?

I tested adding the extra flags last night and including those flags brought performance much closer to what ScpVBus provides. I see that you have already included the change in the ViGEm repository. Thank you for incorporating that change.

More testing will have to be done to see what changes could improve performance more. Some of those changes could just be on my test implementation for DS4Windows. If I have any recommendations then I will let you know.

For testing, I mainly use play testing and judge based on feel. One simple test that I use lately is to load .hack//G.U., go to Mac Anu and check how quickly the door near the Chaos Gate opens when Cross is pressed.

Testing various changes has been an interesting experience and ViGEm performance is slightly better after some tweaks than what is currently offered using ScpVBus. Some minor changes that I have made on my local copy might not be necessary but I will mention the crucial ones that have led to noteworthy performance differences during my testing.

One simple change for the ViGEmClient.NET code that has helped is to allow setting the Buttons property in some way. With the current implementation of Xbox360Report, either each individual button state has to be set using a method call or Xbox360Report.SetButtons is used to set the buttons that you want to be active. For my test implementation, I am reusing an instance of Xbox360Report so using Xbox360Report.SetButtons is not really feasible; I have tested making a new instance each poll and using Xbox360Report.SetButtons by populating a list and converting it to an array. Making object instances in .NET seems to be a fairly expensive operation so that is why I am reusing an instance. Using Xbox360Report.SetButtonState results in too many extra method calls. Since Xbox360Buttons is an enum flag, what I am doing in DS4Windows now is to bitmask the various active buttons into a local variable and I wrote a small method to convert the value into a ushort and set the Buttons value in the Xbox360Report instance.

public void SetButtons(Xbox360Buttons buttons)
{
    Buttons = (ushort)buttons;
}

Usage

Xbox360Buttons tempButtons = 0;
if (state.Share) tempButtons |= Xbox360Buttons.Back;
if (state.L3) tempButtons |= Xbox360Buttons.LeftThumb;
if (state.R3) tempButtons |= Xbox360Buttons.RightThumb;
if (state.Options) tempButtons |= Xbox360Buttons.Start;

if (state.DpadUp) tempButtons |= Xbox360Buttons.Up;
if (state.DpadRight) tempButtons |= Xbox360Buttons.Right;
if (state.DpadDown) tempButtons |= Xbox360Buttons.Down;
if (state.DpadLeft) tempButtons |= Xbox360Buttons.Left;

if (state.L1) tempButtons |= Xbox360Buttons.LeftShoulder;
if (state.R1) tempButtons |= Xbox360Buttons.RightShoulder;

if (state.Triangle) tempButtons |= Xbox360Buttons.Y;
if (state.Circle) tempButtons |= Xbox360Buttons.B;
if (state.Cross) tempButtons |= Xbox360Buttons.A;
if (state.Square) tempButtons |= Xbox360Buttons.X;
if (state.PS) tempButtons |= Xbox360Buttons.Guide;
xboxreport.SetButtons(tempButtons);

One other big change is regarding guidelines for handling overlapped IO calls in the ViGEmBus driver. In busenum.c, STATUS_PENDING needs to be taken into consideration in the Bus_SubmitReport function. Just making sure to ignore calling WdfRequestComplete for STATUS_PENDING resulted in a good performance jump; it is now being checked shortly after calling WdfIoQueueRetrieveNextRequest. It seems like it is standand practice to skip that call if the status is set to STATUS_PENDING.

Around busenum.c Line 568

if (status == STATUS_PENDING)
    goto endSubmitReport;
else if (!NT_SUCCESS(status))
    goto endSubmitReport;

After some minor testing, one nice difference with ViGEm is that it does not seem to have a problem with using a faster BT poll rate than 4 ms like ScpVBus does. Although the default BT poll rate in DS4Windows will continue to be 4 ms, enabling a faster poll rate results in quicker responses in game and some users would probably be willing to sacrifice battery life for a more responsive experience.

Marvelous! I've implemented some P/Invoke optimizations in the meantime as well. You can grab a build using it from my new personal NuGet source. Just add it in VS and enjoy more frequent releases.

Anyways, regarding your observations:

Yes, the overhead on calling managed methods is a valid concern, I'll refactor that a tad.

About the STATUS_PENDING on submitting report updates; have you been able to measure a difference? Because at this stage in the code the status variable will never be set to STATUS_PENDING. I expect it to be either STATUS_SUCCESS which means a pending IRP has been returned from the queue or STATUS_NO_MORE_ENTRIES if the queue is empty. So WdfRequestComplete get's only called on STATUS_SUCCESS anyways, no?

Using a Debug build of ViGEmBus and DebugView, I have not seen a time when the STATUS_PENDING case has been encountered. However, using a Release build and testing builds with the check enabled and disabled seems to show that there is a performance difference with the quicker version being the one with the check enabled. The Visual Studio profiler seems to show that the vigem_target_x360_update function runs slightly faster with the check enabled. I don't know why there seems to be a performance difference. I cannot quantify the difference in responsiveness but it feels like a minor difference of maybe a frame or two.

I am using an older copy of ViGEm on my system; I am currently using commit https://github.com/nefarius/ViGEm/commit/a08a81e6747f3fcf0441d88f3fe5b6a8baf18902. I will have to clone the new version and give it a try.

Well it won't hurt if I add it.

I downloaded and built from the latest git code. Results ended up being similar. I also tried making various other tweaks to the ViGEmBus driver. I removed goto usage, included always false if statement and tried the same if statement with some more commonly returned status values such as STATUS_NO_MORE_ENTRIES. For some reason, the STATUS_PENDING version is the one that turns ViGEm from slightly underperforming to being the better option. Have you tried this on your system to see if you experience similar results?

For the most part, ViGEm integration is finished. Multiple controller support and force feedback functionality have been added with the most recent changes. Some of the code still deviates from what ViGEmClient.NET supports so the changes have not been included in the DS4Windows repository yet. The last major hurdle is making an automated method for installing the ViGEmBus driver. Here is a diff file showing what progress has been made.

https://gist.github.com/Ryochan7/13f9f3fa77fd4097cd26d406a7ea9205

I completely reworked the installer, unattended installations are no problem anymore.

Testing with VDX has shown that the ViGEmBus driver changes can be felt in that application as well.

The PowerShell cmdlets work well and those will definitely come in handy.

A pull request has been made with some proposed changes to ViGEm that DS4Windows is currently taking advantage of.

https://github.com/nefarius/ViGEm/pull/73

Due to some recent changes, I will consider ViGEm integration to be complete. Although ScpVBus has served as a good baseline while tweaking DS4Windows, ViGEm is more than ready to use regularly if you build from the current code base. The base build of DS4Windows will start to use ViGEm once a new version of ViGEmBus is published. I plan to use ViGEm regularly on my own system from now on.

https://github.com/ViGEm/ViGEmBus

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wergio picture wergio  路  3Comments

bison3 picture bison3  路  5Comments

pralima87 picture pralima87  路  8Comments

khanghugo picture khanghugo  路  4Comments

Okami23 picture Okami23  路  6Comments