/ Forums
New To The Forum? Click Here To Read The How To Guide. -- Developers Click Here.

OpenGL context management VS Oculus

eskileskil Posts: 18
edited February 2015 in PC Development
Hi

I'm having some issues with writing a Oculus plugin for a platform layer i have.

To explain my issue i need to explain a bit about my plugin interface. The platform layer opens a window and creates a openGL context, then once this is done it will look for plugins. Plugins can do all sorts of things but in this example all that matters is rendering. When a plugin gets initialized, if can tell the API that it wants to intercept the applications rendering. When this call is made the Platform layer will create an additional OpenGL context and use wglShareLists to link it to the openglContext linked to the window. Then the once the plugin is activated, the plugin will take over the main rendering look, and can trigger the applications main render loop as many times as it likes and then present the result to the screen. The API intercepts FrameBufferBinds so that the application actually draws to a texture when it binds FBO 0, (Kind of nifty right? :-))

I have written a fair bunch of plugs for this to do color correction, and DK1 pluging among other things, but i cant get it to work with the new API. The issue I'm having is that it works on screen but it doesn't show up in the HMD. I assume that the rendering is working since it is warping and tracking correctly, but is unable to capture the image for some reason.

Right now the order of things are like this:

-OpenWindow.
-Create a GL Context /* WONT BE USED BY OCULUS! */
-ovr_Initialize()
-ovrHmd_Create();
-Create the GL Context the oculus renderer will use.
-ovrHmd_AttachToWindow();
-ovrHmd_ConfigureRendering
-create my textures in the oculus context.

Is this wrong, and if so how can it be wrong? I do create the window before i run ovr_Initialize, but I'm not giving ovr access to it until later and i am creating the context that will be used later. ovr shouldnt be able to care if i have an other open gl context. I'm assuming that ovr needs to create its own context and use wglShareLists, so it would matter that it gets access to the render context before the textures are created. I'm a bit lost here. If you like i can send you source code. I would be very interested to know how the capturing of the image has been implemented.

Cheers

E

Side note: the 64bit service exe crashes, the 32 bit works, im running 64 bit windows, a 64 bit app and all demos work fine.

Comments

  • jhericojherico Posts: 1,417
    Nexus 6
    The Ouclus runtime actually integrates with the OpenGL driver, most likely overriding some functions. Because of this, it's going to be virtually impossible to get a stable application where some OpenGL contexts are created before ovr_Initialize and some are created after.

    In order to do what you're trying to do you'll need to iterate over the plugins so that they can trigger the call to ovr_Initialize before creating the first GL context.
    Brad Davis - Co-author of Oculus Rift in Action - Like us on Facebook
    Rifty Business - A blog on software development for the Rift.
    bdavis_cover_tiny.jpg
  • eskileskil Posts: 18
    Can somebody in detail explain how Oculus integrates with windows and OpenGL? What is it actually doing?

    Cheers

    E
  • kojackkojack Posts: 3,115 Volunteer Moderator
    eskil wrote:
    Can somebody in detail explain how Oculus integrates with windows and OpenGL? What is it actually doing?
    Most of the lower level details aren't known, since that's in the binary only driver they won't let us look at.

    However what does happen is the oculus sdk intercepts the following win32 functions: LoadLibraryA, LoadLibraryW, LoadLibraryExA, LoadLibraryExW, GetModuleHandleExA, GetModuleHandleExW.
    It then monitors any call to them for the following system libraries: dxgi.dll, d3d9.dll, d3d11.dll, dxgidebug.dll, d3d10core.dll, d3d10.dll, opengl32.dll. If one of them is being loaded, it gets replaced with an oculus library that takes over certain functions to allow stuff like direct mode.

    This is why order can matter in initialising, if opengl is loaded before oculus takes over the loadlibrary calls, then you have the normal opengl instead of the oculus opengl.
  • eskileskil Posts: 18
    Shouldn't someone form oculus be here and be able to answer this?
  • cyberealitycybereality Posts: 20,661 Oculus Staff
    Sorry for the delay.

    First, make sure that you call the following function before you set up any of the other stuff you're doing.
    ovr_InitializeRenderingShim();
    

    Also, watch out because framebuffer 0 isn't the backbuffer when the Oculus shims are loaded.
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 32GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i
    PowerColor RX 480 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
  • eskileskil Posts: 18
    I tried to use the ovr_InitializeRenderingShim(); but it still doesn't work. Ive done loads of testing and I think I have some clues. I tried initializing OVR in the main application, before i do anything else, and then start the window and activate the plugin. But then the plugin refuses to give me anything and trows out an error telling me i haven't initialized OVR. Apparently the initialization in the application does not carry over to the DLL. So i try to do it the other way and move the context creation to the DLL (In the past the DLL would ask the main app to create a context for it), and it still doesn't work. Maybe it cant find the window that is being created in the EXE, but hey, I'm giving it the handle! So for as far as i can tell ALL context creation, window opening and OVR setup has to be done in the same EXE and you cant do anything in a DLL. Well possibly you can do it in a DLL but then EVERYTHING has to happen in that DLL.

    This makes the OVR API utterly broken for anyone trying to support Oculus using some sort of plugin interface. I really dislike the design of an API that is trying to be "smart" and do things under the table, padding me on the head with a "Don't you worry". Well I want to know what the API is doing! I don't mind if i have to jump through hoops to make it work, just give me a API that gives me the hoops i need!

    Can you please tell me what the API does under the hood?

    You can download my source, my EXE and my DLL here: http://www.quelsolaar.com/oculus_test.zip

    Cheers

    E
  • cyberealitycybereality Posts: 20,661 Oculus Staff
    I'll try to take a look at the code later today and see if I find anything.
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 32GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i
    PowerColor RX 480 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
  • eskileskil Posts: 18
    Thanks!
  • cyberealitycybereality Posts: 20,661 Oculus Staff
    Can you provide me with the VS solution file, or some way I can build on my Windows machine?

    Just taking a quick look at the code, I see you call "ovr_InitializeRenderingShim" directly before "ovr_Initialize". However, you may want to call "ovr_InitializeRenderingShim" earlier in the code before you start initializing OpenGL.

    If I could build the app, I could probably look into it further.
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 32GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i
    PowerColor RX 480 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
  • kojackkojack Posts: 3,115 Volunteer Moderator
    There's no need to call them individually if there's no gap between them. ovr_initialize includes the same functionality as ovr_initializerenderingshim (all ovr_initializerenderingshim does is call OVR::System::DirectDisplayInitialize(), which ovr_initialize also calls).
    The purpose of calling ovr_initializerenderingshim manually is to set up the render shim (must be done before any opengl use by the program) without creating all the other oculus stuff too, then call ovr_initialize later to finish the start up.
  • jfehjfeh Posts: 17
    Sorry for the delay.

    First, make sure that you call the following function before you set up any of the other stuff you're doing.
    ovr_InitializeRenderingShim();
    

    Also, watch out because framebuffer 0 isn't the backbuffer when the Oculus shims are loaded.

    Hi,

    Could you please elaborate on the latter point ?
    Is it a global side effect (i.e. in a process that has called "ovr_InitializeRenderingShim" at its start-up, will all the OpenGL context further created won't have their default framebuffer referenced by the index 0 regardless of their window being attached or not to the HMD) ?

    I am having an issue when trying to bind the default framebuffer on the OpenGL context that serves my main window (this window being attached to the Rift via "ovrHmd_AttachToWindow").
    Up till the first call to "ovrHmd_GetEyePoses " or "ovrHmd_EndFrame", I can successfully rebind my default framebuffer. However, as soon as one of the 2 previous functions have been called, calling glBindFramebuffer(GL_FRAMEBUFFER, 0) returns with no error, but when querying the current framebuffer with "glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &fbo)" I get constantly a result of "2". What made me realize the latter was a call to glReadBuffer(GL_FRONT) (same for GL_BACK) that failed with a GL_INVALID_OPERATION as any framebuffer of non zero index is an FBO, and thus only COLOR_ATTACHMENT_$i are valid queries.
    It is as if the OpenGL context had "lost" its default framebuffers at runtime (note : as Nsight can not be launched when libOVR is initialized, I cannot truly analyze the situation, any suggestions are welcome for proper OpenGL profiling with the Rift).

    If you do have an explanation, I would be really grateful as understanding this point is of great importance regarding the integration of the DK2 in our software.

    As to why am trying to do so ? I realized that when attaching the window to the HMD via "ovrHmd_AttachToWindow", one has to configure rendering with config.OGL.Header.BackBufferSize set to the window size and not the optimal Rift resolution (1920*1080) :
    - Setting the Rift to optimal resolution (BackBufferSize = {1920,1080}) and attaching it to a smaller window clips/truncates the 2 distorted views to the window's viewport (i.e. no stereoscopy i.e. rubbish in HMD). So obviously, no minification is done inside libOVR.
    - If the window is smaller than the Rift's optimal resolution but the Rift is configured in accordance (BackBufferSize = {window.w,window.h}), stereoscopy operates but rendering quality degrades (screen space undersampling).

    So in order to benefit from full HMD resolution and thus optimal rendering quality without being constrained to show on screen a window of 1920*1080, I tried to render to the Rift via a dedicated hidden window which will always be in the optimal resolution (hmd->Resolution).
    If mirroring of the 2 views is required by the application (because it rocks), one can copy to texture the Rift's framebuffer for further texture mapping the full viewport of another -visible- window (e.g. an OpenGL widget of 800*600 inside a full UI).
    This should be possible as when tracing "ovrHmd_ConfigureRendering" and "ovrHmd_EndFrame" we can see that an OpenGL context is created by libOVR for distortion rendering, this context sharing the data with our original context passed inside the ovrGLConfig structure.
    However, as we can not trace "ovrHmd_AttachToWindow" (socket serialization towards the service), we can not know how the HWND of the attached window is used. Does it have to have an OpenGL context ? Or for example will the service set an adequate PFD format and create a shared context with the distortion context (for accessing the distorted view internal textures) ? Is the content of the attached window copied at each frame to the native framebuffer of the Rift (this would explain the previous undersampling/truncation)? Or is the attached window "physically" bound to the hardware (i.e. no copy) ?
    Any information regarding the internals of the "ovrHmd_AttachToWindow" that would help proper SDK use would be greatly appreciated.

    Thanks for your support (and reading this too long post :)
  • eskileskil Posts: 18
    I have Posted a new version that includes two projects and at the source code here:
    http://www.quelsolaar.com/oculus_test.zip

    The application activates the Oculus mode with F1 and quits with "q". Note that once you have built the DLL you have to move it to the directory that runs the test application. I have left a copy there already.

    All oculus related code is in betray_plugin_oculus_rift2.c, and at the point where this plugin gets initialized, the window has been opened, and a context has been created. When the plugin calls betray_plugin_callback_set_image_warp a new context gets created exclusively for the oculus plugin. The plugin will never touch or make use of any other oculus. To be clear the code that creates this context is in the EXE and is then handed back to the DLL its not created in the DLL. (Creating it in the DLL doesnt help by the way i have tried)

    I hope this helps.

    Cheers

    E
  • jfehjfeh Posts: 17
    As this topic was started by eskil, I will create a new topic dedicated to my specific issue (sorry if I overstepped on your topic eskil).
    However, cybereality, could you please elaborate on the point you previously mentionned :
    "Also, watch out because framebuffer 0 isn't the backbuffer when the Oculus shims are loaded."

    Where is the backbuffer when the shims are loaded (is it an fbo index ?) ?
    How can we retrieve its content (which is the specific topic that I wanted to address) ?

    Thanks,
    Jeff.
  • eskileskil Posts: 18
    Is anyone form oculus around? I was told to give you projects, so i did. Will you take a look at them?

    E
  • cyberealitycybereality Posts: 20,661 Oculus Staff
    I did take a quick look at the code, but honestly I was having trouble figuring out how it was supposed to work or even what I was looking at. I can see if one of the other guys more familiar with OpenGL can look at it.
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 32GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i
    PowerColor RX 480 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
  • eskileskil Posts: 18
    If you can find someone i can always give more help over mail or skype. You can reach me at eskil at obsession dot se.
  • eskileskil Posts: 18
    Well great! Now i have tied to uninstall Oculus and that has broken my AMD graphics driver by messing with the drives registry. Uninstalling and and reinstalling does not help. Thanks oculus! Can you please in the future limit yourselves to writing your own broken software and not try to break other peoples software too?
  • jfehjfeh Posts: 17
    Cybereality,

    I would appreciate an answer regarding what you previously said :
    Also, watch out because framebuffer 0 isn't the backbuffer when the Oculus shims are loaded.

    Even though it helps a bit (in a way) to know that 0 is not the default framebuffer, it would be even more useful -and a lot less frustrating- to us developpers to know what is the default framebuffer's index after loading the shims, or how to retrieve it.

    Jeff.
  • cyberealitycybereality Posts: 20,661 Oculus Staff
    @eskil: See the post here on how to fix a failed driver uninstall:

    viewtopic.php?f=34&t=19343&p=237425#p237425
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 32GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i
    PowerColor RX 480 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
  • eskileskil Posts: 18
    I managed to figure it out by searching my registry. Still cant get my code to run...
  • eskileskil Posts: 18
    So I have just spent another day on this and I'm not getting anywhere. I have tried 0.4.3 and 0.4.4, i have tried on AMD (my main dev machine) with latest drivers and 14.4 drivers and I'm now trying to get it to work on a nVidia machine, but its "waiting for camera" and the service doesn't run on that machine. The service does run on my main machine but only the x86 version (despite the OS being x64), bot the 64 bit version and the launcher crashes. I have removed all my multiple contexts and written a very straight forward implementation, still doesnt work. I have moved around all calls and tried all kinds of combinations of ordering becoming increasingly unlikely to be right. My application is pure C and doesn't link to any external libs beyond windows and openGL. Tracking is working fine, and so is the rendering in the window, (it warps correctly and even shows the health warning) but nothing shows up in the HMD. The HMD flashes for a split second when the application starts, so its getting some kind of initialization. The demo scene in the Oculus Configuration Utility works fine, and shows up in the display.

    I don't know what more to do.

    I know that the people from oculus answering questions in this forum aren't necessarily the people responsible for the implementation of OVR, and any negative vibe you get from me is purely a result of my frustration and is in no way directed at anyone personally. I'm just trying to get some kind of clue as to why its not working. I really want Oculus to succeed.
  • sebjfsebjf Posts: 5
    Virtual Boy (or Girl)
    Hi, 

    Could someone confirm whether this behaviour (hooking OpenGL) still occurs in the latest SDKs? (1.3.0)

    I am also trying to integrate the Oculus SDK with an existing platform via a plugin, and am encountering very odd behaviour that does not occur when I move the code into one of the SDK samples.

    (Eskil, if you still receive notifications on this thread, did you ever get your application working?)

    Sj

Sign In or Register to comment.