convert direct3d surface to umat fails

asked 2018-07-03 02:33:21 -0600

dorimu gravatar image

updated 2019-12-10 01:23:48 -0600

Akhil Patel gravatar image

my GPU is NVIDIA GT 730. I compiled the opencv 4.0 with the opencl in nvidia sdk. The extension in opencl doesn't support cl_khr_dx9_media_sharing, so I change some code in directx.cpp with cl_nv_d3d9_sharing. It seems to be ok at first. The sample d3d9_interop runs correctly. However, in some cases I need to call the function initializeContextFromDirect3DDevice9 twice to initialize two direct3d device. The function convertFromDirect3DSurface9 initialized by the second device occuss error with invalid context, so I wonderd whether the initilize function has some bugs. If I initialize the same device twice, at the scend time the clCreateContext returns failure with CL_OUT_OF_HOST_MEMORY, which doesn't appears on the original source code. The code in initializeContextFromDirect3DDevice9 I modified is as follows:

Context& initializeContextFromDirect3DDevice9(IDirect3DDevice9* pDirect3DDevice9)
 {
     (void)pDirect3DDevice9;

     cl_uint numPlatforms;
     cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
     if (status != CL_SUCCESS)
         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
     if (numPlatforms == 0)
         CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");

     std::vector<cl_platform_id> platforms(numPlatforms);
     status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
     if (status != CL_SUCCESS)
         CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");

     // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE

     int found = -1;
     cl_device_id device = NULL;
     cl_uint numDevices = 0;
     cl_context context = NULL;

     for (int i = 0; i < (int)numPlatforms; i++)
     {
         clGetDeviceIDsFromD3D9NV_fn clGetDeviceIDsFromD3D9NV = (clGetDeviceIDsFromD3D9NV_fn)
            clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D9NV");
         if (!clGetDeviceIDsFromD3D9NV)
             continue;

         device = NULL;
         numDevices = 0;
        //cl_d3d9_device_source_nv type = CL_D3D9_DEVICE_NV;
         status = clGetDeviceIDsFromD3D9NV(platforms[i], CL_D3D9_DEVICE_NV, pDirect3DDevice9,
                 CL_PREFERRED_DEVICES_FOR_D3D9_NV, 1, &device, &numDevices);
         if (status != CL_SUCCESS)
             continue;
         if (numDevices > 0)
         {
             cl_context_properties properties[] = {
                CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i], 
                CL_CONTEXT_D3D9_DEVICE_NV, (cl_context_properties)(pDirect3DDevice9),
                //CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,  //do not supprot
                NULL, NULL, 0   //ended with 0
              };
             context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
             if (status != CL_SUCCESS)
             {
                 clReleaseDevice(device);
             }
             else
             {
                 found = i;
                 break;
             }
         }
     }

     if (found < 0)
     {
         // try with CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
         for (int i = 0; i < (int)numPlatforms; i++)
         {
        clGetDeviceIDsFromD3D9NV_fn clGetDeviceIDsFromD3D9NV = (clGetDeviceIDsFromD3D9NV_fn)
                     clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D9NV");
             if (!clGetDeviceIDsFromD3D9NV)
                 continue;

             device = NULL;
             numDevices = 0;

             status = clGetDeviceIDsFromD3D9NV(platforms[i], CL_D3D9_DEVICE_NV, pDirect3DDevice9,
            CL_ALL_DEVICES_FOR_D3D9_NV, 1, &device, &numDevices);
             if (status != CL_SUCCESS)
                 continue;
             if (numDevices > 0)
             {
             cl_context_properties properties[] = {
                    CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i], 
                    CL_CONTEXT_D3D9_DEVICE_NV, (cl_context_properties)(pDirect3DDevice9),
                //CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,   //do not support
                NULL, NULL, 0
                };
                 context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
                 if (status != CL_SUCCESS)
                 {
                     clReleaseDevice(device);
                 }
                 else
                 {
                     found = i;
                     break;
                 }
             }
         }
         if (found < 0)
             CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
     }

     Context& ctx = Context::getDefault(false);
     initializeContextFromHandle(ctx, platforms[found], context, device);
     g_isDirect3DDevice9Ex = false;
     return ctx;
 }

Could someone help me? Thanks!

edit retag flag offensive close merge delete