Forum Discussion
Anonymous
12 years ago0.4.0 & Unity 4.5.2p3 DirectToRift: How-to
I've done a lot of experimenting and I have found what I feel are the best settings and methods for 0.4.0 and the latest patch release of Unity (4.5.2p3). These instructions might also work on older versions of Unity, but I updated to latest because the 4.5.2p2 release notes mentioned DX11 lag fixes and I wanted to make sure to grab those.
Important settings:
1. QualitySettings - Other - VSync Count - Don't Vsync
The new driver handles setting vsync for you. I found if vsync is on here, the app actually crashes on startup when using DirectToRift.exe and won't run. Turning it off allows app to start.
2. PlayerSettings - Resolution & Presentation - Default is Full Screen setting should be off. If your app is set to full screen, the 1st time you run it using DirectToRift.exe, it will crash. Next time you run it will work though (because DirectToRift.exe apparently changes setting to window mode during the crash). Window mode is apparently required for DirectToRift to work.
3. OVRCameraController - set Time Warp off - it appears Time Warp is not working with Unity at this point and causes judder and/or lag. Unfortunate since Time Warp works so well with the Oculus World Demo (that is not built in Unity)
4. OVRCameraController/OVRDevice - set Prediction on - I find 30ms (0.03 - the default) works great.
5. Set Rift Display Mode to "Direct HMD Access From Apps" in driver
DX11 project:
Just build & run, exit immediately by pressing ESC. Navigate to your project folder, and double-click [app]_DirectToRift.exe. If it crashes the 1st time, just retry. It should work on next run.
DX9 project:
You can have your project set to use DX9, but when you actually go to run DirectToRift.exe, it will give you a window with nothing rendered in it and Rift display won't turn on. To fix this, you can create a shortcut to DirectToRift.exe that forces dx11 mode. To do this right-click on [app]_DirectToRift.exe in your project folder, and choose Create Shortcut. Now right-click on new shortcut, and click Properties. In the Target box, add -force-d3d11 at the end (outside of the quotations if there are any). Double-click new shortcut. If it crashes the 1st time, just retry. It should work on next run.
Tearing:
Noticing tearing when running DirectToRift? I found this happens pretty frequently even though it is clear vsync is on and app is running at 75fps. I found a simple code fix. You can bind a key to toggle vsync. To clear the tearing, just hit the toggle key twice when you notice it. The tearing should disappear. Here is the code to add to OVRDevice.cs:
Then in the OVRDevice.cs Update() I put a key binding to do this:
Now the 'V' key will toggle between vsync on and off. Toggle it off and on once and the tearing should disappear. A side benefit is you can see how fast your app will run with vsync off, although it will look terrible and hurt your eyes. I actually bound the above to a timer that does 1st toggle 5 seconds after app starts and 2nd toggle 1 second after that. That way the tearing is never an issue and I don't have to use the V key to correct the issue.
Other useful things to try:
'M' key to toggle mirroring. The window that is normally black should now have a mirror of what you see in Rift.
'T' key to toggle timewarp back on. I think you'll find like I did that Timewarp isn't working correctly here. It causes additional judder and/or lag.
'F1' key to toggle low persistence. Really impressive to see the difference.
Important settings:
1. QualitySettings - Other - VSync Count - Don't Vsync
The new driver handles setting vsync for you. I found if vsync is on here, the app actually crashes on startup when using DirectToRift.exe and won't run. Turning it off allows app to start.
2. PlayerSettings - Resolution & Presentation - Default is Full Screen setting should be off. If your app is set to full screen, the 1st time you run it using DirectToRift.exe, it will crash. Next time you run it will work though (because DirectToRift.exe apparently changes setting to window mode during the crash). Window mode is apparently required for DirectToRift to work.
3. OVRCameraController - set Time Warp off - it appears Time Warp is not working with Unity at this point and causes judder and/or lag. Unfortunate since Time Warp works so well with the Oculus World Demo (that is not built in Unity)
4. OVRCameraController/OVRDevice - set Prediction on - I find 30ms (0.03 - the default) works great.
5. Set Rift Display Mode to "Direct HMD Access From Apps" in driver
DX11 project:
Just build & run, exit immediately by pressing ESC. Navigate to your project folder, and double-click [app]_DirectToRift.exe. If it crashes the 1st time, just retry. It should work on next run.
DX9 project:
You can have your project set to use DX9, but when you actually go to run DirectToRift.exe, it will give you a window with nothing rendered in it and Rift display won't turn on. To fix this, you can create a shortcut to DirectToRift.exe that forces dx11 mode. To do this right-click on [app]_DirectToRift.exe in your project folder, and choose Create Shortcut. Now right-click on new shortcut, and click Properties. In the Target box, add -force-d3d11 at the end (outside of the quotations if there are any). Double-click new shortcut. If it crashes the 1st time, just retry. It should work on next run.
Tearing:
Noticing tearing when running DirectToRift? I found this happens pretty frequently even though it is clear vsync is on and app is running at 75fps. I found a simple code fix. You can bind a key to toggle vsync. To clear the tearing, just hit the toggle key twice when you notice it. The tearing should disappear. Here is the code to add to OVRDevice.cs:
public static void ToggleVsync() {
if (HMD == null || !SupportedPlatform)
return;
uint caps = HMD.GetEnabledCaps();
uint current = caps & (uint)ovrHmdCaps.ovrHmdCap_NoVSync;
if (current == 0) {
// vsync is on - turn it off
caps |= (uint)ovrHmdCaps.ovrHmdCap_NoVSync;
} else {
// vsync is off - turn it on
caps &= ~(uint)ovrHmdCaps.ovrHmdCap_NoVSync;
}
HMD.SetEnabledCaps(caps);
}
Then in the OVRDevice.cs Update() I put a key binding to do this:
void Update()
{
if (HMD != null && Input.anyKeyDown && HMD.GetHSWDisplayState().Displayed)
HMD.DismissHSWDisplay();
if (Input.GetKeyDown(KeyCode.V))
ToggleVsync();
}
Now the 'V' key will toggle between vsync on and off. Toggle it off and on once and the tearing should disappear. A side benefit is you can see how fast your app will run with vsync off, although it will look terrible and hurt your eyes. I actually bound the above to a timer that does 1st toggle 5 seconds after app starts and 2nd toggle 1 second after that. That way the tearing is never an issue and I don't have to use the V key to correct the issue.
Other useful things to try:
'M' key to toggle mirroring. The window that is normally black should now have a mirror of what you see in Rift.
'T' key to toggle timewarp back on. I think you'll find like I did that Timewarp isn't working correctly here. It causes additional judder and/or lag.
'F1' key to toggle low persistence. Really impressive to see the difference.
17 Replies
Replies have been turned off for this discussion
- drashHeroic ExplorerGreat info ccs. I wasn't aware you could toggle Vsync within the SDK itself. I completely missed that.
Also very helpful that you mentioned "if it crashes the first time, try it again". This has been very helpful for me now to avoid assuming something is not working just because of that first crash. Maybe this introduces a bit of confusion when people have done tests to see what works and what doesn't.
To add to this, to also support "Extend Desktop to the HMD" mode (which seems to work a lot better in Dx9 mode), it appears Unity's Vsync must be set to on from the player settings or else you will get a crash (at least I do). So now what I am doing is setting the Unity Vsync to on, then at startup checking for the -force-d3d11 command line arg to decide whether to leave it on (dx9), or to toggle ovrHmdCap_NoVSync off and on to clear up tearing (dx11). I haven't tried the 4.5.2p3 patch yet, but 4.5.2f1 definitely still has very high latency in dx11 mode, so that's my next step here.
Thanks again for the great info! I assume all of this will be obsolete by the next SDK update. :D - AnonymousYeah I'll be happy if the next version of the SDK makes all the workarounds obsolete. I'll be very happy when everything runs flawlessly with DirectToRift mode. I find Extended mode too much of a pain to deal with, and it just doesn't work with DX11 without extra pain of making Rift the primary monitor to get the refresh to be 75hz. I also like that in DirectToRift mode the HMD shuts off when not in use.
4.5.2p2 and beyond + DirectToRift (with workarounds as above of course) = completely lag free DX11. Before with older SDK and DK1, I was having to run my app with vsync off because I couldn't stand the lag. It works great now. I definitely recommend getting the patch for that alone if you use DX11, but beware Unity also added monitor selection to the start menu with this patch, so that throws some more trickery in getting Extended mode working right. The monitor selection would have been great to have 6 months ago with DK1. :D - drashHeroic ExplorerYes, it's very nice that Direct mode shuts off the display when not in use. I'm running in Extended most of the time so I've had to make my desktop background black and turn off the taskbar for the secondary desktop that shows up in the Rift. For some reason I have great success running demos in Extended mode even though the Rift is not set as the primary monitor -- no judder, smooth 75fps etc.
I'm jealous of your lag-free DX11 builds. I just tried Unity 4.5.2p3, and I found that DX11 still has high headtracking latency for me. I need to read up on using the built-in latency tester to confirm and check my other settings, but that was kind of a bummer. This patch also makes working with Extended mode a lot less stable (plus DirectToRift.exe puts the game on the wrong display by default now!), so I think for now I'll go back to vanilla 4.5.2 as I don't actually need Dx11 features just yet. - AnonymousSorry to hear you are still having trouble. It sounds like different systems might respond differently. For DX11 4.5.2p3 build, did you disable TimeWarp? It messes up headtracking quite a bit. I'm enjoying having lag-free DX11, but I can't confidently release an app or demo if it doesn't work for everyone. Oculus seems to be hinting that next SDK release is going to fix a lot of these issues, so I guess wait and see is the right approach for now.
- drashHeroic Explorer
"ccs" wrote:
For DX11 4.5.2p3 build, did you disable TimeWarp?
Yep. Prediction time set to 0.03 as well. Followed your list above to the letter! - LaeusVRHonored GuestLots of useful info, thanks for posting. My project is DX9 and I have a basic mouse-look implementation for iterating in the Unity editor, which led me to write a helper script that sets up a few things, builds a standalone player, and runs the direct-mode exe in DX11 mode. It means I can hit a single key combo to go from whatever I'm doing in the editor to running the game on DK2. It will likely need modifications for others to use, but it might help serve as a launching point for someone.
// these imports are likely not all needed for just this snippet, but most are
using UnityEngine;
using UnityEditor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.IO;
public class EditorTools : MonoBehaviour
{
[MenuItem("Tools/Build and Run on DK2 %&B")] // mapped by default to Ctrl-Alt-B
static void MyBuild()
{
// specify your path, app name, and whether to force DX11
string path = System.IO.Directory.GetCurrentDirectory() + "\\..";
string appName = "app.exe";
BuildAndRunApp(path, appName, true);
}
static void BuildAndRunApp(string path, string appName, bool forceDX11)
{
// pre-build: here's where I do some prep stuff
// then, construct scene list and build
string[] scenes = (from scene in EditorBuildSettings.scenes
where scene.enabled
select scene.path).ToArray();
BuildPipeline.BuildPlayer(scenes,
Path.Combine(path, appName),
BuildTarget.StandaloneWindows,
BuildOptions.None);
// post-build: undo the prep stuff, if any
// launch the app
Process proc = new Process();
proc.StartInfo.WorkingDirectory = path;
if (forceDX11)
proc.StartInfo.Arguments = "-force-d3d11";
proc.StartInfo.FileName = Path.GetFileNameWithoutExtension(appName)
+ "_DirectToRift.exe";
proc.Start();
}
} - AnonymousThanks LaeusVR - That is a really useful script. I didn't realize you could even do something like that in Unity. I was getting kind of tired of 'Build & Run', exit, navigate to folder, launch [app]_DirectToRift.exe for testing. You have made it a 1-click operation!
ccs - cocomonk22Honored GuestIf you use OVRCameraController, check Mirror to Display. I've also found that adding OVRDevice.ResetOrientation(); at the end of the Start() function fixes the problem that I've seen with several demos in which the camera is not directly in front of the user.
- ggunhouseHonored Guest
"ccs" wrote:
the 1st time you run it using DirectToRift.exe, it will crash. Next time you run it will work though
Thanks for these tips. I've been struggling to get DirectToRift working, but your suggested settings and procedure finally did the job for me. - 9of9Expert ProtegeAny updates for getting these workarounds to work with the 0.4.6 beta?
DX11 seems to work well except for screen tearing on the right side of the rift. Using the workaround in the original post to toggle V-Sync works to get rid of the screen tear, but adds significant headtracking lag. Toggling timewarp doesn't remove the lag - only time it's not laggy is when the project is first loaded up and there's screen tearing.
Is there any reliable way to have my cake and eat it?
Quick Links
- Horizon Developer Support
- Quest User Forums
- Troubleshooting Forum for problems with a game or app
- Quest Support for problems with your device
Other Meta Support
Related Content
- 10 months ago
- 6 months ago
- 11 months ago