In our application, we are successfully using CUDA OpenGL interop. Our application uses some GLSL shaders to write into a texture (via a frame buffer) and subsequently reads the data from the texture in a CUDA kernel.
For performance reasons, we are moving to an asynchronous architecture. In this architecture, thread A writes the texture in OpenGL context A. Subsequently, we pass on the texture to thread B using OpenGL context B, which is shared with OpenGL context A.
This is what we do in pseudo-code:
void ApixaThread::run()
{
if (!m_context->makeCurrent(m_surface.get()))
{
Log::error("Failed to make the shared OpenGL context current to the Apixa thread.");
return;
}
if (!InitCuda())
{
Log::error("Failed to initialize CUDA for the Apixa thread.");
return;
}
while (!isInterruptionRequested())
{
Input input = GetNextFromQueue();
GLuint tex_name = input.tpeIn->GetTextureID();
glBindTexture(GL_TEXTURE_2D, tex_name);
if (!OpenGLUtil::IsOpenGLSucces())
{
Log::info("Failed to bind texture");
continue;
}
if (!MapOpenGlTextureInCuda(input.tpeIn))
{
Log::error("Failed to map and OpenGL texture in CUDA: id={} is-texture={}", textureName, glIsTexture(tex_name));
continue;
}
}
}
bool InitCuda(int deviceIndex = 0)
{
CUresult cudaResult;
CUdevice cuDevice {};
cudaResult = cuDeviceGet(&cuDevice, deviceIndex);
if (cudaResult != CUDA_SUCCESS)
{
Log::error("Failed query the CUDA device with index {}: {}", deviceIndex, FmtCudaError(cudaResult));
return false;
}
char deviceNameBuffer[128] { 0 };
cudaResult = cuDeviceGetName(deviceNameBuffer, 128, cuDevice);
if (cudaResult != CUDA_SUCCESS)
{
Log::error("Failed to query the device name: {}", FmtCudaError(cudaResult));
return false;
}
CUcontext cudaContext {};
cudaResult = cuCtxCreate(&cudaContext, 0, cuDevice);
if (cudaResult != CUDA_SUCCESS)
{
Log::error("Failed to create a new CUDA context: {}", FmtCudaError(cudaResult));
return false;
}
cudaResult = cuCtxSetCurrent(cudaContext);
if (cudaResult != CUDA_SUCCESS)
{
Log::error("Failed to make the CUDA context current: {}", FmtCudaError(cudaResult));
return false;
}
Log::info("Successfully initialized CUDA device '{}', index {}", deviceNameBuffer, deviceIndex);
return true;
}
bool MapOpenGlTextureInCuda(const PooledTextureRef& tpe)
{
CUresult error;
CUgraphicsResource m_pcudaResource;
error = cuGraphicsGLRegisterImage(&m_pcudaResource, tpe->GetTextureID(), GL_TEXTURE_2D, CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY);
if (error != CUDA_SUCCESS)
{
Log::error("Failed to register texture to CUDA: {}", FmtCudaError(error));
return false;
}
return true;
}
It would be great if someone could tell me if CUDA—OpenGL interop is possible with a shared texture or if this is already a losing strategy. I couldn’t find anything in the documentation that says this would not be possible.
Thanks,
Thomas