ValveSoftware / openvr

OpenVR SDK
http://steamvr.com
BSD 3-Clause "New" or "Revised" License
6.03k stars 1.27k forks source link

Cannot enable "Direct Mode" with IVRDriverDirectModeComponent implemented #431

Open dperox opened 7 years ago

dperox commented 7 years ago

My driver implements the IVRDriverDirectModeComponent and SteamVR is submitting frames to it. However, When I start SteamVR there is an warning message that says: "SteamVR is in Extended Mode". There is also button that says "Enable Direct Mode" which restarts SteamVR but nothing changes. And its not possible to enable the "Direct Mode" from SteamVR settings.

I have a few questions:

  1. Is the message just an indication that Nvidia/AMD Direct mode not being used? Or does it mean there is an issue with my IVRDriverDirectModeComponent implementation?

  2. In order to enable "Direct Mode", other then implementing the IVRDriverDirectModeComponent and setting up the Prop_UsesDriverDirectMode_Bool property to true, is there anything else that is required?

  3. What is the "Extended Mode" meaning in this case? As I do receive the frames in my driver and there is nothing being rendered to the desktop.

TheDeveloperGuy commented 7 years ago

This is a bug in SteamVR IMO. When using Oculus/Direct mode, the OpenVR compositor does not have control of the display, and has no way to tell if the HMD is in direct/extended mode. It therefore shouldn't give any warnings in this regard. The Oculus driver doesn't show this warning, so there must be flag to set in the driver to avoid the warning, but I haven't found it. In any case, trying to enable it can't/won't do anything, so all you can do is 'dismiss'.

TheDeveloperGuy commented 7 years ago

Really wish they'd called this "Oculus/Direct" Mode something else. Endless confusion between "Oculus/Direct" and "Display/Direct", which are almost completely unrelated but are both called "direct". In this instance "direct" mode is referring to "Display/Direct" and so is unrelated to your "Oculus/Direct" driver.

dperox commented 7 years ago

@TheDeveloperGuy my thoughts exactly.

The Oculus driver doesn't show this warning, so there must be flag to set in the driver to avoid the warning, but I haven't found it.

I was wondering if the DirectMode can be enabled with the Oculus runtime since there is a physical headset present on the system and its edid is whitelisted by the NVIDIA driver. to OpenVR then gets its indication that DirectMode is available/enabled.

My only concern is that OpenVR will perform worse since it thinks it is in "extended mode" (e.g. if it does extra steps that aren't needed by a DirectMode driver)

TheDeveloperGuy commented 7 years ago

Please don't make me have to explain the difference between "Oculus/Direct" and "Display/Direct" to anyone again! :)

The IVRDriverDirectModeComponent might as well be called IVRDriverOculusModeComponent because that is what it is. It has nothing to do with your display driver's "direct" mode. Whether or not OpenVR thinks your display is "extended" or not makes no difference to your HMD driver. In particular these terms have absolutely no meaning if your HMD is not connected via a VGA/DVI/HDMI/DP port! Your OpenVR HMD driver effectively bypasses most of OpenVR's compositor and is responsible for all of the kind of things that the OpenVR compositor would normally be responsible for.

The real Oculus OpenVR driver (your's is a fake) uses the Oculus runtime's own compositor. You have to emulate this in your fake driver. Somewhere in the real Oculus OpenVR driver it sets something which disables this warning (who knows what it is? we will probably never find out because the Oculus driver is closed source that noone wants to give any info about).

OpenVR doesn't know anything about the screen mode, monitor ID etc. that the Oculus runtime is using (if you doubt this look at vrserver.txt log after running Oculus and you will see the same "DXGI thread failed to get SDL display index" that you will see for your own driver).

In any case, you'll have to live with this because there doesn't appear to be any way around it. I have had no problems running 120+FPS with this interface, so I wouldn't worry too much about the performance implications.

HelenXR commented 7 years ago

@TheDeveloperGuy Thank you very much for your wonderful answer. Finally my understanding is:

TheDeveloperGuy commented 7 years ago

@HelenXR 1) No, you can use IVRDriverDirectModeComponent for your own driver, if you implement an equivalent of the Oculus compositor yourself. 2) If your hardware supports 120Hz, maybe. I used the Oculus interface to achieve 120FPS.

HelenXR commented 7 years ago

@TheDeveloperGuy thanks!

TheDeveloperGuy commented 7 years ago

@HelenXR The primary benefit of using a IVRDriverDirectModeComponent driver for HDMI connected headsets is much finer control over when the HMD can be activated. In a IVRDisplayComponent driver, the HMD's display must be presented to Windows (either as extended or direct mode) before the driver is initialised, whereas the IVRDriverDirectModeComponent can activate the display whenever it wants to. This allows a IVRDriverDirectModeComponent driver to operate without a 'server' application running on the PC. The IVRDriverDirectModeComponent also allows more flexibility when it comes to composing the final image that gets sent to the headset (image rotation, scan-line interleaving etc.).

zezba9000 commented 7 years ago

Did you ever figure out how to get the "Prop_UsesDriverDirectMode_Bool" / "Prop_EdidVendorID_Int32" / "Prop_EdidProductID_Int32" values to work?

I have DirectMode working in a custom app but am trying to get it working in OpenVR using there compositor.

godbyk commented 7 years ago

The Prop_UsesDriverDirectMode_Bool property should be false if you want to use SteamVR's own direct-mode implementation. Set the EDID properties properly.

zezba9000 commented 7 years ago

Set the EDID properties properly. -- Can you clarify this? I've set "Prop_EdidVendorID_Int32" and "Prop_EdidProductID_Int32" to the same values in my working DirectMode app and the vrcompositor just opens then quits. The vrmonitor says my HMD is there but not ready.

zezba9000 commented 7 years ago

My values are set like:

vr::VRProperties()->SetBoolProperty(m_ulPropertyContainer, Prop_UsesDriverDirectMode_Bool, false);
vr::VRProperties()->SetInt32Property(m_ulPropertyContainer, Prop_EdidVendorID_Int32, 0x1017);
vr::VRProperties()->SetInt32Property(m_ulPropertyContainer, Prop_EdidProductID_Int32, 0x0007);
godbyk commented 7 years ago

It means set Prop_EdidVendorID_Int32 and Prop_EdidProductID_Int32 to the EDID vendor and product ID values associated with the monitor you want SteamVR to put into direct mode.

zezba9000 commented 7 years ago

image My Edid looks like the values shown.

Also these values are passing correct I assume?

bool IVRDisplayComponent::IsDisplayOnDesktop()
{
    return false;
}

bool IVRDisplayComponent::IsDisplayRealDisplay()
{
    return true;
}
godbyk commented 7 years ago

IsDisplayRealDisplay() should return true, as you've done. IsDisplayOnDesktop() should return true when the display is in extended mode and false when it's in direct mode (or if you're using your own direct-mode implementation instead of SteamVR's).

zezba9000 commented 7 years ago

Awesomeness, I got it working. Had the resolution set incorrectly. Now I have direct mode working. Tnx for the clarification!! Cool so both extended and direct work now.

godbyk commented 7 years ago

Glad I could help. It's definitely a matter of knowing all the right buttons to push at the right time.

zezba9000 commented 7 years ago

One last question if you know off the top of your head. So a Unity OpenVR game is running on the screen just fine, however I still get the "Not Ready" status in the vrmonitor. Because of this, "DriverPose_t" updates I'm passing from "ITrackedDeviceServerDriver::GetPose" stops taking effect in the game.

Am I required to implement something else to prevent this from happening?

godbyk commented 7 years ago

It's hard to say. Check to make sure you're continuing to send pose updates regularly. I think it may go to a not-ready state if too much time elapses without a pose update.

zezba9000 commented 7 years ago

I can attach a debugger and see the method is always fired as that was my first guess. O well more digging I guess. I'm guessing I need to implement some other interface or have some other setting wrong.

wintersku commented 6 years ago

@TheDeveloperGuy @zezba9000 Need display support HDCP to achieve direct mode?Thx!

AllenVC commented 5 years ago

@zezba9000 Hi,Im trying to realize the IVRDriverDirectModeComponent by myself, but it can`t work corrcetly and there has not picture on the HMD , how do u realize the IVRDriverDirectModeComponent::Present function?

zezba9000 commented 5 years ago

@AllenVC Yes HDCP is required for DirectMode to function correctly on Nvidia. You can use a HDMI splitter with HDCP support to add it if your screen doesn't support it. You also have to whitelist your LCD/OLED screen using the Nvidia SDK if you haven't done that.

After you have all that stuff working OpenVR should start presenting stuff with your custom OpenVR driver. Make sure your screens hardware VID / PID ids are valid etc.

TheDeveloperGuy commented 5 years ago

@AllenVC "VR-Direct" (aka. Direct) mode and DirectModeComponent are 2 very different things. You don't give enough information for anyone to tell which one you are actually trying to implement. If it's a custom HMD connected via HDMI/DP, it's "VR-Direct", otherwise if the HMD implements its own compositor it's DirectModeComponent.

AllenVC commented 5 years ago

@TheDeveloperGuy @zezba9000 Actually,my HMD screen has existed in Nvidia's whitelist, I have realised the DirectMode with Nvidia API.Now I want to implement DirectMode on SteamVR with my HMD and add our own algorithm in SteamVR's games to detect my screen and algorithm.That why I try to realise IVRDriverDirectModeComponent by myself,but it couldn't work correctly and the screen is always black,so I want to know how do u implement the IVRDriverDirectModeComponent::present()?

TheDeveloperGuy commented 5 years ago

@AllenVC You don't. Re-read my previous comment. You shouldn't be implementing IVRDriverDirectModeComponent at all, only IVRDisplayComponent

TheDeveloperGuy commented 5 years ago

@AllenVC All you need to do is some minor modifications (for tracking and lens distortion) to the sample driver.

AllenVC commented 5 years ago

@TheDeveloperGuy Thanks a lot. I want to get and save the texture after distortion on OpenVR. And I also should use my algorithm to process the texture then displayed on my HMD. The IVRDisplayComponent can't satisfy my requirement because I can't get texture by IVRDisplayComponent .

TheDeveloperGuy commented 5 years ago

@AllenVC You'll have to use IVRVirtualDisplay. It's not really intended for use in place of IVRDisplayComponent, so you'll have to do your own output. You'll get the output texture and then do whatever you need to do to get it to the HMD, as the only way SteamVR will do that work is with IVRDisplayComponent. You could also use IVRDriverDirectModeComponent but it's a lot more complexity for no advantage in your use case (you'd have to do texture management, layer composition and lens distortion yourself). Valve gives sample code for IVRDisplayComponent and IVRVirtualDisplay but not IVRDriverDirectModeComponent, as it's a (pretty much) private public interface.

AllenVC commented 5 years ago

@TheDeveloperGuy OK!I will attempt to use IVRVirtualDisplay to implement my request.Thanks very much!

TheDeveloperGuy commented 5 years ago

@AllenVC If your headset is PSVR, you can just use my driver... ;)

AllenVC commented 5 years ago

@TheDeveloperGuy My headset has not been published, but my EDID has been in Nvidia's whitelist. I will try to use the openVR/virtual_display to implement my request....;)

JoeLudwig commented 5 years ago

@AllenVC If your display can be represented by the various properties and functions represented by IVRDisplayComponent that's the easiest way to get pixels onto it. SteamVR can open it directly and your driver doesn't need to touch the pixels at all.

AllenVC commented 5 years ago

@JoeLudwig ok! thanks!

TheDeveloperGuy commented 5 years ago

@AllenVC Hehe, was just going off your avatar. As discussed previously you don't need to use one of the other driver interfaces if you don't need to touch the pixels. If you do, then use the virtual interface.

AllenVC commented 5 years ago

@JoeLudwig @TheDeveloperGuy I need to touch the pixels,so I should use the virtual interface.

AllenVC commented 5 years ago

@JoeLudwig @TheDeveloperGuy I have get the distortion texture through IVRVirtualDisplay::prent ,but I have the last question is that how should I do to present the texture in my HMD?Should I use the NVIDIA DirectMode API or the openVR has it's own function?

TheDeveloperGuy commented 5 years ago

@AllenVC Please read the previous messages discussing this: "you'll have to do your own output"

AllenVC commented 5 years ago

@TheDeveloperGuy OK! I have finished the work in the weekend! Thanks for your help very much!

AllenVC commented 5 years ago

@TheDeveloperGuy Hi,Sorry to bother you again. I want to use IVRCameraComponent to handle the camera ,but can't find the information on website,what should I do to use the IVRCameraComponent ?

TheDeveloperGuy commented 5 years ago

@AllenVC Unfortunately I do not have any experience with that component. My suggestion is to spend some time trying to figure it out yourself. Once you know enough about it to ask educated questions you'll get some help from the Valve developers (I am not one). All of this stuff is fairly undocumented, and I don't see that changing any time soon. If you plan on doing driver work in OpenVR, you'll need to teach yourself to fish, there are no people giving out fish (or fishing lessons) here... ;)