Skip to main content
Up and Coming
March 20, 2019

wglDXRegisterObjectNV returns 0 but no error ( NV_DX_interop2 )

Has anyone successfully added NV_DX_interop2 functionality to a PC Win10 OVR SDK app with NVIDIA GTX 1080 GPU?  Just to be clear, my goal is to be able to execute arbitrary GL code and have it
write to the DX eye render targets, with the proper wglDXLockObjectsNV()
and wglDXUnlockObjectsNV() surrounds.


The problem I am having is that when I call

gl_handles[0] = wglDXRegisterObjectNV(gl_handleD3D, dxColorbuffer,  gl_names[0], GL_RENDERBUFFER,  WGL_ACCESS_READ_WRITE_NV);

the handle is set to 0, but there is no error detected by GetLastError();  So, I have 2 renderbuffer objects, color and depth, that are derived from the OVR eye render targets/buffers.  The dxColorbuffer object appears correct, as does the dxDepthbuffer object.  The call succeeds on the dxDepthbuffer object and sets the handle to a non-null value.

I think I am doing all the required steps correctly, including:

gl_handleD3D = wglDXOpenDeviceNVFunc((void *)((OVR::Render::D3D11::RenderDevice*)pRender)->Device); 
glGenFramebuffers(2, gl_fbonames);
glGenRenderbuffers(2, gl_names);
gl_handles[0] = wglDXRegisterObjectNV(gl_handleD3D, dxColorbuffer, gl_names[0],   GL_RENDERBUFFER,      WGL_ACCESS_READ_WRITE_NV);

... subsequent calls such as glBindFramebuffer(), etc. are present but not shown.

Thanks.












    57 replies

    knchaffinAuthor
    Up and Coming
    April 16, 2019
    @thewhiteambit

    I have everything set up to do the interop in the way that you suggested, but so far when I use DeviceContext->CopyResource(pDst, pDXtexture)
    I'm not getting anything rendered.  For testing, I am trying to just copy the empty pDXtexture to the destination without having GL render to it.  My expectation is that it should replace what is in the pDst texture when I do this as I am not using a depth texture.  I have also let the GL code clear the DX texture to an opaque red, to no avail. 

    I have tried several pDst textures:

    ID3D11Texture2D *pDst;

    pDst=Device->BackBuffer, and
    Device->BackBufferRT->GetResource(pDst), and

    IDXGISwapChain *dxswapchain = Device->SwapChain;
    dxswapchain->GetBuffer(0, IID_ID3D11Texture2D, (void **)&pDst);  and

    ovrTextureSwapChain oTSC = Device->CurRenderTarget->Get_ovrTextureSet();
    ovr_GetTextureSwapChainBufferDX(Session, oTSC, 0, IID_ID3D11Texture2D, (void **)&pDst);  // and other indices 1 and 2

    All textures have been confirmed to have the same format and dimensions.

    I can call:
    Device->Clear(1.0, 0.0, 0.0, 1.0, 1, 1);
    to clear the BackBufferRT render target view to opaque red, and that seems to work correctly depending where I call it relative to the 3 "~layers" I am rendering.  Those layers are the Tuscany scene and/or my OVRvision Pro video, the two Touch controllers, and then the interop GL layer.

    I'm somewhat at a loss as to what is going on.

    What do you use for the CopyResource() destination texture in your interop applications?

    I'm sure I am doing something stupid.

    Thanks.





    Inspiring
    April 16, 2019
    @knchaffin
    I am using CopySubresourceRegion() but just for convenience. CopyResource() also works. Did you manage to use the GL interop textures in DX space (for example as a shader resource while rendering), so you can be sure it's the copy operation failing? Sorry to not be very specific, I implemented this long time ago. But I still remember Copy operations often resulting in only black textures. Maybe you want to fill the destination texture with Blue in advance, so you can see if the read of the copy operation just had it reading wrong and interpret it as Black, or if it does not perform write at all. With CopySubresourceRegion you also can try to copy only a little part in the center then.
    knchaffinAuthor
    Up and Coming
    April 19, 2019
    @volgaksoy
    @thewhiteambit

    I followed your advice and created my own ID3D11Texture2D render target/shader resource texture of the same format and size of the OVR final render targest (backbuffer, current render target, swap chain members, etc).  I also initialized this DX texture with a checkerboard data pattern in CreateTexture().  For testing purposes I'm trying to make sure I can copy this texture to the OVR final render texture(s) before registering it with GL via the interop functionality, although I have successfully registered it in tests.  I have tried using Context->CopyResource() and Context->CopySubResourceRegion() to every variant of the OVR final render target textures I can think of and verified that those texture formats and dimensions match my DX texture.  The problem is that I never see the checkerboard texture in the final output.  I can successfully clear the render target color to opaque red via:
    D3D11Device->Clear(1.0, 0.0, 0.0, 1.0, 0.0, true, false);
    which actually ends up clearing D3D11Device->CurrRenderTarget->GetRtv().  So, I made sure that one variant for my CopyResource() is to destination D3D11Device->CurrRenderTarget->GetRtv()->GetResource()

    Do either of you know which OVR render target I should copy to and if this should work?  Is there anything else I may need to do to make this work?  This is not an interop issue, but rather an issue of copying pure DX textures to OVR render target textures.

    Thanks in advance.







    Inspiring
    April 19, 2019
    @knchaffin
    You are probably running into non compatible texture formats for simple blit copying. I know there is somewhere a huge table in DX documentation explaining all compatible texture formats. But I couldn't find them.

    Or did you just switch the parameter order on CopyResource? Is uses a counter intuitive way of destination first, then source...
    knchaffinAuthor
    Up and Coming
    April 19, 2019
    @thewhiteambit

    I agree that pDst and pSrc argument order is counter intuitive, but I do have them correct.

    Both the source and destination textures are
    DXGI_FORMAT_R8G8B8A8_UNORM
    The DX documentation does not limit the formats that can be used with CopyResource() but rather requires that the formats be "compatible" if a format conversion is required.  E.G.., the texel sizes are 32 bits in both.
    Inspiring
    April 19, 2019
    @knchaffin
    just trying to guess why a simple copy can fail. What other flags/parameters do you use for creation of the source and destination texture(s)?
    knchaffinAuthor
    Up and Coming
    April 19, 2019

    ID3D11Texture2D* d3d_colortex_;

    const int w = 1600;
    const int h = 900;
    if (CurrRenderTarget)
    {
    // w=CurrRenderTarget->GetWidth();
    // h=CurrRenderTarget->GetHeight();
    debug_trace("CurrRenderTarget w=%d h=%d", w, h);
    }
    // Create DX surface with dimensions of CurrRenderTarget
    D3D11_TEXTURE2D_DESC desc;
    ZeroMemory(&desc, sizeof(desc));
    desc.Height = h;
    desc.Width = w;
    desc.MipLevels = 1;
    desc.ArraySize = 1;
    desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // A four-component, 32-bit unsigned-normalized-integer format that supports 8 bits per channel including alpha.
    desc.SampleDesc.Count = 1;
    desc.SampleDesc.Quality = 0;
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.BindFlags = 0;
    desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
    desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
    desc.CPUAccessFlags = 0;
    desc.MiscFlags = 0;

    HRESULT hr=deviceD3D11->CreateTexture2D(&desc, NULL, &d3d_colortex_);
    @thewhiteambit

    The above is my DX texture creation code without the checkerboard data initialization.  Note, I have sRGB turned off in the app.  The OVR rendertargets were created by OVR in the default initialization steps, but with sRGB turned off.  I'm using the OculusWorldDemo app framework, with the /Samples/CommonSrc/Render/Render_D3D11_Device.cpp code included in the VS2017 project..  The DX texture desc values were selected to match obtained desc/format of the OVR render color target (or backbuffer, or swap chain textures as they all are verified to have the same desc/format values)..




    Inspiring
    April 19, 2019
    @knchaffin
    The texture desc seems ok. Have you tried if copying works without registering the textures for GL interop?
    knchaffinAuthor
    Up and Coming
    April 19, 2019
    @thewhiteambit
    Yes, that is what I am doing.  I tested the interop registration and it succeeds, but I commented that out for testing the resource copying.

    I suspect that I am trying to copy to the wrong OVR final render target texture.  For testing I am not using any eye views or RT's but rather just using the single DX texture I created and trying to copy it to the:
    ovrD3D11device class object members as defined in CommonSrc/Render_D3D11_Device.h:
    Ptr<IDXGISwapChain> SwapChain (GetBuffer(0,)); or
    Ptr<ID3D11Texture2D> BackBuffer; or
    Ptr<ID3D11RenderTargetView> BackBufferRT; or
    Ptr<Texture> CurRenderTarget; ( CurRenderTarget->GetTex()) or          (CurRenderTarget->GetRtv()->GetResource(&ppResource1) 

    For each destination test, I make sure the DX texture description matches as the RTV based textures have different width and height than the other textures.

    Or the OVR runtime is locking the textures or something similar.




    knchaffinAuthor
    Up and Coming
    April 19, 2019
    @thewhiteambit

    I think only the BackBuffer and SwapChain textures make any sense to try to copy to as I think the RenderTargetViews GetResource() calls only return the resource from which the RTV was constructed and the RTV's are only accessed via the pipeline to which they are set via Context->OMSetRenderTargets() .  So I'm hoping the CopyResource to the Backbuffer or device SwapChain happens independent  of the RTV's .  Does this make sense?