I am writting a moudule which does OpenGL off-screen renderring.
(using GLAD+GLFW+CUDA OpenGL interop)
When using one object of this module, renderring goes well.
But if I create two objects of this module (for example, object 1 used to render small image, object 2 used to render large image),
the second one will go error 219 (cudaErrorInvalidGraphicsContext) when calling cudaGraphicsMapResources.
I have tried to search the document and found: CUDA C++ Programming Guide
And I tried to add cuCtxCreate() / cuCtxPopCurrent()/ cuCtxPushCurrent(), still could not work.
What is the correct way to do with 2 OpenGL context?
The error suggests to me that you are attempting to use resources in CUDA OpenGL interop that belong to a graphics context other than the one that is current. There might be other possibilities as well. Simply manipulating CUDA contexts wont fix this. You can explicitly switch between OpenGL contexts (google for that). It seems to be not recommended in general because it may be expensive.
And it is important to associate each GL context with an appropriate CUDA context. The CUDA sample codes demonstrate how to do this.
I use glfwMakeContextCurrent to switch between 2 OpenGL contexts.
And all functions in the module I called glfwMakeContextCurrent at start, so I think resources belonged to the current context?
And it is important to associate each GL context with an appropriate CUDA context. The CUDA sample codes demonstrate how to do this.
It’s a bit hidden. The basic idea is to init OpenGL first, then do a cudaSetDevice() if you are using the CUDA runtime API. That will associate that OpenGL context with that device (i.e. with the primary context on that device, which is used by the CUDA runtime.) So in a sample like SimpleGL or FluidsGL, you see that the GL init activity occurs first, and then there is a (hidden) call to cudaSetDevice via the helper SDK. That should guarantee that the OpenGL context just created gets associated with the device in question.
(On windows/D3D the binding is needed also. Yes, I know this is not what you are asking.)
I saw some document said cudaSetDevice() will bind OpenGL context to primary CUDA context. If I want to use 2 OpenGL context, could I just all bind to primary CUDA context?
I have no experience with it, but I guess I would create a GL context, then do cudaSetDevice, then create another, then do cudaSetDevice, and see if that worked. Beyond that I’m unlikely to be able to offer much advice, and its unclear to me why 2 OpenGL contexts are needed, and the stated reason (one to render a small image, one to render a large image) is unconvincing for me.
I want to use 2 OpenGL contexts because I want to render 2 different images in 2 different windows in one program. I do not know whether this is the right way or not.
Finally I found that I was using OpenGL rendering wrong in 2 threads.
It is right to call glfwMakeContextCurrent(window) before calling rendering functions (include CUDA GL interop), and then call glfwMakeContextCurrent(NULL)after calling rendering function.
The reason why still error 219 occured was I was not using glfwCreateWindow and rendering functions in the same thread.
Do not call glfwCreateWindow for all the windows at the beginning of the program, just call the init function in the thread which will actually do the rendering for each window.