Thanks for your attention,
your suggestion didn’t work for me, As I previously mentioned I want a method to convert GL buffer to DMA buffer zero copy. Beacause EGLstream supports commiunication between interfaces like DMA,GL,CUDA,EGLOutput, I wanted a EGLstream example that producer is GL and Consumer is DMA.
Two solutions were suggested by me, first one base on “nveglstreamsrc” and secound one Argus Interface.
nveglstreamsrc is not low level and depends on Gstreamer.
Argus Interface didn’t work for me. error occurred.
so both solution have problems.
Finally I found solution , base on GL - CUDA Interoperablity
EGLSurface eglSurface = EGL_NO_SURFACE;
EGLContext eglContext = EGL_NO_CONTEXT;
EGLConfig egl_cfg;
EGLDisplay eglDisplay = EGL_NO_DISPLAY;
int xsurfsize = 1920, ysurfsize = 1080;
cudaArray* srcArray;
int dma_CUDA_GL;
CUgraphicsResource pResource = 0;
EGLImageKHR egl_image = 0;
void* cudaPtr = 0;
cudaGraphicsResource *cudapbo;
GLuint texture;
GLuint framebuffer;
EGLint num_config;
eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(eglDisplay, nullptr, nullptr);
static const EGLint configAttribs[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_NONE
};
eglChooseConfig(eglDisplay, configAttribs, &config, 1, &num_config);
eglBindAPI(EGL_OPENGL_API);
context = eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT, NULL);
const EGLint srfPbufferAttr[] = {
EGL_WIDTH, WIDTH,
EGL_HEIGHT, HEIGHT,
EGL_NONE
};
eglSurface = eglCreatePbufferSurface(eglDisplay, config, srfPbufferAttr);
NvBufferCreateParams outPut_params = {0};
outPut_params.payloadType = NvBufferPayload_SurfArray;
outPut_params.layout = NvBufferLayout_Pitch;
outPut_params.width = xsurfsize ;
outPut_params.height = ysurfsize;
outPut_params.colorFormat = NvBufferColorFormat_ABGR32;
outPut_params.nvbuf_tag = NvBufferTag_NONE;
NvBufferCreateEx(&dma_CUDA_GL, &outPut_params);
int ret;
CUresult status;
CUeglFrame eglFrame;
// // Create EGLImage from dmabuf fd
egl_image = NvEGLImageFromFd(eglDisplay, dma_CUDA_GL);
if (egl_image == NULL)
{
printf("\n if (egl_image == NULL) \n");
}
if(egl_image != NULL)
{
cudaFree(0);
ret = cuGraphicsEGLRegisterImage(& pResource,
egl_image,
CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
if (ret != CUDA_SUCCESS) {
printf ("\n Failed to register EGLImage in cuda : %d \n",ret);
}
else
if (cuGraphicsResourceGetMappedEglFrame (&eglFrame,
pResource, 0, 0) != CUDA_SUCCESS) {
printf ("\n Failed to get mapped EGL Frame\n");
}
else
{
status = cuCtxSynchronize();
if (status != CUDA_SUCCESS) {
printf ("cuCtxSynchronize failed \n");
}
printf("\n capture width %d \n",eglFrame.width);
printf("\n capture height %d \n",eglFrame.height);
printf("\n capture depth %d \n",eglFrame.depth);
printf("\n capture pitch %d \n",eglFrame.pitch);
printf("\n capture planeCount %d \n",eglFrame.planeCount);
printf("\n capture numChannels %d \n",eglFrame.numChannels);
printf("\n capture frameType %d \n",eglFrame.frameType);
printf("\n capture eglColorFormat %d \n",eglFrame.eglColorFormat);
printf("\n capture cuFormat %d \n",eglFrame.cuFormat);
// sleep(5);
cudaPtr = ( unsigned char*)(CUdeviceptr) eglFrame.frame.pPitch[0];
status = cuCtxSynchronize();
if (status != CUDA_SUCCESS) {
printf ("cuCtxSynchronize failed after memcpy \n");
}
}
}
glGenFramebuffers( 1, &framebuffer );
glBindFramebuffer( GL_FRAMEBUFFER, framebuffer );
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0 );
// set basic parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Create texture data (4-component unsigned byte)
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, xsurfsize, ysurfsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
cudaError_t code;
code = cudaGraphicsGLRegisterImage(&cudapbo, texture,GL_TEXTURE_2D, cudaGraphicsRegisterFlagsReadOnly);
if (code != cudaSuccess)
{
fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code),__FILE__, __LINE__);
if (abort)
{
exit(code);
}
}
code = cudaGraphicsMapResources(1, &cudapbo, NULL);
if (code != cudaSuccess)
{
fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code),__FILE__, __LINE__);
if (abort)
{
exit(code);
}
}
cudaArray* srcArray;
// gpuErrchk(cudaGraphicsResourceGetMappedPointer((void**)&a_d, NULL, cudapbo));
code = cudaGraphicsSubResourceGetMappedArray( &srcArray, cudapbo, 0, 0 ) ;
if (code != cudaSuccess)
{
fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code),__FILE__, __LINE__);
if (abort)
{
exit(code);
}
}
eglMakeCurrent(display, eglSurface, eglSurface, context);
while (true)
{
glEnable(GL_SCISSOR_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glScissor(0, 0, 100, 100);
glClearColor(0.9,0.9,0.6,1);
glClear(GL_COLOR_BUFFER_BIT);
// Remember to disable scissor test, or, perhaps reset the scissor rectangle:
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
if (glGetError() != GL_NO_ERROR)
{
printf(" error %s",glGetError());
//return -1;
}
CUresult status;
status = cuCtxSynchronize();
if (status != CUDA_SUCCESS) {
printf ("cuCtxSynchronize failed after memcpy \n");
}
cudaError_t error;
// error= cudaMemcpyFromArray(cudaPtr,srcArray,0,0,xsurfsize*4*ysurfsize,cudaMemcpyDeviceToDevice);
error = cudaMemcpy2DFromArray(cudaPtr,xsurfsize*4,srcArray,0,0,xsurfsize * 4,ysurfsize,cudaMemcpyDeviceToDevice);
if(error != cudaSuccess)
printf( " \n erroer %d \n ",error);
status = cuCtxSynchronize();
if (status != CUDA_SUCCESS) {
printf ("cuCtxSynchronize failed after memcpy \n");
}
}
I created a DMA buffer and Mapped it to CUDA, after that through GL-CUDA Interoperablity I transfer GL-texture color to CUDA and copy GL-CUDA to my DMA-cuda. so I transfer GL-buffer to DMA.
problem here is one device to device copy
cudaMemcpy2DFromArray(cudaPtr,xsurfsize*4,srcArray,0,0,xsurfsize * 4,ysurfsize,cudaMemcpyDeviceToDevice);
so Any better solution without need to copy DeviceToDevice.
Does “nveglstreamsrc” have a device-to-device or VIC copy ?
Can we omit this copy?
Thanks so much.