convert direct3d surface to umat fails
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!