Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check for NV_DX_interop extension available and fallback mode #109

Open
marcotod1410 opened this issue May 11, 2023 · 22 comments
Open

Check for NV_DX_interop extension available and fallback mode #109

marcotod1410 opened this issue May 11, 2023 · 22 comments
Labels
4.0 enhancement New feature or request
Milestone

Comments

@marcotod1410
Copy link
Contributor

At this current time, this control only works if the NV_DX_interop is supported. If the extension is not supported, an AccessViolationException is thrown. This happened to me on a virtual machine where 3D acceleration was enabled via a virtual Mesa graphics card.

I've got the following questions:

  • Should we check for the NV_DX_interop extension support before creating the DXGLContext? If so, should we expose a dependency property and/or an event when the initialization fails? Doing so, the control could notify the user about the issue, so that the error can be handled correctly by the application.
  • If the extension is not supported, should the library provide a fallback mode for rendering? I was thinking also about the rendering mode used before the NV_DX_interop way was introduced (rendering to an hidden window, then copying the buffer to a WriteableBitmap).
@NogginBops NogginBops added enhancement New feature or request 4.0 labels May 11, 2023
@NogginBops NogginBops added this to the 4.3.0 milestone May 11, 2023
@NogginBops
Copy link
Member

NogginBops commented May 11, 2023

I think we should fall back (or at least have the option to fall back) to a version that does that CPU roundtrip if interop is not supported.
And making sure the user can query if they got a fast backend or a slow one.

@NogginBops NogginBops modified the milestones: 4.3.0, 4.3.1 May 30, 2024
@NogginBops
Copy link
Member

Moving this to 4.3.1.

@Krugpelke
Copy link
Contributor

Krugpelke commented Jun 5, 2024

I've had black screen issues with Intel UHD gpus, in those cases software fallback seems to solve the problem, but on some integrated gpus this AccessViolationException completely crashes my application and I've had no success try/catching this. It would be great if it would be possible to at least safely handle cases when this control fails to initialize.

@NogginBops
Copy link
Member

@Krugpelke how would you like to handle the initialization error? Should we throw a more specific exception or should we have some other way of handling this?

@Krugpelke
Copy link
Contributor

Krugpelke commented Jun 5, 2024

Personally, I'm completely fine with throwing an exception in how it's currently implemented in 4.3.1, it should work as long as NV_DX_interop is safely handled.
Actually, disregard my previous comment about DxGlContext constructor crashing, I was thinking about 4.2.3, previously I would crash in DxGLFramebuffer constructor on var genHandle = Wgl.DXRegisterObjectNV(context.GlDeviceHandle, dxRenderTargetHandle, (uint)GLSharedTextureHandle, (uint)TextureTarget.Texture2D, WGL_NV_DX_interop.AccessReadWrite).
In 4.3.1, however, the crash happens in DxGlContext Dispose on Wgl.DXCloseDeviceNV(DxDevice.Handle), this dispose is getting called from the finalizer for some reason, the exception for clarity is:

Exception thrown at 0x00007FFD2A857BCC (nvoglv64.dll) in Application.exe: 0xC0000005: Access violation reading location 0x000001E35169A5EE.
An unhandled exception of type 'System.AccessViolationException' occurred in OpenTK.Graphics.dll
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

@NogginBops
Copy link
Member

With 67129a3 I've added a PlatformNotSupportedException when WGL_NV_DX_interop can't be found. We can implement the fallback mode in 4.3.3.

@NogginBops NogginBops modified the milestones: 4.3.2, 4.3.3 Aug 8, 2024
@ArticadAlistair
Copy link

ArticadAlistair commented Sep 18, 2024

I'm in the process of switching my prototype Windows (WPF) (.NET 8) app from using SharpGL to OpenTK 4, because everywhere I read suggests OpenTK is better. I now get an Access Violation exception when showing the window containing the GLWpfControl, and I believe it is related to this issue, judging from the above comments.
The crash happens on this line in OpenTK.Wpf.GLWpfControlRenderer.ReallocateFramebufferIfNeeded():

this.DxInteropColorRenderTargetRegisteredHandle = OpenTK.Graphics.Wgl.Wgl.DXRegisterObjectNV(this._context.GLDeviceHandle, this.DxColorRenderTarget.Handle, (uint) this.GLSharedColorRenderbufferHandle, 36161U, WGL_NV_DX_interop.AccessReadWrite);

My machine only has Intel built-in graphics hardware, so I suspect I do not have NV_DX_interop support. It looks as though this is a known issue, with the only proposed solution being to throw a PlatformNotSupportedException. The trouble is, many of my users will be in the same position as me. This seems a major handicap to OpenTK, from my perspective, meaning I simply cannot use it. Is there not any better solution? There should at least be a warning (preferably in bold text) which people will see before they try to install or use the control. I've wasted a whole afternoon on this.

@NogginBops
Copy link
Member

To print a list of all WGL extensions your GPU+driver combo supports you can use this code:

[DllImport("opengl32.dll")]
static extern IntPtr wglGetCurrentDC();

public static unsafe void PrintWGLExtensions()
{
    Wgl.LoadBindings(new GLFWBindingsContext());
    IntPtr dc = wglGetCurrentDC();
    string[] extensions = Wgl.Arb.GetExtensionsString(dc).Split(' ');
    for (int i = 0; i < extensions.Length; i++)
    {
        Console.WriteLine(extensions[i]);
    }
}

You will have to call this function after your control and OpenGL context has been created.

If your driver supports NV_DX_interop that will be one of the strings that this function prints out.

@ArticadAlistair
Copy link

ArticadAlistair commented Sep 19, 2024

Thanks. I have the GLview utility and can see that my driver doesn't support NV_DX_interop. Am I right in concluding I cannot use OpenTK at all?

@NogginBops
Copy link
Member

Unfortunately not at the moment, no.
I do think we should enable some sort of (slower) fallback mode in case this extension isn't supported.

In older versions of this repo there was an implementation that read the data fram OpenGL to the cpu and then uploaded it back to DX, so it shouldn't be too hard to bring parts of that code back. But I'm not sure how soon I can get to that, if someone else decided to have a go at it before me that would be fantastic.

@ArticadAlistair
Copy link

ArticadAlistair commented Sep 19, 2024

I have limited experience with OpenGL, and none with DirectX, otherwise I might offer to help. All I wanted was a C# wrapper for OpenGL that was reasonably future-proof. It looks like OpenTK has gone a bit too far into the future, and left the present behind. I don't know how representative my experience is, but if it is common, OpenTK may have shot itself in the foot.

@NogginBops
Copy link
Member

Looking at the old renderer's source it's quite simple so I don't think it would be too much work to actually do the slower fallback method of rendering.
https://github.com/opentk/GLWpfControl/blob/551b59ae02c846936db700de49c0bbf640821358/src/GLWpfControl/GLWpfControlRenderer.cs

If no one else wants to have a go at implementing this into the control I'll do it. But not sure how fast I can get to it.

But basically the change would mean checking for WGL_NV_DX_interop and switching the renderer to either use DX interop or do the pixel buffer object shuffle that is being done in the linked code above.

@NogginBops
Copy link
Member

NogginBops commented Sep 20, 2024

Looking at https://opengl.gpuinfo.org/listreports.php?extension=WGL_NV_DX_interop&option=not and filtering for "Windows" and "OpenGL" (exclusing OpenGLES) most of the GPUs that don't support WGL_NV_DX_interop are either software implementations, OpenGL over Vulkan translation layers, really old intel GPUs, and some odd AMD cards running MESA on windows.

Generally WGL_NV_DX_interop is generally well supported. What GPU and driver do you have?

@ArticadAlistair
Copy link

I have an Intel(R) UHD Graphics 770 (Forward Context 4.6). It is on a PC that is only 18 months old. The rest of the PC is fairly high spec. I don't need a fancy graphics card, not least because many of my customers don't either, so I need to know how well the program will work for them.
When you say the "change would mean checking for WGL_NV_DX_interop and switching the renderer to either use DX interop or do the pixel buffer object shuffle", you've left me behind! Does this mean my machine would be able to use hardware acceleration on my OpenGL application if I'm only using OpenGL API calls?

@NogginBops
Copy link
Member

NogginBops commented Sep 20, 2024

Looking at reports for the UHD Graphics 770 you should expect WGL_NV_DX_interop to be supported:
https://opengl.gpuinfo.org/displayreport.php?id=7677
(all UHD Graphics 770 reports report support for this extension).

Do you know what graphics driver you are running? The oldest driver version reported on the website is 30.0.101.1994 so I guess if you have something lower than that it could be possible that it doesn't have the extension.

Should be as simple as just installing the latest driver to get it working in that case.

@ArticadAlistair
Copy link

ArticadAlistair commented Sep 20, 2024

My most recent graphics driver update was this:
Description: This download installs Intel® Graphics Driver 32.0.101.5972 (WHQL Certified) for Intel® Arc™ A-Series Graphics, Intel® Iris® Xe Graphics, and Intel® Core™ Ultra Processors with Intel® Arc™ Graphics.
Version: 32.0.101.5972
Release date: August 23, 2024
Size: 884.42 MB
More information here.
It looks like a newer one is available. I'll get it now...

@ArticadAlistair
Copy link

ArticadAlistair commented Sep 20, 2024

Here's a possibly revealing development: the GLview Extensions Viewer utility does not show support for NV_DX_interop:
image
However, the code snippet posted above "To print a list of all WGL extensions your GPU+driver combo supports" does indicate support for NV_DX_interop:
image
I still get a crash within Wgl.DXRegisterObjectNV():
image
hDevice = 0x000001a50afaf730
dxObject = 0x000001a503f33af8
name = 1
type = 36161
access = AccessReadWrite
EntryPoints[21] = 0x00007ff83d80a4d0
If I try to put the 0x00007ff83d80a4d0 address (EntryPoints[21]) into the debugger's Dissasembly address box at this point, I get this:
image
Suggesting there is a different problem altogether. Any suggestions?

@NogginBops
Copy link
Member

The GLview Extensions Viewer only shows you GL_ extensions and will not show you platform specific extensions for WGL (nor EGL, GLX etc).

So this seems to be a recurring issue with WGL_NV_DX_interop on intel (or generally integrated graphics), we've never really figured out if it's a bug on our end or if it's a intel graphics driver bug.

Can you show me the code you use to initialize your GLWpfControl?

@ArticadAlistair
Copy link

ArticadAlistair commented Sep 20, 2024

I created a minimalist app to initialise the control and then list the WGL extensions. Here is the WPF XAML:
image
And here is the code-behind:
image
As I'm a relative newbie, you also need to consider the possibility that I'm a moron who doesn't know what they're doing!

@NogginBops
Copy link
Member

And just to make sure, what version of GLWpfControl are you running?

@ArticadAlistair
Copy link

4.3.2

@NogginBops NogginBops removed this from the 4.3.3 milestone Oct 31, 2024
@NogginBops NogginBops added this to the 4.3.4 milestone Oct 31, 2024
@NogginBops
Copy link
Member

There will be no fallback mode in 4.3.3, but maybe we can add this in 4.3.4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.0 enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants