Stereo3D implementation in DirectX

Started by
1 comment, last by Eti307 15 years, 10 months ago
Hi all, We have a stereoscopic environment using OffAxis projection and stereo3d viewing in OpenGl right now. We want to port it into directx so we can use the new game technologies (like Unreal Engine 3). In openGL you can have quadbuffers so stereo is easily implemented.. but in directx you only have access to one frontbuffer. I tried multiple ways to implement stereoscopic view in directx. I have a directx wrapper intercepting every directx call and applying the offaxis on the transform matrix (that works fine) but for the stereo it's a little more complicated. The main problem is that we must have the framerate locked at 96Hz, preventing any flickering. Right now the application on it's own can't draw the frames fast enough. I can only intercept the Present call so I can't go optimize the drawing sequence. I had to find another way to stabilize the framerate. What I've been trying to do is having the application device and another thread device running on 2 different adapters. I intercept the application's present call, get the backbuffer and copy it in a direct3d surface in the memory. Then the thread gets that surface (either right or left eye) update his corresponding buffer and call his own present. The thread is basically controlling the rendering to the screen, while the application is feeding it frames. To compensate for the lack of frames, the thread will present the last frame until a new one is ready, so we always have a frame to present at each screen refresh. (by the way I'm using directx8 for now, once we have everything working with our current application we'll make the transition to directx9) Now here's the real problem: the operation of copying the application's backbuffer into a shared memory is demanding, while it's doing that the application can't begin to draw it's new frame (the code is added right before the present call is done). So there's a real slowdown in performance. While the screen is running at 60fps (the tests are done at 60Hz for now), the game itself is at a mere 12-15fps. So the game appears to be real slow and choppy. Anyone tried something similar before? Any idea on how it can be done? My goal is to have a 96Hz stereo3d display, maybe this is the wrong approach and I'm completely sidetracked but I'm pretty new with directx so I might have missed some important features :) My next try will be to try to have another thread doing the application's buffer copy so the application will be good to begin drawing it's next frame right away, I don't know if it's doable... I'll try nonetheless. If you guys have any idea on how to make this work it would be greatly appreciated Thank You, Etienne
Advertisement
With more testing I think the problem is that even if I have a thread dedicated to copy the frame from the card to a shared memory, that thread is still using the same device as the application... So it doesn't change the fact that the application is waiting for the copy to finish.

Basically what I'm doing (keep in mind this is directx8):
- Copy the application's backbuffer to a surface.
- Lock that surface
- memcpy the rect from the surface owned by device#1 to another owned by device#2 (the thread)
- Unlock
- Copy that device#2 surface into it's backbuffer
- Present.

Now even if the memcpy is done by another thread, the application isn't drawing any faster. Is this caused because the locked surface is still on the same device as the application? Is it actually possible to do this kind of thing?

If I could I would've just check if the scene is completely drawn in 1/96sec and if not present the last frame... but I have no control over the drawing since I'm not the one doing it (I'm hooking the d3d calls)
Oh well just by enabling triple buffering the problem went away on it's own, no need for any of those threads. But that's linked to the computer performance. We wanted something generic that could work on any scene, no matter how complex it is.

I'm now switching to Directx9 and will have to tackle the same problem soon ;) But DirectX9 seems to have more functions permitting surface copies (UpdateSurface, GetRenderTargetData, etc)

I'll experiment with that soon

This topic is closed to new replies.

Advertisement