Closed Wassermann-nl closed 1 year ago
I cloned managedCuda and changed the following in the file OpenGL.cs, then my program runs properly. I don't know if that's the best solution, but it works.
can you please change it in the nuget package so that i can use the nuget package instead of the clone.
i am a git noob, otherwise I would make an pull request.
// from
static OpenGLNativeMethods()
{
NativeLibrary.SetDllImportResolver(typeof(OpenGLNativeMethods).Assembly, ImportResolver);
}
// to
static OpenGLNativeMethods()
{
try
{
NativeLibrary.SetDllImportResolver(typeof(OpenGLNativeMethods).Assembly, ImportResolver);
}
catch (Exception)
{
}
}
Hi,
indeed, the call to NativeLibrary.SetDllImportResolver(...)
is the cause of the troubles, as a loader is already set for the main CUDA-dll. I'm just hesitating to use a try/catch as regular control flow, on the other side I heaven't seen any API that allows to query if a delegate is already set.
I guess the best solution would be to replace NativeLibrary.SetDllImportResolver
by DriverAPINativeMethods.Init()
: this way everthing is well centralised in one static method.
I'll have to check if that works and, if not, what would be a good solution to fix that issue, if you have any other ideas, don't hesitate to post them here!
Cheers, Michael
Contrary to the description of the method SetDllImportResolver, you can see in the code that the InvalidOperationException is thrown if the resolver for the assembly was already set, so you could only intercept exactly these.
/// <summary>
/// Set a callback for resolving native library imports from an assembly.
/// This per-assembly resolver is the first attempt to resolve native library loads
/// initiated by this assembly.
///
/// Only one resolver can be registered per assembly.
/// Trying to register a second resolver fails with InvalidOperationException.
/// </summary>
/// <param name="assembly">The assembly for which the resolver is registered.</param>
/// <param name="resolver">The resolver callback to register.</param>
/// <exception cref="System.ArgumentNullException">If assembly or resolver is null</exception>
/// <exception cref="System.ArgumentException">If a resolver is already set for this assembly</exception>
public static void SetDllImportResolver(Assembly assembly, DllImportResolver resolver)
{
ArgumentNullException.ThrowIfNull(assembly);
ArgumentNullException.ThrowIfNull(resolver);
if (assembly is not RuntimeAssembly)
throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
if (s_nativeDllResolveMap == null)
{
Interlocked.CompareExchange(ref s_nativeDllResolveMap,
new ConditionalWeakTable<Assembly, DllImportResolver>(), null);
}
if (!s_nativeDllResolveMap.TryAdd(assembly, resolver))
{
throw new InvalidOperationException(SR.InvalidOperation_CannotRegisterSecondResolver);
}
}
static OpenGLNativeMethods()
{
try
{
NativeLibrary.SetDllImportResolver(typeof(OpenGLNativeMethods).Assembly, ImportResolver);
}
catch (InvalidOperationException)
{
}
}
I just pushed a correction for that bug that seems to fix the issue in my tests. Could you please try it out and check if that also works in your case? If so, I'll create new Nuget images (also including then Cuda12.1).
Cheers, Michael
i will try it out today.
hi Michael, it works !
Great, thanks! I'll update the nuget packages soon
Hi, I'm in the process of changing my program from using ManagedCuda.NETStandard 9.1.300 to ManagedCuda-12 (12.0.48).
I get the following runtime exception when I use CudaContext.CreateOpenGLContext for context creation :
if I create the context with the CudaContext constructor instead, then it works without any problems as long as I don't use gl interoperability.
But if I then use CudaOpenGLBufferInteropResource, for example, I get the following similar exception.
Do you have any idea what is causing the problem and how to fix it?