CU_GRAPHICS_REGISTER_FLAGS_NONE and CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD both work. Only CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY errors.
Also, the function documentation says that the function takes CU_GRAPHICS_MAP_RESOURCE_FLAGS_* which does not make sense. The CUDA for Tegra doc example under “4.2.1. CUDA interop with EGLImage” uses CU_GRAPHICS_REGISTER_FLAGS_NONE which does make sense. What is the correct set of accepted flags?
Also, that section includes the note “The cudaGraphicsEGLRegisterImage() function is only supported on Tegra® devices.” But, the generic documentation for the function does not mention the restriction. Instead, on the desktop the function will compile and link without error then give an error 999 UNKNOWN at runtime.
Below is a minimal example of the CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY error that fails on my Xavier AGX with Jetpack 4.3.
//usr/bin/g++ RegisterEglImageError.cpp -I /usr/local/cuda/include -L/usr/local/cuda/lib64 -lcuda -lEGL -lGLESv2 && ./a.out
// CUDA_ERROR_INVALID_VALUE
#include "cuda.h"
#include "cudaEGL.h"
#include <GLES3/gl32.h>
#include <GLES2/gl2ext.h>
#include <EGL/eglext.h>
#include <stdio.h>
int main() {
cuInit(0);
CUdevice device;
cuDeviceGet(&device, 0);
CUcontext cudaContext;
cuDevicePrimaryCtxRetain(&cudaContext, device);
cuCtxPushCurrent(cudaContext);
EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(eglDisplay, nullptr, nullptr);
EGLContext eglContext;
{
EGLint configAttributes[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_NONE
};
EGLConfig config;
EGLint numConfigs;
eglChooseConfig(eglDisplay, configAttributes, &config, 1, &numConfigs);
EGLint contextAttributes[] = {
EGL_CONTEXT_MAJOR_VERSION, 3,
EGL_CONTEXT_MINOR_VERSION, 2,
EGL_NONE
};
eglContext = eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT, contextAttributes);
}
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
GLenum oglError = glGetError();
if (oglError != GL_NO_ERROR) fprintf(stderr, "OGL Error %x\n", oglError);
EGLAttrib eglImgAttrs[] = { EGL_IMAGE_PRESERVED, EGL_FALSE, EGL_NONE, EGL_NONE };
EGLImageKHR eglImage = eglCreateImage(eglDisplay, eglContext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(intptr_t)texture, eglImgAttrs);
EGLint eglErrorCode = eglGetError();
if (eglErrorCode != EGL_SUCCESS) fprintf(stderr, "EGL Error %x\n", eglErrorCode);
CUgraphicsResource cudaResource; // CU_GRAPHICS_REGISTER_FLAGS_NONE or CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD instead of CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY does work.
CUresult cudaError = cuGraphicsEGLRegisterImage(&cudaResource, eglImage, CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY);
if (cudaError == CUDA_ERROR_INVALID_VALUE) fprintf(stderr, "CUDA_ERROR_INVALID_VALUE\n");
else if (cudaError == CUDA_SUCCESS) fprintf(stderr, "CUDA_SUCCESS\n");
else fprintf(stderr, "Other CUDA Error %d\n", cudaError);
return 0;
}