Skip to main content
Up and Coming
May 11, 2014

Strange effect using Sdk 0.3.1

Hi All,

I've been writing some code interfacing a .NET application with the new Rift 0.3.1 code. But it's producing some strange effects.

I'm using the SDK rendering (a texture per eye) and although I get something showing up when I render, the are pushed out to the side. The cube is rendered dead centre of the texture but comes out like the picture below.

edit

Just to say that this is using OpenGL with OpenTK driving the GL on the .NET side.

The Setup follows the examples as far as I can see.
		
eyes[0].Eye = ovrEye_Left;
eyes[1].Eye = ovrEye_Right;
eyes[0].Fov = hmdDesc.DefaultEyeFov[0];
eyes[1].Fov = hmdDesc.DefaultEyeFov[1];
eyes[0].TextureSize = renderTargetSize;
eyes[1].TextureSize = renderTargetSize;
eyes[0].RenderViewport.Pos = Vector2i(0,0);
eyes[0].RenderViewport.Size = Sizei(renderTargetSize.w, renderTargetSize.h);
eyes[1].RenderViewport.Pos = Vector2i(0,0);
eyes[1].RenderViewport.Size = Sizei(renderTargetSize.w , renderTargetSize.h);

eyeRenderDesc[0] = ovrHmd_GetRenderDesc(hmd, eyes[0]);
eyeRenderDesc[1] = ovrHmd_GetRenderDesc(hmd, eyes[1]);

Cfg.OGL.Header.API = ovrRenderAPI_OpenGL;
Cfg.OGL.Header.Multisample = 0;
Cfg.OGL.Header.RTSize.w = hmdDesc.Resolution.w;
Cfg.OGL.Header.RTSize.h = hmdDesc.Resolution.h;
Cfg.OGL.WglContext = wglGetCurrentContext();
Cfg.OGL.Window = HWND(hwnd);
Cfg.OGL.GdiDc = wglGetCurrentDC();

int l_RenderCaps = 0;
int l_DistortionCaps = ovrDistortion_Chromatic | ovrDistortion_TimeWarp;

ovrHmd_ConfigureRendering(hmd, &Cfg.Config, l_RenderCaps, l_DistortionCaps, eyes, eyeRenderDesc);

EyeTexture[0].OGL.Header.API = ovrRenderAPI_OpenGL;
EyeTexture[0].OGL.Header.TextureSize.w = renderTargetSize.w;
EyeTexture[0].OGL.Header.TextureSize.h = renderTargetSize.h;
EyeTexture[0].OGL.Header.RenderViewport = eyes[0].RenderViewport;
EyeTexture[0].OGL.TexId = tid1;

EyeTexture[1].OGL.Header.API = ovrRenderAPI_OpenGL;
EyeTexture[1].OGL.Header.TextureSize.w = renderTargetSize.w;
EyeTexture[1].OGL.Header.TextureSize.h = renderTargetSize.h;
EyeTexture[1].OGL.Header.RenderViewport = eyes[1].RenderViewport;
EyeTexture[1].OGL.TexId = tid2;




NOTE:
Also using the SDK rendering seems to screw up OpenGL state something awful. My VBOs are stomped on and I need to re-upload the data each frame. :(

Any ideas?

    24 replies

    Inspiring
    May 14, 2014
    I was told the following by one of the engineers:
    Time-warp causes the CPU to busy-wait for GPU rendering to complete, which takes up about 20% of CPU time according to profiling.
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 16GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i Gigabyte RX Vega 64 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
    TeraBitAuthor
    Up and Coming
    May 14, 2014
    "cybereality" wrote:
    I was told the following by one of the engineers:
    Time-warp causes the CPU to busy-wait for GPU rendering to complete, which takes up about 20% of CPU time according to profiling.

    Ok, so it eats any available CPU between frames... Ok. It doesn't matter too much as long as it only eats what's left. :)

    There I was, monitoring the CPU usage to make sure I wasn't CPU limited on rendering and wondering why simple scenes were maxing out my render thread. :lol: Well, good to know that I need to turn off timewarp when I check that.

    Thanks for the info. :)
    Regards, Lee Page TeraBit Software
    Up and Coming
    May 14, 2014
    "cybereality" wrote:
    I was told the following by one of the engineers:
    Time-warp causes the CPU to busy-wait for GPU rendering to complete, which takes up about 20% of CPU time according to profiling.

    Thanks cyber, that explains it. Any plans on having an option to do an actual sleep rather than do a busy-wait? I'll have to disable timewarp otherwise.
    Virtual Desktop Developer
    Inspiring
    May 14, 2014
    The code in question is here.

    I'll see how hard it is to convert that to a sleep using a high resolution timer. C++11 has built in microsecond sleeping functionality, but I don't want to make the SDK depend on a C++11 compiler... yet.
    Brad Davis - Developer for High Fidelity Co-author of Oculus Rift in Action
    Inspiring
    May 14, 2014
    On Windows, the C++11 high_resolution_clock only has millisecond resolution.

    Not sure if the sleep_for() function is any better.
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 16GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i Gigabyte RX Vega 64 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
    Inspiring
    May 14, 2014
    "cybereality" wrote:
    Not sure if the sleep_for() function is any better.


    Edit:
    I just re-read your message and realized you probably meant 'any better' in the context of 'any better than millisecond resolution', not 'any better than a spinlock'. Disregard if that's the case. I'll investigate when I get home.

    Original message:
    Uh, better than this?


    while (newTime < absTime)
    {
    for (int j = 0; j < 50; j++)
    i = 0;

    newTime = ovr_GetTimeInSeconds();
    }


    Yeah, it will be. I guarantee you that std::this_thread::sleep_for and std::this_thread::sleep_until will not max out the CPU with a busy wait. Quite the opposite... they will drop the processor usage for the specified thread to 0. Quoth wikipedia:

    In general, however, spinning is considered an anti-pattern and should be avoided, as processor time that could be used to execute a different task is instead wasted on useless activity.
    Brad Davis - Developer for High Fidelity Co-author of Oculus Rift in Action
    Inspiring
    May 14, 2014
    Yes, I meant better than millisecond precision.

    In any case, I highly doubt we would add the C++11 requirement for our SDK any time soon.
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 16GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i Gigabyte RX Vega 64 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
    Up and Coming
    May 15, 2014
    Any plan on implementing a device driver connected to the GPU IRQ to avoid the busy wait and the 20% CPU overhead ?
    Participant
    July 9, 2014
    In general, however, spinning is considered an anti-pattern and should be avoided, as processor time that could be used to execute a different task is instead wasted on useless activity.


    This is certainly true; however, there are very few cases when it may become necessary to ensure specific timing constraints. As much as I hate the spin in this particular place, it seems like this is the one case where it may be justified.

    The problem with pre-TimeWarp spin logic is that it absolutely must resume in time to do timewarp rendering followed by Present. If we miss by just 1 or 2 ms, it may result in in skipped VSync and frame judder -- that is very obvious and very bad, especially with low persistence.

    The issue with Sleep() and any Windows resume based on time primitives is that they are tied to the OS scheduler, which has significantly higher granularity - I've heard of it being 15 ms or so. Even if this scheduling interval is lower on a newer OS versions, calling Sleep(1) is still equivalent to Sleep(1 + rand(x)) where 'x' is the length of the interval. Unfortunately, we can't rely on Sleep unless it can be guaranteed to resume with precision of 1 ms or so. I don't know how C++ 11 std::this_thread::sleep_for could do better then OS allows; my guess it will either just call OS or spin as we do, perhaps also utilizing the CPU 'pause' instruction.

    The best way to wait on a Windows is to block on a mutex or an event - such blocked threads are resumed and scheduled immediately after data is available (assuming there is an available core). Unfortunately, I do not know of any Event that is signaled at regular 1ms intervals. Perhaps our own Oculus IMU packets can be used; however, these now arrive in a service and frequently have +/- 3ms variability anyway. Perhaps we can do something with GPU interrupts, etc, but that is all advanced and non-standard - this is an area we plan to research.

    The way spin is implemented right now is benign from the rendering thread point of view: If you have a lot to render, it will not start untill you are done, and at that point it may no longer need to spin. So it shouldn't make your rendering slower. At the same time, it will "burn off" any extra time on that core. So our options are:
    - Leave it AS Is, perhaps adding "pause" instruction for better hyperthread efficiency.
    - Add a flag to remove the spin. If you use that, however, the Latency will go up significantly (by say 7 ms or so) in simpler scenes that currently rely on a spin.
    Participant
    July 10, 2014
    "mikeant" wrote:
    Unfortunately, I do not know of any Event that is signaled at regular 1ms intervals.


    In Windows, there are Waitable Timers. While the resolution you supply the wait time in is supplied in 100 ns increments, the effective frequency only seems to be 1 ms on my machine. This was tested with this code, lowering the amount of time to wait will cause it to miss its target.

    I also did a more stressful benchmark to see how it held up being used continuously since that's closer to how a game would use it. Here is the code, and the output below:

    timeToWait: 1000000 ns
    maxDelta : 3312 ticks
    frequency : 3312841 ticks/second
    Targets missed: 51660
    Targets met : 48340
    Average miss amount: 80 ticks
    Average miss amount: 24148 ns
    Press any key to exit...


    While it does miss the delta sometimes, it is not by very much. Interestingly, the average miss amount was 80 ticks for 100 iterations too, which makes it predictable.

    Obviously more testing would be necessary to see if this is a good fit for LibOVR, but this might be something to look into. I hope you find this useful!