cuEGLStreamConsumerConnect is resulting in EGL_BAD_ALLOC

Calling eglCreateStreamProducerSurfaceKHR with cuEGLStreamConsumerConnect gives EGL_BAD_ALLOC.
If I connect to an eglStreamConsumerGLTextureExternalKHR instead, it works fine.
This sure looks like a driver bug to me. Any clues what I’m doing wrong?
Here’s someone else with the same bug back in 2018

Below is the complete and minimal code to repro.

Ubuntu 18.04
CUDA SDK 10.0 installed via Jetpak
Driver Version: 430.34 CUDA Version: 10.1

// g++ errorDemo.cpp -I /usr/local/cuda/include -L/usr/local/cuda/lib64 -lcuda -lEGL && ./a.out
// Bad Alloc
#include "cuda.h"
#include "cudaEGL.h"
#include <stdio.h>
int main() {
    cuInit(0);
    CUdevice device;
    cuDeviceGet(&device, 0);
    CUcontext cudaContext;
    cuDevicePrimaryCtxRetain(&cudaContext, device);
    cuCtxPushCurrent(cudaContext);
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(display, nullptr, nullptr);
    PFNEGLCREATESTREAMKHRPROC eglCreateStreamKHR = (PFNEGLCREATESTREAMKHRPROC)eglGetProcAddress("eglCreateStreamKHR");
    EGLStreamKHR stream = eglCreateStreamKHR(display, nullptr);
    CUeglStreamConnection consumerConnection;
    CUresult cudaResult = cuEGLStreamConsumerConnect(&consumerConnection, stream);
    const char *cudaErrorName;
    cuGetErrorName(cudaResult, &cudaErrorName);
    if (cudaResult != cudaError_enum::CUDA_SUCCESS) fprintf(stderr, "cuda error: %s\n", cudaErrorName);
    EGLint configAttributes[] = {
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
        EGL_SURFACE_TYPE, EGL_STREAM_BIT_KHR,
        EGL_ALPHA_SIZE, 1,
        EGL_NONE
    };
    EGLConfig config;
    EGLint numConfigs;
    eglChooseConfig(display, configAttributes, &config, 1, &numConfigs);
    EGLint contextAttributes[] = {
        EGL_CONTEXT_MAJOR_VERSION, 3,
        EGL_CONTEXT_MINOR_VERSION, 2,
        EGL_NONE
    };
    EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
    EGLint surfaceAttributes[] = {
        EGL_WIDTH, 256,
        EGL_HEIGHT, 256,
        EGL_NONE
    };
    EGLint beforeErrorCode = eglGetError();
    if (beforeErrorCode != EGL_SUCCESS) fprintf(stderr, "Previous Error\n");
    PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC eglCreateStreamProducerSurfaceKHR = (PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)eglGetProcAddress("eglCreateStreamProducerSurfaceKHR");
    EGLSurface surface = eglCreateStreamProducerSurfaceKHR(display, config, stream, surfaceAttributes);
    EGLint afterErrorCode = eglGetError();
    if (afterErrorCode == EGL_BAD_ALLOC) fprintf(stderr, "Bad Alloc\n");
    else fprintf(stderr, "No Error\n");
    return 0;
}

Hi Cory,

I used below configuration setup to reproduce issue locally and I received error message as “cuda error: CUDA_ERROR_INVALID_HANDLE”.

Alienware Area-51 R6 + Ubuntu 18.04.4 LTS + 5.3.0-46-generic + GeForce GTX 1650 + Driver 430.34 + release 10.0, V10.0.130
root@test-Precision-T7610:/home/test#
root@test-Precision-T7610:/home/test# g++ errorDemo.cpp -I /usr/local/cuda-10.0/include/ -L/usr/local/cuda-10.0/lib64 -lcuda -lEGL && ./a.out
cuda error: CUDA_ERROR_INVALID_HANDLE
Previous Error
No Error
root@test-Precision-T7610:/home/test#
root@test-Precision-T7610:/home/test# ./a.out
cuda error: CUDA_ERROR_INVALID_HANDLE
Previous Error
No Error
root@test-Precision-T7610:/home/test#

Please confirm if this can be considered as repro.
Also plese send another sample code which worked fine at you end so that I can verify at my end if it’s working or not.

Thank you for the highly accurate test. Odd that you get a different error than I do. I guess I’d still accept that as a repro. Here is a version of the code that can flip between working and not.

// $ g++ textureConsumerDemo.cpp -DWORKS=0 -I /usr/local/cuda/include -L/usr/local/cuda/lib64 -lcuda -lEGL -lGL && ./a.out
// Bad Alloc
// $ g++ textureConsumerDemo.cpp -DWORKS=1 -I /usr/local/cuda/include -L/usr/local/cuda/lib64 -lcuda -lEGL -lGL && ./a.out
// No Error
    #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 display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        eglInitialize(display, nullptr, nullptr);
        PFNEGLCREATESTREAMKHRPROC eglCreateStreamKHR = (PFNEGLCREATESTREAMKHRPROC)eglGetProcAddress("eglCreateStreamKHR");
        EGLStreamKHR stream = eglCreateStreamKHR(display, nullptr);
#ifndef WORKS
# define WORKS 1
#endif
#if WORKS
        EGLContext consumerEglContext;
        {
            EGLint configAttributes[] = {
                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
                EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
                EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
                EGL_RED_SIZE, 8,
                EGL_GREEN_SIZE, 8,
                EGL_BLUE_SIZE, 8,
                EGL_ALPHA_SIZE, 8,
                EGL_NONE
            };
            EGLConfig config;
            EGLint numConfigs;
            eglChooseConfig(display, configAttributes, &config, 1, &numConfigs);
            EGLint contextAttributes[] = {
                EGL_CONTEXT_MAJOR_VERSION, 3,
                EGL_CONTEXT_MINOR_VERSION, 2,
                EGL_NONE
            };
            consumerEglContext = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
        }
        eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, consumerEglContext);
        GLuint textureHandle;
        glGenTextures(1, &textureHandle);
        glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureHandle);
        PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC eglStreamConsumerGLTextureExternalKHR = (PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC)eglGetProcAddress("eglStreamConsumerGLTextureExternalKHR");
        eglStreamConsumerGLTextureExternalKHR(display, stream);
        EGLint textureErrorCode = eglGetError();
        if (textureErrorCode != EGL_SUCCESS) fprintf(stderr, "Texture Error %x\n", textureErrorCode);
#else
        CUeglStreamConnection consumerConnection;
        CUresult cudaResult = cuEGLStreamConsumerConnect(&consumerConnection, stream);
        const char *cudaErrorName;
        cuGetErrorName(cudaResult, &cudaErrorName);
        if (cudaResult != cudaError_enum::CUDA_SUCCESS) fprintf(stderr, "cuda error: %s\n", cudaErrorName);
#endif
        EGLContext producerEglContext;
        EGLint configAttributes[] = {
            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
            EGL_SURFACE_TYPE, EGL_STREAM_BIT_KHR,
            EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
            EGL_RED_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_BLUE_SIZE, 8,
            EGL_ALPHA_SIZE, 8,
            EGL_NONE
        };
        EGLConfig config;
        EGLint numConfigs;
        eglChooseConfig(display, configAttributes, &config, 1, &numConfigs);
        EGLint contextAttributes[] = {
            EGL_CONTEXT_MAJOR_VERSION, 3,
            EGL_CONTEXT_MINOR_VERSION, 2,
            EGL_NONE
        };
        producerEglContext = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
        EGLint surfaceAttributes[] = {
            EGL_WIDTH, 256,
            EGL_HEIGHT, 256,
            EGL_NONE
        };
        EGLint beforeErrorCode = eglGetError();
        if (beforeErrorCode != EGL_SUCCESS) fprintf(stderr, "Previous Error %x\n", beforeErrorCode);
        PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC eglCreateStreamProducerSurfaceKHR = (PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)eglGetProcAddress("eglCreateStreamProducerSurfaceKHR");
        EGLSurface surface = eglCreateStreamProducerSurfaceKHR(display, config, stream, surfaceAttributes);
        EGLint afterErrorCode = eglGetError();
        if (afterErrorCode == EGL_BAD_ALLOC) fprintf(stderr, "Bad Alloc\n");
        else if (afterErrorCode != EGL_SUCCESS) fprintf(stderr, "Other error %x\n", afterErrorCode);
        else fprintf(stderr, "No Error\n");
        return 0;
    }

I tried compiling the latest code but it fails with below error, can you please suggest on it.

root@test-Precision-T7610:/home/test# g++ noerrordemo.cpp -I /usr/local/cuda-10.0/include/ -L/usr/local/cuda-10.0/lib64 -lcuda -lEGL && ./a.out
/tmp/ccYxk57R.o: In function main': noerrordemo.cpp:(.text+0x1cb): undefined reference to glGenTextures’
noerrordemo.cpp:(.text+0x1dd): undefined reference to `glBindTexture’
collect2: error: ld returned 1 exit status
root@test-Precision-T7610:/home/test#

The compiler args changed between the two versions.
The second version added -lGL
And also -DWORKS=0 or 1

Cory, can you run nvidia-bug-report.sh and attach the log file from it? That might help figure out why we’re getting a different result.

Output from EGL_KHR_debug might also help narrow down the problem while we’re trying to reproduce it. Here’s a version of your program that adds that debug info:
debug-info.cpp (4.8 KB)

(Apologies for the extra .log extension – the forum doesn’t allow attachments that end in .cpp).

Also, as a quick note: libGL.so is still the GLX library and it should never be used with EGL (though in Ubuntu 18.04, it probably will work anyway). For an EGL+GLES program, you want to use -lEGL -lGLESv2.

$ g++ debug-info.cpp -DWORKS=0 -I /usr/local/cuda/include -L/usr/local/cuda/lib64 -lcuda -lEGL -lGLESv2 && ./a.out
DEBUG: 0x3003, eglCreateStreamProducerSurfaceKHR, 0x33b9: EGL_BAD_ALLOC error: In eglCreateStreamProducerSurface: Unable to allocate resources for surface

Bad Alloc

nvidia-bug-report.log.gz.log (1.5 MB)

Cory, can you try a more recent driver (440.82 is the current one) and see if you still get problems with that?

I can confirm that with
Driver Version: 440.82 CUDA Version: 10.2
my test code reports: No Error
Thanks!

I had the same problem, which was solved by replacing the driver. But there are still some other problems
1.After eglCreateStreamProducerSurfaceKHR(),the stream state becomes EGL_STREAM_STATE_EMPTY_KHR.
2.After eglSwapBuffers(),the stream state becomes EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR.
3.After cudaEGLStreamConsumerAcquireFrame, The stream state is still EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR.cudaGetErrorString() is unknown.

±----------------------------------------------------------------------------+
| NVIDIA-SMI 450.80.02 Driver Version: 450.80.02 CUDA Version: 11.0 |
|-------------------------------±---------------------±---------------------+