/* * cuda_consumer.cpp * * Copyright 2016 NVIDIA Corporation. All rights reserved. * * Please refer to the NVIDIA end user license agreement (EULA) associated * with this source code for terms and conditions that govern your use of * this software. Any use, reproduction, disclosure, or distribution of * this software and related documentation outside the terms of the EULA * is strictly prohibited. * */ // // DESCRIPTION: Simple CUDA consumer rendering sample app // #include "cuda_consumer.h" #include #include "eglstrm_common.h" #if defined(EXTENSION_LIST) EXTENSION_LIST(EXTLST_EXTERN) #endif int checkbuf(FILE *fp1, FILE *fp2); CUresult cudaConsumerTest(test_cuda_consumer_s *data, char *fileName) { CUresult cuStatus = CUDA_SUCCESS; CUarray cudaArr = NULL; CUeglFrame cudaEgl; CUgraphicsResource cudaResource; unsigned int i; int check_result; FILE *pInFile1 = NULL, *pInFile2 = NULL, *file_p = NULL; EGLint streamState = 0; if (!data) { printf("%s: Bad parameter\n", __func__); goto done; } if (!eglQueryStreamKHR(g_display, eglStream, EGL_STREAM_STATE_KHR, &streamState)) { printf("Cuda consumer, eglQueryStreamKHR EGL_STREAM_STATE_KHR failed\n"); } if (streamState == EGL_STREAM_STATE_DISCONNECTED_KHR) { printf("CUDA Consumer: - EGL_STREAM_STATE_DISCONNECTED_KHR received\n"); } if (streamState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) { cuStatus = cuEGLStreamConsumerAcquireFrame(&(data->cudaConn), &cudaResource, NULL, 16000); if (cuStatus == CUDA_SUCCESS) { CUdeviceptr pDevPtr = 0; int bufferSize; unsigned char *pCudaCopyMem = NULL; unsigned int copyWidthInBytes = 0, copyHeight = 0; file_p = fopen(fileName, "wb+"); if (!file_p) { printf("WriteFrame: file open failed %s\n", fileName); cuStatus = CUDA_ERROR_UNKNOWN; goto done; } cuStatus = cuGraphicsResourceGetMappedEglFrame(&cudaEgl, cudaResource, 0, 0); if (cuStatus != CUDA_SUCCESS) { printf("Cuda get resource failed with %d\n", cuStatus); goto done; } cuStatus = cuCtxSynchronize(); if (cuStatus != CUDA_SUCCESS) { printf("cuCtxSynchronize failed \n"); goto done; } if (!(cudaEgl.planeCount >= 1 && cudaEgl.planeCount <= 3)) { printf("Plane count is invalid\nExiting\n"); goto done; } for (i = 0; i < cudaEgl.planeCount; i++) { if (cudaEgl.frameType == CU_EGL_FRAME_TYPE_PITCH) { pDevPtr = (CUdeviceptr)cudaEgl.frame.pPitch[i]; if (cudaEgl.planeCount == 1) { bufferSize = cudaEgl.pitch * cudaEgl.height; copyWidthInBytes = cudaEgl.pitch; copyHeight = data->height; } else if (i == 1 && cudaEgl.planeCount == 2) { // YUV 420 // semi-planar bufferSize = cudaEgl.pitch * cudaEgl.height / 2; copyWidthInBytes = cudaEgl.pitch; copyHeight = data->height / 2; } else { bufferSize = data->width * data->height; copyWidthInBytes = data->width; copyHeight = data->height; if (i > 0) { bufferSize >>= 2; copyWidthInBytes >>= 1; copyHeight >>= 1; } } } else { cudaArr = cudaEgl.frame.pArray[i]; if (cudaEgl.planeCount == 1) { bufferSize = data->width * data->height * 4; copyWidthInBytes = data->width * 4; copyHeight = data->height; } else if (i == 1 && cudaEgl.planeCount == 2) { // YUV 420 // semi-planar bufferSize = data->width * data->height / 2; copyWidthInBytes = data->width; copyHeight = data->height / 2; } else { bufferSize = data->width * data->height; copyWidthInBytes = data->width; copyHeight = data->height; if (i > 0) { bufferSize >>= 2; copyWidthInBytes >>= 1; copyHeight >>= 1; } } } if (i == 0) { pCudaCopyMem = (unsigned char *)malloc(bufferSize); if (pCudaCopyMem == NULL) { printf("pCudaCopyMem malloc failed\n"); goto done; } } memset(pCudaCopyMem, 0, bufferSize); if (data->pitchLinearOutput) { cuStatus = cuMemcpyDtoH(pCudaCopyMem, pDevPtr, bufferSize); if (cuStatus != CUDA_SUCCESS) { printf( "cuda_consumer: pitch linear Memcpy failed, bufferSize =%d\n", bufferSize); goto done; } cuStatus = cuCtxSynchronize(); if (cuStatus != CUDA_SUCCESS) { printf("cuda_consumer: cuCtxSynchronize failed after memcpy \n"); goto done; } } else { CUDA_MEMCPY3D cpdesc; memset(&cpdesc, 0, sizeof(cpdesc)); cpdesc.srcXInBytes = cpdesc.srcY = cpdesc.srcZ = cpdesc.srcLOD = 0; cpdesc.srcMemoryType = CU_MEMORYTYPE_ARRAY; cpdesc.srcArray = cudaArr; cpdesc.dstXInBytes = cpdesc.dstY = cpdesc.dstZ = cpdesc.dstLOD = 0; cpdesc.dstMemoryType = CU_MEMORYTYPE_HOST; cpdesc.dstHost = (void *)pCudaCopyMem; cpdesc.WidthInBytes = copyWidthInBytes; // data->width * 4; cpdesc.Height = copyHeight; // data->height; cpdesc.Depth = 1; cuStatus = cuMemcpy3D(&cpdesc); if (cuStatus != CUDA_SUCCESS) { printf( "Cuda consumer: cuMemCpy3D failed, copyWidthInBytes=%d, " "copyHight=%d\n", copyWidthInBytes, copyHeight); } cuStatus = cuCtxSynchronize(); if (cuStatus != CUDA_SUCCESS) { printf("cuCtxSynchronize failed after memcpy \n"); } } if (cuStatus == CUDA_SUCCESS) { if (fwrite(pCudaCopyMem, bufferSize, 1, file_p) != 1) { printf("Cuda consumer: output file write failed\n"); cuStatus = CUDA_ERROR_UNKNOWN; goto done; } } } pInFile1 = fopen(data->fileName1, "rb"); if (!pInFile1) { printf("Failed to open file :%s\n", data->fileName1); goto done; } pInFile2 = fopen(data->fileName2, "rb"); if (!pInFile2) { printf("Failed to open file :%s\n", data->fileName2); goto done; } rewind(file_p); check_result = checkbuf(file_p, pInFile1); if (check_result == -1) { rewind(file_p); check_result = checkbuf(file_p, pInFile2); if (check_result == -1) { printf("Frame received does not match any valid image: FAILED\n"); } else { printf("Frame check Passed\n"); } } else { printf("Frame check Passed\n"); } if (pCudaCopyMem) { free(pCudaCopyMem); pCudaCopyMem = NULL; } cuStatus = cuEGLStreamConsumerReleaseFrame(&data->cudaConn, cudaResource, NULL); if (cuStatus != CUDA_SUCCESS) { printf("cuEGLStreamConsumerReleaseFrame failed with cuStatus = %d\n", cuStatus); goto done; } } else { printf("cuda AcquireFrame FAILED with cuStatus=%d\n", cuStatus); goto done; } } done: if (file_p) { fclose(file_p); file_p = NULL; } if (pInFile1) { fclose(pInFile1); pInFile1 = NULL; } if (pInFile1) { fclose(pInFile2); pInFile2 = NULL; } return cuStatus; } int checkbuf(FILE *fp1, FILE *fp2) { int match = 0; int ch1, ch2; if (fp1 == NULL) { printf("Invalid file pointer for first file\n"); return -1; } else if (fp2 == NULL) { printf("Invalid file pointer for second file\n"); return -1; } else { ch1 = getc(fp1); ch2 = getc(fp2); while ((ch1 != EOF) && (ch2 != EOF) && (ch1 == ch2)) { ch1 = getc(fp1); ch2 = getc(fp2); } if (ch1 == ch2) { match = 1; } else if (ch1 != ch2) { match = -1; } } return match; } CUresult cudaDeviceCreateConsumer(test_cuda_consumer_s *cudaConsumer, CUdevice device) { CUresult status = CUDA_SUCCESS; if (CUDA_SUCCESS != (status = cuInit(0))) { printf("Failed to initialize CUDA\n"); return status; } int major = 0, minor = 0; char deviceName[256]; checkCudaErrors(cuDeviceGetAttribute( &major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, device)); checkCudaErrors(cuDeviceGetAttribute( &minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, device)); checkCudaErrors(cuDeviceGetName(deviceName, 256, device)); printf( "CUDA Consumer on GPU Device %d: \"%s\" with compute capability " "%d.%d\n\n", device, deviceName, major, minor); if (CUDA_SUCCESS != (status = cuCtxCreate(&cudaConsumer->context, 0, device))) { printf("failed to create CUDA context\n"); return status; } checkCudaErrors(cuCtxPopCurrent(&cudaConsumer->context)); return status; } void cuda_consumer_init(test_cuda_consumer_s *cudaConsumer, TestArgs *args) { cudaConsumer->pitchLinearOutput = args->pitchLinearOutput; cudaConsumer->width = args->inputWidth; cudaConsumer->height = args->inputHeight; cudaConsumer->fileName1 = args->infile1; cudaConsumer->fileName2 = args->infile2; cudaConsumer->outFile1 = "cuda_out1.yuv"; cudaConsumer->outFile2 = "cuda_out2.yuv"; } CUresult cuda_consumer_deinit(test_cuda_consumer_s *cudaConsumer) { return cuEGLStreamConsumerDisconnect(&cudaConsumer->cudaConn); }