| Name |
| |
| NV_DX_interop |
| |
| Name Strings |
| |
| WGL_NV_DX_interop |
| |
| Contributors |
| |
| Michael Gold, NVIDIA |
| Nuno Subtil, NVIDIA |
| |
| Contact |
| |
| Nuno Subtil, NVIDIA Corporation (nsubtil 'at' nvidia.com) |
| |
| Status |
| |
| Complete. Shipping with NVIDIA release 265 drivers, November 2010. |
| |
| Version |
| |
| Last Modified Date: 10/11/2010 |
| Revision: 1 |
| |
| Number |
| |
| 407 |
| |
| Dependencies |
| |
| OpenGL 2.1 is required. |
| |
| Overview |
| |
| This extension allows OpenGL to directly access DirectX buffers |
| and surfaces. A DirectX vertex buffer may be shared as an OpenGL |
| buffer object and a DirectX surface may be shared as an OpenGL |
| texture or renderbuffer object. |
| |
| New Procedures and Functions |
| |
| BOOL wglDXSetResourceShareHandleNV(void *dxObject, HANDLE shareHandle); |
| |
| HANDLE wglDXOpenDeviceNV(void *dxDevice); |
| BOOL wglDXCloseDeviceNV(HANDLE hDevice); |
| HANDLE wglDXRegisterObjectNV(HANDLE hDevice, void *dxObject, |
| GLuint name, GLenum type, GLenum access); |
| BOOL wglDXUnregisterObjectNV(HANDLE hDevice, HANDLE hObject); |
| BOOL wglDXObjectAccessNV(HANDLE hObject, GLenum access); |
| BOOL wglDXLockObjectsNV(HANDLE hDevice, GLint count, HANDLE *hObjects); |
| BOOL wglDXUnlockObjectsNV(HANDLE hDevice, GLint count, HANDLE *hObjects); |
| |
| New Tokens |
| |
| Accepted by the <access> parameters of wglDXRegisterObjectNV and |
| wglDXObjectAccessNV: |
| |
| WGL_ACCESS_READ_ONLY_NV 0x0000 |
| WGL_ACCESS_READ_WRITE_NV 0x0001 |
| WGL_ACCESS_WRITE_DISCARD_NV 0x0002 |
| |
| Additions to the WGL Specification |
| |
| OpenGL may directly access textures, surfaces and buffers created |
| by DirectX. A DirectX device is prepared for interoperability |
| by calling |
| |
| HANDLE wglDXOpenDeviceNV(void *dxDevice); |
| |
| <dxDevice> is a pointer to a supported Direct3D device |
| object. Supported devices are listed in the wgl.devicetypes table, |
| along with applicable restrictions for each device. The return |
| value is a handle to a GL/DirectX interop device. |
| |
| When wglDXOpenDeviceNV fails to open a Direct3D device, NULL is |
| returned. To get extended error information, call GetLastError. |
| Possible errors are as follows: |
| |
| ERROR_OPEN_FAILED Could not open the Direct3D device. |
| |
| ERROR_NOT_SUPPORTED The <dxDevice> is not supported. |
| This can be caused either by passing in |
| a device from an unsupported DirectX |
| version, or by passing in a device |
| referencing a display adapter that is |
| not accessible to the GL. |
| |
| Calling this entrypoint with an invalid <dxDevice> pointer results |
| in undefined behavior and may result in data corruption or program |
| termination. |
| |
| Versions of the operating system that support the Windows Display |
| Driver Model (WDDM) support a sharing mechanism for DirectX |
| resources that makes use of WDDM share handles. The application may |
| obtain a share handle from the operating system to share a surface |
| among several Direct3D devices. |
| |
| This extension accommodates, but does not require use of WDDM share |
| handles. An application should only obtain a WDDM share handle at |
| resource creation time if it will share the resource with non-GL |
| clients. |
| |
| As of today, all versions of Microsoft Windows starting with Windows |
| Vista use the Windows Display Driver Model, enabling the usage of |
| WDDM share handles. |
| |
| If the application wishes to share a DirectX version 9 resource |
| under a WDDM operating system, it is required that the Direct3D |
| device that owns the resource be a Direct3D9Ex device. |
| |
| ------------------------------------------------------------------------- |
| DirectX device type Device Restrictions |
| ------------------------------------------------------------------------- |
| IDirect3DDevice9 can not be used on WDDM operating systems; |
| D3DCREATE_MULTITHREADED behavior flag must be |
| set at device creation time |
| |
| IDirect3DDevice9Ex D3DCREATE_MULTITHREADED behavior flag must be |
| set at device creation time |
| ------------------------------------------------------------------------- |
| Table wgl.devicetypes - Valid device types for the <dxDevice> parameter of |
| wglDXOpenDeviceNV and associated restrictions. |
| ------------------------------------------------------------------------- |
| |
| If the application wishes to share a DirectX resource with GL and |
| non-GL clients, it should request a share handle for the |
| resource. It must also call |
| |
| BOOL wglDXSetResourceShareHandleNV(void *dxResource, HANDLE shareHandle); |
| |
| to associate the share handle with the DirectX resource prior to |
| registering it with the GL. <dxResource> is a pointer to the DirectX |
| resource that will be shared, <shareHandle> contains the share |
| handle that the OS generated for the resource. |
| |
| The return value for wglDXSetResourceShareHandleNV is FALSE if |
| this function is called more than once for any resource; called |
| with an invalid <shareHandle> parameter; or called for a resource |
| that is already being shared with the GL; otherwise, the return |
| value is TRUE. On a version of the OS that does not support WDDM, |
| calling wglDXSetResourceShareHandleNV returns TRUE but has no |
| effect. |
| |
| Results are undefined if the <dxResource> pointer is invalid and |
| may result in data corruption or program termination. |
| |
| Calling |
| |
| HANDLE wglDXRegisterObjectNV(HANDLE hDevice, void *dxResource, |
| GLuint name, GLenum type, GLenum access); |
| |
| prepares a DirectX object for use by the GL. <hDevice> is a |
| GL/DirectX interop device handle, as returned by wglDXOpenDeviceNV. |
| |
| <dxResource> is a pointer to a DirectX resource to be registered |
| with the GL. The resource must be of one of the types identified in |
| table wgl.objtypes and must also obey the restrictions specified for |
| that resource in table wgl.restrictions. |
| |
| <type> identifies the GL object type that will map to the DirectX |
| resource being shared and must be one of the types enumerated in |
| table wgl.objtypes. <name> is the GL object name to be assigned |
| to the DirectX resource in the namespace of the objects identified |
| by <type> in the current GL context. The valid combinations of |
| <type> and <dxResource> are described in table wgl.objtypes. |
| |
| <access> indicates the intended usage of the resource in GL and must |
| be one of the following: |
| |
| WGL_ACCESS_READ_ONLY_NV indicates that GL will read the |
| DirectX resource but will not modify it. If GL attempts to |
| modify the data store of the resource, the result is undefined |
| and may include program termination. |
| |
| WGL_ACCESS_READ_WRITE_NV indicates that GL may read or write |
| the data store of the resource. |
| |
| WGL_ACCESS_WRITE_DISCARD_NV indicates that any previous |
| contents of the object may be discarded and GL may write to |
| the resource. Any data written by GL may be reliably read in |
| subsequent operations. The result of subsequently reading |
| data outside the region written by GL is undefined. |
| |
| If the call is successful, the return value is a handle to a |
| GL/DirectX interop object. A return value of NULL indicates that |
| an error occurred. To obtain extended error information, call |
| GetLastError. Possible errors are as follows: |
| |
| ERROR_INVALID_HANDLE No GL context is made current to the |
| calling thread. |
| |
| ERROR_INVALID_DATA Incorrect <name> <type> or <access> |
| parameters. |
| |
| ERROR_OPEN_FAILED Opening the Direct3D resource failed. |
| |
| Calling wglDXRegisterObjectNV with an invalid <hDevice> handle |
| results in undefined behavior and may result in data corruption or |
| program termination. |
| |
| If the application explicitly requests a share handle for a |
| DirectX resource, results are undefined (and may result in data |
| corruption, incorrect DirectX operation or program termination) if |
| wglDXRegisterObjectNV is called before calling |
| wglDXSetResourceShareHandleNV for the same resource. This |
| restriction does not apply to non-WDDM operating systems. |
| |
| -------------------------------------------------------------------------- |
| <type> type of <name> Valid DirectX resource types |
| -------------------------------------------------------------------------- |
| TEXTURE_2D texture IDirect3DSurface9 |
| IDirect3DTexture9 |
| |
| TEXTURE_3D texture IDirect3DVolumeTexture9 |
| |
| TEXTURE_CUBE_MAP texture IDirect3DCubeTexture9 |
| |
| TEXTURE_RECTANGLE texture IDirect3DSurface9 |
| IDirect3DTexture9 |
| |
| RENDERBUFFER renderbuffer IDirect3DSurface9 |
| |
| NONE buffer IDirect3DIndexBuffer9 |
| IDirect3DVertexBuffer9 |
| -------------------------------------------------------------------------- |
| Table wgl.objtypes - Valid values for the <type> parameter of |
| wglDXRegisterObjectNV and associated object types for GL and |
| DirectX. |
| -------------------------------------------------------------------------- |
| |
| -------------------------------------------------------------------------- |
| Resource Type Resource Restrictions |
| -------------------------------------------------------------------------- |
| IDirect3DSurface9 Must not be lockable |
| |
| IDirect3DTexture9 Memory pool must be D3DPOOL_DEFAULT |
| |
| IDirect3DCubeTexture9 Memory pool must be D3DPOOL_DEFAULT |
| |
| IDirect3DVolumeTexture9 Memory pool must be D3DPOOL_DEFAULT |
| |
| IDirect3DVertexBuffer9 Memory pool must be D3DPOOL_DEFAULT |
| |
| IDirect3DIndexBuffer9 Memory pool must be D3DPOOL_DEFAULT |
| |
| -------------------------------------------------------------------------- |
| Table wgl.restrictions - Restrictions on DirectX resources that can |
| be registered via wglDXRegisterObjectNV |
| -------------------------------------------------------------------------- |
| |
| Before a GL object which is associated with a DirectX resource may |
| be used, it must be locked. The function |
| |
| BOOL wglDXLockObjectsNV(HANDLE hDevice, GLint count, |
| HANDLE *hObjects); |
| |
| attempts to lock an array of <count> interop objects. <hObjects> |
| is an array of length <count> containing the handles of the |
| objects to be locked. |
| |
| A return value of TRUE indicates that all objects were |
| successfully locked. A return value of FALSE indicates an |
| error. To get extended error information, call |
| GetLastError. Possible errors are as follows: |
| |
| ERROR_BUSY One or more of the objects in <hObjects> |
| was already locked. |
| |
| ERROR_INVALID_DATA One or more of the objects in <hObjects> |
| does not belong to the interop device |
| specified by <hDevice>. |
| |
| ERROR_LOCK_FAILED One or more of the objects in <hObjects> |
| failed to lock. |
| |
| If the function returns FALSE, none of the objects will be locked. |
| |
| Attempting to access an interop object via GL when the object is |
| not locked, or attempting to access the DirectX resource through |
| the DirectX API when it is locked by GL, will result in undefined |
| behavior and may result in data corruption or program |
| termination. Likewise, passing invalid interop device or object |
| handles to this function has undefined results, including program |
| termination. |
| |
| Locked objects are available for operations which read or write |
| the data store, according to the access mode specified in |
| wglDXRegisterObjectNV. If a different access mode is required |
| after the object has been registered, the access mode may be |
| modified by calling |
| |
| BOOL wglDXObjectAccessNV(HANDLE hObject, GLenum access); |
| |
| <hObject> is an interop object handle returned by |
| wglDXRegisterObjectNV and identifies the interop object for which |
| the access mode should be modified. |
| |
| <access> is a new access mode with the same meaning as the |
| <access> parameter of wglDXRegisterObjectNV. The access mode may |
| be modified only when an object is not locked and will affect |
| subsequent lock operations. |
| |
| The return value is TRUE if the function succeeds. If an error |
| occurs, the return will be FALSE. To get extended error |
| information, call GetLastError. Possible errors are as follows: |
| |
| ERROR_INVALID_DATA Invalid <access> parameter. |
| |
| ERROR_BUSY <hObject> is currently locked for |
| GL access. |
| |
| Operations which attempt to read or write an object in a manner |
| inconsistent with the specified access mode will result in |
| undefined behavior and may result in data corruption or program |
| termination. |
| |
| Calling wglDXObjectAccessNV with an invalid <hObject> parameter |
| results in undefined behavior and may result in data corruption or |
| program termination. |
| |
| In order to return control of an object to DirectX, it must be unlocked |
| by calling |
| |
| BOOL wglDXUnlockObjectsNV(HANDLE hDevice, GLint count, |
| HANDLE *hObjects); |
| |
| A return value of TRUE indicates that the objects were |
| successfully unlocked and DirectX may now safely access them. A |
| return value of FALSE indicates that an error occurred. To get |
| extended error information, call GetLastError. Possible errors are |
| as follows: |
| |
| ERROR_NOT_LOCKED One or more of the objects in <hObjects> |
| was not locked. |
| |
| ERROR_INVALID_DATA One or more of the objects in <hObjects> |
| does not belong to the interop device |
| identified by <hDevice>. |
| |
| ERROR_LOCK_FAILED One or more of the objects in <hObjects> |
| failed to unlock. |
| |
| If the function returns FALSE, none of the objects are unlocked. |
| |
| Results are undefined if any of the handles in <hObjects> are |
| invalid and may result in data corruption or program termination. |
| |
| When access to a DirectX resource from GL is no longer required, the |
| association between the GL object and the DirectX resource should be |
| terminated by calling |
| |
| BOOL wglDXUnregisterObjectNV(HANDLE hObject); |
| |
| where <hObject> is the interop object handle returned by |
| wglDXRegisterObjectNV. Any subsequent attempt to access |
| <hObject> will result in undefined behavior and may result in data |
| corruption or program termination. |
| |
| A return value of TRUE indicates that the object was successfully |
| unregistered and <hObject> is now invalid. A return value of FALSE |
| indicates that an error occurred. To get extended error |
| information, call GetLastError. Possible errors are as follows: |
| |
| ERROR_BUSY <hObject> is currently locked for access |
| by the GL |
| |
| Results are undefined if <hObject> is invalid and may result in |
| program termination or data corruption. |
| |
| When all interop operations have been completed, the connection |
| between OpenGL and DirectX may be terminated by calling |
| |
| BOOL wglDXCloseDeviceNV(HANDLE hDevice); |
| |
| where <hDevice> is the interop device handle returned by |
| wglDXOpenDeviceNV. Once the device is closed, any attempt to |
| access DirectX resources through associated GL handles will result |
| in undefined behavior and may result in data corruption or program |
| termination. |
| |
| A return value of TRUE indicates that the device was successfully |
| closed and <hDevice> is now invalid. A return value of FALSE |
| indicates an error. To get extended error information, call |
| GetLastError. Possible errors are as follows: |
| |
| ERROR_INVALID_DATA The Direct3D device failed to |
| close. |
| |
| Calling this function with an invalid <hDevice> parameter results |
| in undefined behavior and may result in data corruption or program |
| termination. |
| |
| Issues |
| |
| 1) Should we support explicit usage of share handles under WDDM or |
| disallow it entirely? |
| |
| RESOLUTION: We should support it. Implicit share handles are |
| useful when writing code that's meant to be portable between WDDM |
| and non-WDDM operating systems; explicit share handles are useful |
| when writing an application that needs to share resources with |
| non-GL clients. |
| |
| 2) Can DirectX and OpenGL render concurrently to the same DirectX |
| resource? |
| |
| RESOLUTION: Concurrent rendering by OpenGL and DirectX to the same |
| resource is not supported. |
| |
| DISCUSSION: The Lock/Unlock calls serve as synchronization points |
| between OpenGL and DirectX. They ensure that any rendering |
| operations that affect the resource on one driver are complete |
| before the other driver takes ownership of it. |
| |
| When sharing a large resource, applications can potentially desire |
| concurrent access to different regions of the resource (e.g., if |
| the application is drawing a user interface in DirectX with an |
| OpenGL viewport occupying a region of it, where the UI and OpenGL |
| regions do not overlap). In this case, more fine-grained |
| synchronization could be achieved by not doing implicit |
| synchronization on the driver side and providing primitives to the |
| application to enable it to synchronize on it's own, for instance, |
| by allowing a DirectX 9 event query to be mapped and used as a GL |
| sync object. This is, however, beyond the scope of the current |
| extension. |
| |
| 3) If two GL contexts are sharing textures, what is the correct |
| way to access a DirectX resource from both contexts? |
| |
| RESOLUTION: Sharing a DirectX resource among multiple GL contexts is |
| best achieved without having shared namespaces among the GL |
| contexts, by simply registering the texture on each GL context |
| separately. |
| |
| If two GL contexts share namespaces, it is still necessary to lock |
| the DirectX resource for each GL context that needs to access |
| it. Note that only one GL context may hold the lock on the |
| resource at any given time --- concurrent access from multiple GL |
| contexts is not currently supported. |
| |
| 4) How do driver control panel settings regarding anti-aliasing |
| modes affect this extension? |
| |
| DISCUSSION: User-configurable system settings may allow users to |
| force anti-aliasing for applications that do not support |
| it. Usually, this causes the implementation to create multisampled |
| surfaces for render targets that the application creates as |
| non-multisampled. |
| |
| GL API semantics for textures can differ between multisample and |
| non-multisample textures. If the application creates a DirectX |
| render target that is to be bound as a GL texture, it will have no |
| way to know that the surface is actually multisampled, but GL will |
| require that it is bound to the TEXTURE_2D_MULTISAMPLE target |
| instead of the TEXTURE_2D target. Because of this, it is |
| recommended that render targets be bound to GL renderbuffers |
| instead. |
| |
| Additionally, DirectX implementations are free to create render |
| targets that do not match the number of samples that the app |
| requested. Implementations are also free to create color and depth |
| render targets with incompatible multisample modes. This can |
| result in FBO completeness errors if incompatible color and depth |
| render targets are bound for rendering to the same FBO. This |
| problem also exists with pure DirectX applications and is not |
| specific to this extension. |
| |
| Sample Code |
| |
| Render to Direct3D 9 multisample color and depth buffers with |
| OpenGL under WDDM: |
| |
| // create the Direct3D9Ex device: |
| IDirect3D9Ex *direct3D; |
| IDirect3DDevice9Ex *device; |
| D3DPRESENT_PARAMETERS d3dpp; |
| |
| direct3D = Direct3DCreate9Ex(D3D_SDK_VERSION, &direct3D); |
| |
| <set appropriate device parameters in d3dpp> |
| |
| direct3D->CreateDevice(D3DADAPTER_DEFAULT, |
| D3DDEVTYPE_HAL, |
| hWnd, |
| D3DCREATE_HARDWARE_VERTEXPROCESSING | |
| D3DCREATE_PUREDEVICE | |
| D3DCREATE_MULTITHREADED, |
| &d3dpp, |
| &device); |
| |
| // create the Direct3D render targets |
| IDirect3DSurface9 *dxColorBuffer; |
| IDirect3DSurface9 *dxDepthBuffer; |
| |
| device->CreateRenderTarget(width, height, |
| D3DFMT_A8R8G8B8, |
| D3DMULTISAMPLE_4_SAMPLES, 0, |
| FALSE, |
| &dxColorBuffer, |
| NULL); |
| |
| device->CreateDepthStencilSurface(width, height, |
| D3DFMT_D24S8, |
| D3DMULTISAMPLE_4_SAMPLES, 0, |
| FALSE, |
| &dxDepthBuffer, |
| NULL); |
| |
| // register the Direct3D device with GL |
| HANDLE gl_handleD3D; |
| gl_handleD3D = wglDXOpenDeviceNV(device); |
| |
| // register the Direct3D color and depth/stencil buffers as |
| // 2D multisample textures in opengl |
| GLuint gl_names[2]; |
| HANDLE gl_handles[2]; |
| |
| glGenTextures(2, gl_names); |
| |
| gl_handles[0] = wglDXRegisterObjectNV(gl_handleD3D, dxColorBuffer, |
| gl_names[0], |
| GL_TEXTURE_2D_MULTISAMPLE, |
| WGL_ACCESS_READ_WRITE_NV); |
| |
| gl_handles[1] = wglDXRegisterObjectNV(gl_handleD3D, dxDepthBuffer, |
| gl_names[1], |
| GL_TEXTURE_2D_MULTISAMPLE, |
| WGL_ACCESS_READ_WRITE_NV); |
| |
| // attach the Direct3D buffers to an FBO |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| GL_TEXTURE_2D_MULTISAMPLE, gl_names[0]); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, |
| GL_TEXTURE_2D_MULTISAMPLE, gl_names[1]); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, |
| GL_TEXTURE_2D_MULTISAMPLE, gl_names[1]); |
| |
| // rendering loop |
| while (!done) { |
| <direct3d renders to the render targets> |
| |
| // lock the render targets for GL access |
| wglDXLockObjectsNV(handleD3D, 2, gl_handles); |
| |
| <opengl renders to the render targets> |
| |
| // unlock the render targets |
| wglDXUnlockObjectsNV(handleD3D, 2, gl_handles); |
| |
| <direct3d renders to the render targets and presents |
| the results on the screen> |
| } |
| |
| Revision History |
| |
| Revision 1, 2010/11/10 |
| - Initial public revision |