Add CUDA support for D3D11 interop. #13888

color_detail.hpp: fixed build error : dynamic initialization is not supported for a __constant__ variable.
directx.cpp: Add CUDA support(cl_nv_d3d11_sharing) for D3D11 interop.  #13888

Update directx.cpp

Format adjustment.

Update directx.cpp

fix error.

Update directx.cpp

Format adjustment

Update directx.cpp

fix trailing whitespace.

fix format errors

convert indentation to spaces .
Trim trailing whitespace.
Add information about source of cl_d3d11_ext.h
Avoid unrelated changes.

Increase compile-time conditional judgment.

Increase the judgment of whether the OCL device has the required extensions at compile time.

Add compilation option  `HAVE_CLNVEXT`.Check CL support in runtime.

Check result of `clGetExtensionFunctionAddressForPlatform` for KHR is invalid.It always can get the address(from OpenCL.dll),So I check NV support(from nvopencl64.dll) before KHR when `HAVE_CLNVEXT` is enabled.

Delete cl_d3d11_ext.h

Modified parameter list

fix "cannot open include file: 'CL/cl_d3d11_ext.h'"

 remove not referenced var

fix C2143: syntax error

Improve compile-time judgment.

dlrectx.cpp Modify the detection order.
initializeContextFromD3D11Device:
```
    // try with NV(Need to check it first)
    // try with KHR
```

fix warnig C4100

Revert "fix warnig C4100"

This reverts commit 76e5becb67780071d0cbde61cc4f5f807ad7c5ac.

fix warning C4100

fix warning C4505

Format alignment

Format adjustment and automatically detect header files.

Automatically detect header files when users are not configured or configuration errors occur.

avoid unrelated changes.

Update .cmake

Update .cmake
pull/13972/head
WangGuobao 6 years ago committed by Mainvooid
parent 73bf170800
commit 0e0229852e
  1. 4
      CMakeLists.txt
  2. 25
      cmake/OpenCVDetectOpenCL.cmake
  3. 3
      cmake/templates/cvconfig.h.in
  4. 424
      modules/core/src/directx.cpp
  5. 3
      modules/core/src/directx.inc.hpp

@ -384,6 +384,9 @@ OCV_OPTION(WITH_OPENCLAMDFFT "Include AMD OpenCL FFT library support" ON
OCV_OPTION(WITH_OPENCLAMDBLAS "Include AMD OpenCL BLAS library support" ON
VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT
VERIFY HAVE_CLAMDBLAS)
OCV_OPTION(WITH_OPENCL_D3D11_NV "Include NVIDIA OpenCL D3D11 support" OFF
VISIBLE_IF WIN32 AND NOT WINRT
VERIFY HAVE_OPENCL_D3D11_NV)
OCV_OPTION(WITH_DIRECTX "Include DirectX support" ON
VISIBLE_IF WIN32 AND NOT WINRT
VERIFY HAVE_DIRECTX)
@ -1614,6 +1617,7 @@ if(WITH_OPENCL OR HAVE_OPENCL)
IF HAVE_OPENCL_SVM THEN "SVM"
IF HAVE_CLAMDFFT THEN "AMDFFT"
IF HAVE_CLAMDBLAS THEN "AMDBLAS"
IF HAVE_OPENCL_D3D11_NV THEN "NVD3D11"
ELSE "no extra features")
status("")
status(" OpenCL:" HAVE_OPENCL THEN "YES (${opencl_features})" ELSE "NO")

@ -2,11 +2,30 @@ set(OPENCL_FOUND ON CACHE BOOL "OpenCL library is found")
if(APPLE)
set(OPENCL_LIBRARY "-framework OpenCL" CACHE STRING "OpenCL library")
set(OPENCL_INCLUDE_DIR "" CACHE PATH "OpenCL include directory")
else(APPLE)
else()
set(OPENCL_LIBRARY "" CACHE STRING "OpenCL library")
set(OPENCL_INCLUDE_DIR "${OpenCV_SOURCE_DIR}/3rdparty/include/opencl/1.2" CACHE PATH "OpenCL include directory")
if(WITH_OPENCL_D3D11_NV)
if(NOT EXISTS "${OPENCL_INCLUDE_DIR}/CL/cl_d3d11_ext.h")
message(STATUS "CL/cl_d3d11_ext.h not found in OPENCL_INCLUDE_DIR. Automatic detection has been turned on")
unset(OPENCL_INCLUDE_DIR CACHE)
find_path(OPENCL_INCLUDE_DIR
NAMES CL/cl_d3d11_ext.h
PATHS ENV CUDA_PATH ENV ProgramFiles
PATH_SUFFIXES include
DOC "Extended opencl include directory")
if(OPENCL_INCLUDE_DIR)
set(HAVE_OPENCL_D3D11_NV ON)
else()
message(WARNING "Header file cl_d3d11_ext.h not found")
endif()
else()
set(HAVE_OPENCL_D3D11_NV ON)
endif()
else()
set(OPENCL_INCLUDE_DIR "${OpenCV_SOURCE_DIR}/3rdparty/include/opencl/1.2" CACHE PATH "OpenCL include directory")
endif()
ocv_install_3rdparty_licenses(opencl-headers "${OpenCV_SOURCE_DIR}/3rdparty/include/opencl/LICENSE.txt")
endif(APPLE)
endif()
mark_as_advanced(OPENCL_INCLUDE_DIR OPENCL_LIBRARY)
if(OPENCL_FOUND)

@ -136,6 +136,9 @@
#cmakedefine HAVE_OPENCL_STATIC
#cmakedefine HAVE_OPENCL_SVM
/* NVIDIA OpenCL D3D Extensions support */
#cmakedefine HAVE_OPENCL_D3D11_NV
/* OpenEXR codec */
#cmakedefine HAVE_OPENEXR

@ -48,13 +48,17 @@
#ifdef HAVE_DIRECTX
#include <vector>
# include "directx.inc.hpp"
#include "directx.inc.hpp"
#else // HAVE_DIRECTX
#define NO_DIRECTX_SUPPORT_ERROR CV_Error(cv::Error::StsBadFunc, "OpenCV was build without DirectX support")
#endif
#ifndef HAVE_OPENCL
# define NO_OPENCL_SUPPORT_ERROR CV_Error(cv::Error::StsBadFunc, "OpenCV was build without OpenCL support")
#define NO_OPENCL_SUPPORT_ERROR CV_Error(cv::Error::StsBadFunc, "OpenCV was build without OpenCL support")
#endif // HAVE_OPENCL
#ifndef HAVE_OPENCL_D3D11_NV
#define NO_OPENCL_D3D11_NV_SUPPORT_ERROR CV_Error(cv::Error::StsBadFunc, "OpenCV was build without OpenCL Nvidia D3D11 extension support")
#endif // HAVE_OPENCL
namespace cv { namespace directx {
@ -168,7 +172,7 @@ int getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT)
//case DXGI_FORMAT_BC7_TYPELESS:
//case DXGI_FORMAT_BC7_UNORM:
//case DXGI_FORMAT_BC7_UNORM_SRGB:
#ifdef HAVE_DIRECTX_NV12
#ifdef HAVE_DIRECTX_NV12 //D3DX11 should support DXGI_FORMAT_NV12.
case DXGI_FORMAT_NV12: return CV_8UC3;
#endif
default: break;
@ -260,35 +264,35 @@ Context& initializeContextFromD3D11Device(ID3D11Device* pD3D11Device)
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;
// try with CL_PREFERRED_DEVICES_FOR_D3D11_KHR
#ifdef HAVE_OPENCL_D3D11_NV
// try with CL_PREFERRED_DEVICES_FOR_D3D11_NV(Need to check it first)
for (int i = 0; i < (int)numPlatforms; i++)
{
clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = (clGetDeviceIDsFromD3D11KHR_fn)
clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11KHR");
if (!clGetDeviceIDsFromD3D11KHR)
clGetDeviceIDsFromD3D11NV_fn clGetDeviceIDsFromD3D11NV = (clGetDeviceIDsFromD3D11NV_fn)
clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11NV");
if (!clGetDeviceIDsFromD3D11NV)
continue;
device = NULL;
numDevices = 0;
status = clGetDeviceIDsFromD3D11KHR(platforms[i], CL_D3D11_DEVICE_KHR, pD3D11Device,
CL_PREFERRED_DEVICES_FOR_D3D11_KHR, 1, &device, &numDevices);
status = clGetDeviceIDsFromD3D11NV(platforms[i], CL_D3D11_DEVICE_NV, pD3D11Device,
CL_PREFERRED_DEVICES_FOR_D3D11_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_D3D11_DEVICE_KHR, (cl_context_properties)(pD3D11Device),
CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
NULL, NULL
CL_CONTEXT_D3D11_DEVICE_NV, (cl_context_properties)(pD3D11Device),
//CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
0
};
context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
if (status != CL_SUCCESS)
{
@ -302,6 +306,83 @@ Context& initializeContextFromD3D11Device(ID3D11Device* pD3D11Device)
}
}
if (found < 0)
{
// try with CL_ALL_DEVICES_FOR_D3D11_NV
for (int i = 0; i < (int)numPlatforms; i++)
{
clGetDeviceIDsFromD3D11NV_fn clGetDeviceIDsFromD3D11NV = (clGetDeviceIDsFromD3D11NV_fn)
clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11NV");
if (!clGetDeviceIDsFromD3D11NV)
continue;
device = NULL;
numDevices = 0;
status = clGetDeviceIDsFromD3D11NV(platforms[i], CL_D3D11_DEVICE_NV, pD3D11Device,
CL_ALL_DEVICES_FOR_D3D11_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_D3D11_DEVICE_NV, (cl_context_properties)(pD3D11Device),
//CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
0
};
context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
if (status != CL_SUCCESS)
{
clReleaseDevice(device);
}
else
{
found = i;
break;
}
}
}
}
#endif
if (found < 0)
{
// try with CL_PREFERRED_DEVICES_FOR_D3D11_KHR
for (int i = 0; i < (int)numPlatforms; i++)
{
clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = (clGetDeviceIDsFromD3D11KHR_fn)
clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11KHR");
if (!clGetDeviceIDsFromD3D11KHR)
continue;
device = NULL;
numDevices = 0;
status = clGetDeviceIDsFromD3D11KHR(platforms[i], CL_D3D11_DEVICE_KHR, pD3D11Device,
CL_PREFERRED_DEVICES_FOR_D3D11_KHR, 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_D3D11_DEVICE_KHR, (cl_context_properties)(pD3D11Device),
CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
NULL, NULL
};
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_D3D11_KHR
for (int i = 0; i < (int)numPlatforms; i++)
@ -337,10 +418,11 @@ Context& initializeContextFromD3D11Device(ID3D11Device* pD3D11Device)
}
}
}
if (found < 0)
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
}
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);
@ -678,32 +760,60 @@ Context& initializeContextFromDirect3DDevice9(IDirect3DDevice9* pDirect3DDevice9
} // namespace cv::ocl
#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
#ifdef HAVE_OPENCL_D3D11_NV
clCreateFromD3D11Texture2DNV_fn clCreateFromD3D11Texture2DNV = NULL;
clEnqueueAcquireD3D11ObjectsNV_fn clEnqueueAcquireD3D11ObjectsNV = NULL;
clEnqueueReleaseD3D11ObjectsNV_fn clEnqueueReleaseD3D11ObjectsNV = NULL;
#endif
clCreateFromD3D11Texture2DKHR_fn clCreateFromD3D11Texture2DKHR = NULL;
clEnqueueAcquireD3D11ObjectsKHR_fn clEnqueueAcquireD3D11ObjectsKHR = NULL;
clEnqueueReleaseD3D11ObjectsKHR_fn clEnqueueReleaseD3D11ObjectsKHR = NULL;
static void __OpenCLinitializeD3D11()
static bool __OpenCLinitializeD3D11()
{
using namespace cv::ocl;
static cl_platform_id initializedPlatform = NULL;
cl_platform_id platform = (cl_platform_id)Platform::getDefault().ptr();
bool useCLNVEXT = false;
#ifdef HAVE_OPENCL_D3D11_NV
if (initializedPlatform != platform)
{
clCreateFromD3D11Texture2DKHR = (clCreateFromD3D11Texture2DKHR_fn)
clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromD3D11Texture2DKHR");
clEnqueueAcquireD3D11ObjectsKHR = (clEnqueueAcquireD3D11ObjectsKHR_fn)
clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireD3D11ObjectsKHR");
clEnqueueReleaseD3D11ObjectsKHR = (clEnqueueReleaseD3D11ObjectsKHR_fn)
clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseD3D11ObjectsKHR");
clCreateFromD3D11Texture2DNV = (clCreateFromD3D11Texture2DNV_fn)
clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromD3D11Texture2DNV");
clEnqueueAcquireD3D11ObjectsNV = (clEnqueueAcquireD3D11ObjectsNV_fn)
clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireD3D11ObjectsNV");
clEnqueueReleaseD3D11ObjectsNV = (clEnqueueReleaseD3D11ObjectsNV_fn)
clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseD3D11ObjectsNV");
initializedPlatform = platform;
}
if (!clCreateFromD3D11Texture2DKHR || !clEnqueueAcquireD3D11ObjectsKHR || !clEnqueueReleaseD3D11ObjectsKHR)
if (clCreateFromD3D11Texture2DNV && clEnqueueAcquireD3D11ObjectsNV && clEnqueueReleaseD3D11ObjectsNV)
{
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D11");
useCLNVEXT =true;
}
else
#endif
{
if (initializedPlatform != platform)
{
clCreateFromD3D11Texture2DKHR = (clCreateFromD3D11Texture2DKHR_fn)
clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromD3D11Texture2DKHR");
clEnqueueAcquireD3D11ObjectsKHR = (clEnqueueAcquireD3D11ObjectsKHR_fn)
clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireD3D11ObjectsKHR");
clEnqueueReleaseD3D11ObjectsKHR = (clEnqueueReleaseD3D11ObjectsKHR_fn)
clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseD3D11ObjectsKHR");
initializedPlatform = platform;
}
if (!clCreateFromD3D11Texture2DKHR || !clEnqueueAcquireD3D11ObjectsKHR || !clEnqueueReleaseD3D11ObjectsKHR)
{
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D11");
}
}
return useCLNVEXT;
}
#endif // defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
#endif // defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
} // namespace directx
@ -733,7 +843,6 @@ bool ocl_convert_nv12_to_bgr(
return k.run(2, globalsize, 0, false);
}
static
bool ocl_convert_bgr_to_nv12(
cl_mem clBuffer,
@ -759,17 +868,9 @@ bool ocl_convert_bgr_to_nv12(
} // namespace ocl
namespace directx {
void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D)
{
CV_UNUSED(src); CV_UNUSED(pD3D11Texture2D);
#if !defined(HAVE_DIRECTX)
NO_DIRECTX_SUPPORT_ERROR;
#elif defined(HAVE_OPENCL)
__OpenCLinitializeD3D11();
static void __convertToD3D11Texture2DKHR(InputArray src, ID3D11Texture2D* pD3D11Texture2D){
D3D11_TEXTURE2D_DESC desc = { 0 };
pD3D11Texture2D->GetDesc(&desc);
@ -797,7 +898,6 @@ void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D)
#ifdef HAVE_DIRECTX_NV12
cl_mem clImageUV = 0;
#endif
clImage = clCreateFromD3D11Texture2DKHR(context, CL_MEM_WRITE_ONLY, pD3D11Texture2D, 0, &status);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DKHR failed");
@ -812,7 +912,6 @@ void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D)
#endif
cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
status = clEnqueueAcquireD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsKHR failed");
@ -863,22 +962,109 @@ void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
}
#endif
}
static void __convertToD3D11Texture2DNV(InputArray src, ID3D11Texture2D* pD3D11Texture2D){
CV_UNUSED(src); CV_UNUSED(pD3D11Texture2D);
#if !defined(HAVE_OPENCL_D3D11_NV)
NO_OPENCL_D3D11_NV_SUPPORT_ERROR;
#else
// TODO memcpy
NO_OPENCL_SUPPORT_ERROR;
D3D11_TEXTURE2D_DESC desc = { 0 };
pD3D11Texture2D->GetDesc(&desc);
int srcType = src.type();
int textureType = getTypeFromDXGI_FORMAT(desc.Format);
CV_Assert(textureType == srcType);
Size srcSize = src.size();
CV_Assert(srcSize.width == (int)desc.Width && srcSize.height == (int)desc.Height);
UMat u = src.getUMat();
// TODO Add support for roi
CV_Assert(u.offset == 0);
CV_Assert(u.isContinuous());
cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
using namespace cv::ocl;
Context& ctx = Context::getDefault();
cl_context context = (cl_context)ctx.ptr();
cl_int status = 0;
cl_mem clImage = 0;
#ifdef HAVE_DIRECTX_NV12
cl_mem clImageUV = 0;
#endif
}
clImage = clCreateFromD3D11Texture2DNV(context, CL_MEM_WRITE_ONLY, pD3D11Texture2D, 0, &status);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DNV failed");
#ifdef HAVE_DIRECTX_NV12
if (DXGI_FORMAT_NV12 == desc.Format)
{
clImageUV = clCreateFromD3D11Texture2DNV(context, CL_MEM_WRITE_ONLY, pD3D11Texture2D, 1, &status);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DNV failed");
}
#endif
cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
status = clEnqueueAcquireD3D11ObjectsNV(q, 1, &clImage, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsNV failed");
void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst)
{
CV_UNUSED(pD3D11Texture2D); CV_UNUSED(dst);
#if !defined(HAVE_DIRECTX)
NO_DIRECTX_SUPPORT_ERROR;
#elif defined(HAVE_OPENCL)
__OpenCLinitializeD3D11();
#ifdef HAVE_DIRECTX_NV12
if(DXGI_FORMAT_NV12 == desc.Format)
{
status = clEnqueueAcquireD3D11ObjectsNV(q, 1, &clImageUV, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsNV failed");
if(!ocl::ocl_convert_bgr_to_nv12(clBuffer, (int)u.step[0], u.cols, u.rows, clImage, clImageUV))
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: ocl_convert_bgr_to_nv12 failed");
status = clEnqueueReleaseD3D11ObjectsNV(q, 1, &clImageUV, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsNV failed");
}
else
#endif
{
size_t offset = 0; // TODO
size_t origin[3] = { 0, 0, 0 };
size_t region[3] = { (size_t)u.cols, (size_t)u.rows, 1 };
status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, origin, region, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed");
}
status = clEnqueueReleaseD3D11ObjectsNV(q, 1, &clImage, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsNV failed");
status = clFinish(q); // TODO Use events
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
status = clReleaseMemObject(clImage); // TODO RAII
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
#ifdef HAVE_DIRECTX_NV12
if(DXGI_FORMAT_NV12 == desc.Format)
{
status = clReleaseMemObject(clImageUV);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
}
#endif
#endif // HAVE_OPENCL_D3D11_NV
}
static void __convertFromD3D11Texture2DKHR(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst)
{
D3D11_TEXTURE2D_DESC desc = { 0 };
pD3D11Texture2D->GetDesc(&desc);
@ -917,7 +1103,6 @@ void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst
#endif
cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
status = clEnqueueAcquireD3D11ObjectsKHR(q, 1, &clImage, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsKHR failed");
@ -968,10 +1153,145 @@ void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
}
#endif
}
static void __convertFromD3D11Texture2DNV(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst)
{
CV_UNUSED(pD3D11Texture2D); CV_UNUSED(dst);
#if !defined(HAVE_OPENCL_D3D11_NV)
NO_OPENCL_D3D11_NV_SUPPORT_ERROR;
#else
// TODO memcpy
D3D11_TEXTURE2D_DESC desc = { 0 };
pD3D11Texture2D->GetDesc(&desc);
int textureType = getTypeFromDXGI_FORMAT(desc.Format);
CV_Assert(textureType >= 0);
// TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!
dst.create(Size(desc.Width, desc.Height), textureType);
UMat u = dst.getUMat();
// TODO Add support for roi
CV_Assert(u.offset == 0);
CV_Assert(u.isContinuous());
cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
using namespace cv::ocl;
Context& ctx = Context::getDefault();
cl_context context = (cl_context)ctx.ptr();
cl_int status = 0;
cl_mem clImage = 0;
clImage = clCreateFromD3D11Texture2DNV(context, CL_MEM_READ_ONLY, pD3D11Texture2D, 0, &status);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DNV failed");
#ifdef HAVE_DIRECTX_NV12
cl_mem clImageUV = 0;
if(DXGI_FORMAT_NV12 == desc.Format)
{
clImageUV = clCreateFromD3D11Texture2DNV(context, CL_MEM_READ_ONLY, pD3D11Texture2D, 1, &status);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DNV failed");
}
#endif
cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
status = clEnqueueAcquireD3D11ObjectsNV(q, 1, &clImage, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsNV failed");
#ifdef HAVE_DIRECTX_NV12
if (DXGI_FORMAT::DXGI_FORMAT_NV12 == desc.Format)
{
status = clEnqueueAcquireD3D11ObjectsNV(q, 1, &clImageUV, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsNV failed");
if (!ocl::ocl_convert_nv12_to_bgr(clImage, clImageUV, clBuffer, (int)u.step[0], u.cols, u.rows))
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: ocl_convert_nv12_to_bgr failed");
status = clEnqueueReleaseD3D11ObjectsNV(q, 1, &clImageUV, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsNV failed");
}
else
#endif
{
size_t offset = 0; // TODO
size_t origin[3] = { 0, 0, 0 };
size_t region[3] = { (size_t)u.cols, (size_t)u.rows, 1 };
status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, origin, region, offset, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed");
}
status = clEnqueueReleaseD3D11ObjectsNV(q, 1, &clImage, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsNV failed");
status = clFinish(q); // TODO Use events
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
status = clReleaseMemObject(clImage); // TODO RAII
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
#ifdef HAVE_DIRECTX_NV12
if(DXGI_FORMAT_NV12 == desc.Format)
{
status = clReleaseMemObject(clImageUV);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
}
#endif
#endif // HAVE_OPENCL_D3D11_NV
}
void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D)
{
CV_UNUSED(src); CV_UNUSED(pD3D11Texture2D);
#if !defined(HAVE_DIRECTX)
NO_DIRECTX_SUPPORT_ERROR;
#elif !defined(HAVE_OPENCL)
NO_OPENCL_SUPPORT_ERROR;
#else
bool useCLNVEXT = __OpenCLinitializeD3D11();
if(!useCLNVEXT){
__convertToD3D11Texture2DKHR(src,pD3D11Texture2D);
}
else
{
__convertToD3D11Texture2DNV(src,pD3D11Texture2D);
}
#endif
}
void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst)
{
CV_UNUSED(pD3D11Texture2D); CV_UNUSED(dst);
#if !defined(HAVE_DIRECTX)
NO_DIRECTX_SUPPORT_ERROR;
#elif !defined(HAVE_OPENCL)
NO_OPENCL_SUPPORT_ERROR;
#else
bool useCLNVEXT = __OpenCLinitializeD3D11();
if(!useCLNVEXT){
__convertFromD3D11Texture2DKHR(pD3D11Texture2D,dst);
}
else
{
__convertFromD3D11Texture2DNV(pD3D11Texture2D,dst);
}
#endif
}

@ -48,6 +48,9 @@
#include "opencv2/core/opencl/runtime/opencl_core.hpp"
#include <CL/cl_d3d11.h>
#ifdef HAVE_OPENCL_D3D11_NV
#include <CL/cl_d3d11_ext.h>
#endif
#include <CL/cl_d3d10.h>
#include <CL/cl_dx9_media_sharing.h>
#endif // HAVE_OPENCL

Loading…
Cancel
Save