Using cl_khr_d3d11_sharing and cl_intel_d3d11_nv12_media_sharing.
Mark Thompson authored on 2017/06/26 06:34:40... | ... |
@@ -2120,6 +2120,7 @@ HAVE_LIST=" |
2120 | 2120 |
$TYPES_LIST |
2121 | 2121 |
makeinfo |
2122 | 2122 |
makeinfo_html |
2123 |
+ opencl_d3d11 |
|
2123 | 2124 |
opencl_dxva2 |
2124 | 2125 |
opencl_vaapi_beignet |
2125 | 2126 |
opencl_vaapi_intel_media |
... | ... |
@@ -6172,6 +6173,11 @@ if enabled_all opencl dxva2 ; then |
6172 | 6172 |
enable opencl_dxva2 |
6173 | 6173 |
fi |
6174 | 6174 |
|
6175 |
+if enabled_all opencl d3d11va ; then |
|
6176 |
+ check_type "CL/cl_d3d11.h" clGetDeviceIDsFromD3D11KHR_fn && |
|
6177 |
+ enable opencl_d3d11 |
|
6178 |
+fi |
|
6179 |
+ |
|
6175 | 6180 |
enabled vdpau && |
6176 | 6181 |
check_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || |
6177 | 6182 |
disable vdpau |
... | ... |
@@ -51,6 +51,11 @@ |
51 | 51 |
#include "hwcontext_dxva2.h" |
52 | 52 |
#endif |
53 | 53 |
|
54 |
+#if HAVE_OPENCL_D3D11 |
|
55 |
+#include <CL/cl_d3d11.h> |
|
56 |
+#include "hwcontext_d3d11va.h" |
|
57 |
+#endif |
|
58 |
+ |
|
54 | 59 |
|
55 | 60 |
typedef struct OpenCLDeviceContext { |
56 | 61 |
// Default command queue to use for transfer/mapping operations on |
... | ... |
@@ -89,6 +94,16 @@ typedef struct OpenCLDeviceContext { |
89 | 89 |
clEnqueueReleaseDX9MediaSurfacesKHR_fn |
90 | 90 |
clEnqueueReleaseDX9MediaSurfacesKHR; |
91 | 91 |
#endif |
92 |
+ |
|
93 |
+#if HAVE_OPENCL_D3D11 |
|
94 |
+ int d3d11_mapping_usable; |
|
95 |
+ clCreateFromD3D11Texture2DKHR_fn |
|
96 |
+ clCreateFromD3D11Texture2DKHR; |
|
97 |
+ clEnqueueAcquireD3D11ObjectsKHR_fn |
|
98 |
+ clEnqueueAcquireD3D11ObjectsKHR; |
|
99 |
+ clEnqueueReleaseD3D11ObjectsKHR_fn |
|
100 |
+ clEnqueueReleaseD3D11ObjectsKHR; |
|
101 |
+#endif |
|
92 | 102 |
} OpenCLDeviceContext; |
93 | 103 |
|
94 | 104 |
typedef struct OpenCLFramesContext { |
... | ... |
@@ -98,7 +113,7 @@ typedef struct OpenCLFramesContext { |
98 | 98 |
// device. |
99 | 99 |
cl_command_queue command_queue; |
100 | 100 |
|
101 |
-#if HAVE_OPENCL_DXVA2 |
|
101 |
+#if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11 |
|
102 | 102 |
// For mapping APIs which have separate creation and acquire/release |
103 | 103 |
// steps, this stores the OpenCL memory objects corresponding to each |
104 | 104 |
// frame. |
... | ... |
@@ -778,6 +793,39 @@ static int opencl_device_init(AVHWDeviceContext *hwdev) |
778 | 778 |
} |
779 | 779 |
#endif |
780 | 780 |
|
781 |
+#if HAVE_OPENCL_D3D11 |
|
782 |
+ { |
|
783 |
+ const char *d3d11_ext = "cl_khr_d3d11_sharing"; |
|
784 |
+ const char *nv12_ext = "cl_intel_d3d11_nv12_media_sharing"; |
|
785 |
+ int fail = 0; |
|
786 |
+ |
|
787 |
+ if (!opencl_check_extension(hwdev, d3d11_ext)) { |
|
788 |
+ av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is " |
|
789 |
+ "required for D3D11 to OpenCL mapping.\n", d3d11_ext); |
|
790 |
+ fail = 1; |
|
791 |
+ } else if (!opencl_check_extension(hwdev, nv12_ext)) { |
|
792 |
+ av_log(hwdev, AV_LOG_VERBOSE, "The %s extension may be " |
|
793 |
+ "required for D3D11 to OpenCL mapping.\n", nv12_ext); |
|
794 |
+ // Not fatal. |
|
795 |
+ } |
|
796 |
+ |
|
797 |
+ CL_FUNC(clCreateFromD3D11Texture2DKHR, |
|
798 |
+ "D3D11 to OpenCL mapping"); |
|
799 |
+ CL_FUNC(clEnqueueAcquireD3D11ObjectsKHR, |
|
800 |
+ "D3D11 in OpenCL acquire"); |
|
801 |
+ CL_FUNC(clEnqueueReleaseD3D11ObjectsKHR, |
|
802 |
+ "D3D11 in OpenCL release"); |
|
803 |
+ |
|
804 |
+ if (fail) { |
|
805 |
+ av_log(hwdev, AV_LOG_WARNING, "D3D11 to OpenCL mapping " |
|
806 |
+ "not usable.\n"); |
|
807 |
+ priv->d3d11_mapping_usable = 0; |
|
808 |
+ } else { |
|
809 |
+ priv->d3d11_mapping_usable = 1; |
|
810 |
+ } |
|
811 |
+ } |
|
812 |
+#endif |
|
813 |
+ |
|
781 | 814 |
#undef CL_FUNC |
782 | 815 |
|
783 | 816 |
return 0; |
... | ... |
@@ -957,7 +1005,80 @@ static int opencl_enumerate_dxva2_devices(AVHWDeviceContext *hwdev, |
957 | 957 |
|
958 | 958 |
return 0; |
959 | 959 |
} |
960 |
+#endif |
|
961 |
+ |
|
962 |
+#if HAVE_OPENCL_D3D11 |
|
963 |
+static int opencl_filter_d3d11_platform(AVHWDeviceContext *hwdev, |
|
964 |
+ cl_platform_id platform_id, |
|
965 |
+ const char *platform_name, |
|
966 |
+ void *context) |
|
967 |
+{ |
|
968 |
+ const char *d3d11_ext = "cl_khr_d3d11_sharing"; |
|
969 |
+ |
|
970 |
+ if (opencl_check_platform_extension(platform_id, d3d11_ext)) { |
|
971 |
+ return 0; |
|
972 |
+ } else { |
|
973 |
+ av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the " |
|
974 |
+ "%s extension.\n", platform_name, d3d11_ext); |
|
975 |
+ return 1; |
|
976 |
+ } |
|
977 |
+} |
|
978 |
+ |
|
979 |
+static int opencl_enumerate_d3d11_devices(AVHWDeviceContext *hwdev, |
|
980 |
+ cl_platform_id platform_id, |
|
981 |
+ const char *platform_name, |
|
982 |
+ cl_uint *nb_devices, |
|
983 |
+ cl_device_id **devices, |
|
984 |
+ void *context) |
|
985 |
+{ |
|
986 |
+ ID3D11Device *device = context; |
|
987 |
+ clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR; |
|
988 |
+ cl_int cle; |
|
989 |
+ |
|
990 |
+ clGetDeviceIDsFromD3D11KHR = |
|
991 |
+ clGetExtensionFunctionAddressForPlatform(platform_id, |
|
992 |
+ "clGetDeviceIDsFromD3D11KHR"); |
|
993 |
+ if (!clGetDeviceIDsFromD3D11KHR) { |
|
994 |
+ av_log(hwdev, AV_LOG_ERROR, "Failed to get address of " |
|
995 |
+ "clGetDeviceIDsFromD3D11KHR().\n"); |
|
996 |
+ return AVERROR_UNKNOWN; |
|
997 |
+ } |
|
998 |
+ |
|
999 |
+ cle = clGetDeviceIDsFromD3D11KHR(platform_id, |
|
1000 |
+ CL_D3D11_DEVICE_KHR, device, |
|
1001 |
+ CL_PREFERRED_DEVICES_FOR_D3D11_KHR, |
|
1002 |
+ 0, NULL, nb_devices); |
|
1003 |
+ if (cle == CL_DEVICE_NOT_FOUND) { |
|
1004 |
+ av_log(hwdev, AV_LOG_DEBUG, "No D3D11-supporting devices found " |
|
1005 |
+ "on platform \"%s\".\n", platform_name); |
|
1006 |
+ *nb_devices = 0; |
|
1007 |
+ return 0; |
|
1008 |
+ } else if (cle != CL_SUCCESS) { |
|
1009 |
+ av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices " |
|
1010 |
+ "on platform \"%s\": %d.\n", platform_name, cle); |
|
1011 |
+ return AVERROR_UNKNOWN; |
|
1012 |
+ } |
|
1013 |
+ |
|
1014 |
+ *devices = av_malloc_array(*nb_devices, sizeof(**devices)); |
|
1015 |
+ if (!*devices) |
|
1016 |
+ return AVERROR(ENOMEM); |
|
1017 |
+ |
|
1018 |
+ cle = clGetDeviceIDsFromD3D11KHR(platform_id, |
|
1019 |
+ CL_D3D11_DEVICE_KHR, device, |
|
1020 |
+ CL_PREFERRED_DEVICES_FOR_D3D11_KHR, |
|
1021 |
+ *nb_devices, *devices, NULL); |
|
1022 |
+ if (cle != CL_SUCCESS) { |
|
1023 |
+ av_log(hwdev, AV_LOG_ERROR, "Failed to get list of D3D11-supporting " |
|
1024 |
+ "devices on platform \"%s\": %d.\n", platform_name, cle); |
|
1025 |
+ av_freep(devices); |
|
1026 |
+ return AVERROR_UNKNOWN; |
|
1027 |
+ } |
|
1028 |
+ |
|
1029 |
+ return 0; |
|
1030 |
+} |
|
1031 |
+#endif |
|
960 | 1032 |
|
1033 |
+#if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11 |
|
961 | 1034 |
static int opencl_filter_gpu_device(AVHWDeviceContext *hwdev, |
962 | 1035 |
cl_device_id device_id, |
963 | 1036 |
const char *device_name, |
... | ... |
@@ -1103,6 +1224,32 @@ static int opencl_device_derive(AVHWDeviceContext *hwdev, |
1103 | 1103 |
break; |
1104 | 1104 |
#endif |
1105 | 1105 |
|
1106 |
+#if HAVE_OPENCL_D3D11 |
|
1107 |
+ case AV_HWDEVICE_TYPE_D3D11VA: |
|
1108 |
+ { |
|
1109 |
+ AVD3D11VADeviceContext *src_hwctx = src_ctx->hwctx; |
|
1110 |
+ cl_context_properties props[5] = { |
|
1111 |
+ CL_CONTEXT_PLATFORM, |
|
1112 |
+ 0, |
|
1113 |
+ CL_CONTEXT_D3D11_DEVICE_KHR, |
|
1114 |
+ (intptr_t)src_hwctx->device, |
|
1115 |
+ 0, |
|
1116 |
+ }; |
|
1117 |
+ OpenCLDeviceSelector selector = { |
|
1118 |
+ .platform_index = -1, |
|
1119 |
+ .device_index = -1, |
|
1120 |
+ .context = src_hwctx->device, |
|
1121 |
+ .enumerate_platforms = &opencl_enumerate_platforms, |
|
1122 |
+ .filter_platform = &opencl_filter_d3d11_platform, |
|
1123 |
+ .enumerate_devices = &opencl_enumerate_d3d11_devices, |
|
1124 |
+ .filter_device = &opencl_filter_gpu_device, |
|
1125 |
+ }; |
|
1126 |
+ |
|
1127 |
+ err = opencl_device_create_internal(hwdev, &selector, props); |
|
1128 |
+ } |
|
1129 |
+ break; |
|
1130 |
+#endif |
|
1131 |
+ |
|
1106 | 1132 |
default: |
1107 | 1133 |
err = AVERROR(ENOSYS); |
1108 | 1134 |
break; |
... | ... |
@@ -1461,7 +1608,7 @@ static void opencl_frames_uninit(AVHWFramesContext *hwfc) |
1461 | 1461 |
OpenCLFramesContext *priv = hwfc->internal->priv; |
1462 | 1462 |
cl_int cle; |
1463 | 1463 |
|
1464 |
-#if HAVE_OPENCL_DXVA2 |
|
1464 |
+#if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11 |
|
1465 | 1465 |
int i, p; |
1466 | 1466 |
for (i = 0; i < priv->nb_mapped_frames; i++) { |
1467 | 1467 |
AVOpenCLFrameDescriptor *desc = &priv->mapped_frames[i]; |
... | ... |
@@ -2258,6 +2405,159 @@ fail: |
2258 | 2258 |
|
2259 | 2259 |
#endif |
2260 | 2260 |
|
2261 |
+#if HAVE_OPENCL_D3D11 |
|
2262 |
+ |
|
2263 |
+static void opencl_unmap_from_d3d11(AVHWFramesContext *dst_fc, |
|
2264 |
+ HWMapDescriptor *hwmap) |
|
2265 |
+{ |
|
2266 |
+ AVOpenCLFrameDescriptor *desc = hwmap->priv; |
|
2267 |
+ OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; |
|
2268 |
+ OpenCLFramesContext *frames_priv = dst_fc->device_ctx->internal->priv; |
|
2269 |
+ cl_event event; |
|
2270 |
+ cl_int cle; |
|
2271 |
+ |
|
2272 |
+ cle = device_priv->clEnqueueReleaseD3D11ObjectsKHR( |
|
2273 |
+ frames_priv->command_queue, desc->nb_planes, desc->planes, |
|
2274 |
+ 0, NULL, &event); |
|
2275 |
+ if (cle != CL_SUCCESS) { |
|
2276 |
+ av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface " |
|
2277 |
+ "handle: %d.\n", cle); |
|
2278 |
+ } |
|
2279 |
+ |
|
2280 |
+ opencl_wait_events(dst_fc, &event, 1); |
|
2281 |
+} |
|
2282 |
+ |
|
2283 |
+static int opencl_map_from_d3d11(AVHWFramesContext *dst_fc, AVFrame *dst, |
|
2284 |
+ const AVFrame *src, int flags) |
|
2285 |
+{ |
|
2286 |
+ OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; |
|
2287 |
+ OpenCLFramesContext *frames_priv = dst_fc->internal->priv; |
|
2288 |
+ AVOpenCLFrameDescriptor *desc; |
|
2289 |
+ cl_event event; |
|
2290 |
+ cl_int cle; |
|
2291 |
+ int err, index, i; |
|
2292 |
+ |
|
2293 |
+ index = (intptr_t)src->data[1]; |
|
2294 |
+ if (index >= frames_priv->nb_mapped_frames) { |
|
2295 |
+ av_log(dst_fc, AV_LOG_ERROR, "Texture array index out of range for " |
|
2296 |
+ "mapping: %d >= %d.\n", index, frames_priv->nb_mapped_frames); |
|
2297 |
+ return AVERROR(EINVAL); |
|
2298 |
+ } |
|
2299 |
+ |
|
2300 |
+ av_log(dst_fc, AV_LOG_DEBUG, "Map D3D11 texture %d to OpenCL.\n", |
|
2301 |
+ index); |
|
2302 |
+ |
|
2303 |
+ desc = &frames_priv->mapped_frames[index]; |
|
2304 |
+ |
|
2305 |
+ cle = device_priv->clEnqueueAcquireD3D11ObjectsKHR( |
|
2306 |
+ frames_priv->command_queue, desc->nb_planes, desc->planes, |
|
2307 |
+ 0, NULL, &event); |
|
2308 |
+ if (cle != CL_SUCCESS) { |
|
2309 |
+ av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface " |
|
2310 |
+ "handle: %d.\n", cle); |
|
2311 |
+ return AVERROR(EIO); |
|
2312 |
+ } |
|
2313 |
+ |
|
2314 |
+ err = opencl_wait_events(dst_fc, &event, 1); |
|
2315 |
+ if (err < 0) |
|
2316 |
+ goto fail; |
|
2317 |
+ |
|
2318 |
+ for (i = 0; i < desc->nb_planes; i++) |
|
2319 |
+ dst->data[i] = (uint8_t*)desc->planes[i]; |
|
2320 |
+ |
|
2321 |
+ err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, |
|
2322 |
+ &opencl_unmap_from_d3d11, desc); |
|
2323 |
+ if (err < 0) |
|
2324 |
+ goto fail; |
|
2325 |
+ |
|
2326 |
+ dst->width = src->width; |
|
2327 |
+ dst->height = src->height; |
|
2328 |
+ |
|
2329 |
+ return 0; |
|
2330 |
+ |
|
2331 |
+fail: |
|
2332 |
+ cle = device_priv->clEnqueueReleaseD3D11ObjectsKHR( |
|
2333 |
+ frames_priv->command_queue, desc->nb_planes, desc->planes, |
|
2334 |
+ 0, NULL, &event); |
|
2335 |
+ if (cle == CL_SUCCESS) |
|
2336 |
+ opencl_wait_events(dst_fc, &event, 1); |
|
2337 |
+ return err; |
|
2338 |
+} |
|
2339 |
+ |
|
2340 |
+static int opencl_frames_derive_from_d3d11(AVHWFramesContext *dst_fc, |
|
2341 |
+ AVHWFramesContext *src_fc, int flags) |
|
2342 |
+{ |
|
2343 |
+ AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; |
|
2344 |
+ AVD3D11VAFramesContext *src_hwctx = src_fc->hwctx; |
|
2345 |
+ OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; |
|
2346 |
+ OpenCLFramesContext *frames_priv = dst_fc->internal->priv; |
|
2347 |
+ cl_mem_flags cl_flags; |
|
2348 |
+ cl_int cle; |
|
2349 |
+ int err, i, p, nb_planes; |
|
2350 |
+ |
|
2351 |
+ if (src_fc->sw_format != AV_PIX_FMT_NV12) { |
|
2352 |
+ av_log(dst_fc, AV_LOG_ERROR, "Only NV12 textures are supported " |
|
2353 |
+ "for D3D11 to OpenCL mapping.\n"); |
|
2354 |
+ return AVERROR(EINVAL); |
|
2355 |
+ } |
|
2356 |
+ nb_planes = 2; |
|
2357 |
+ |
|
2358 |
+ if (src_fc->initial_pool_size == 0) { |
|
2359 |
+ av_log(dst_fc, AV_LOG_ERROR, "Only fixed-size pools are supported " |
|
2360 |
+ "for D3D11 to OpenCL mapping.\n"); |
|
2361 |
+ return AVERROR(EINVAL); |
|
2362 |
+ } |
|
2363 |
+ |
|
2364 |
+ cl_flags = opencl_mem_flags_for_mapping(flags); |
|
2365 |
+ if (!cl_flags) |
|
2366 |
+ return AVERROR(EINVAL); |
|
2367 |
+ |
|
2368 |
+ frames_priv->nb_mapped_frames = src_fc->initial_pool_size; |
|
2369 |
+ |
|
2370 |
+ frames_priv->mapped_frames = |
|
2371 |
+ av_mallocz_array(frames_priv->nb_mapped_frames, |
|
2372 |
+ sizeof(*frames_priv->mapped_frames)); |
|
2373 |
+ if (!frames_priv->mapped_frames) |
|
2374 |
+ return AVERROR(ENOMEM); |
|
2375 |
+ |
|
2376 |
+ for (i = 0; i < frames_priv->nb_mapped_frames; i++) { |
|
2377 |
+ AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i]; |
|
2378 |
+ desc->nb_planes = nb_planes; |
|
2379 |
+ for (p = 0; p < nb_planes; p++) { |
|
2380 |
+ UINT subresource = 2 * i + p; |
|
2381 |
+ |
|
2382 |
+ desc->planes[p] = |
|
2383 |
+ device_priv->clCreateFromD3D11Texture2DKHR( |
|
2384 |
+ dst_dev->context, cl_flags, src_hwctx->texture, |
|
2385 |
+ subresource, &cle); |
|
2386 |
+ if (!desc->planes[p]) { |
|
2387 |
+ av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL " |
|
2388 |
+ "image from plane %d of D3D texture " |
|
2389 |
+ "index %d (subresource %u): %d.\n", |
|
2390 |
+ p, i, (unsigned int)subresource, cle); |
|
2391 |
+ err = AVERROR(EIO); |
|
2392 |
+ goto fail; |
|
2393 |
+ } |
|
2394 |
+ } |
|
2395 |
+ } |
|
2396 |
+ |
|
2397 |
+ return 0; |
|
2398 |
+ |
|
2399 |
+fail: |
|
2400 |
+ for (i = 0; i < frames_priv->nb_mapped_frames; i++) { |
|
2401 |
+ AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i]; |
|
2402 |
+ for (p = 0; p < desc->nb_planes; p++) { |
|
2403 |
+ if (desc->planes[p]) |
|
2404 |
+ clReleaseMemObject(desc->planes[p]); |
|
2405 |
+ } |
|
2406 |
+ } |
|
2407 |
+ av_freep(&frames_priv->mapped_frames); |
|
2408 |
+ frames_priv->nb_mapped_frames = 0; |
|
2409 |
+ return err; |
|
2410 |
+} |
|
2411 |
+ |
|
2412 |
+#endif |
|
2413 |
+ |
|
2261 | 2414 |
static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst, |
2262 | 2415 |
const AVFrame *src, int flags) |
2263 | 2416 |
{ |
... | ... |
@@ -2289,6 +2589,11 @@ static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst, |
2289 | 2289 |
if (priv->dxva2_mapping_usable) |
2290 | 2290 |
return opencl_map_from_dxva2(hwfc, dst, src, flags); |
2291 | 2291 |
#endif |
2292 |
+#if HAVE_OPENCL_D3D11 |
|
2293 |
+ case AV_PIX_FMT_D3D11: |
|
2294 |
+ if (priv->d3d11_mapping_usable) |
|
2295 |
+ return opencl_map_from_d3d11(hwfc, dst, src, flags); |
|
2296 |
+#endif |
|
2292 | 2297 |
} |
2293 | 2298 |
return AVERROR(ENOSYS); |
2294 | 2299 |
} |
... | ... |
@@ -2323,6 +2628,18 @@ static int opencl_frames_derive_to(AVHWFramesContext *dst_fc, |
2323 | 2323 |
} |
2324 | 2324 |
break; |
2325 | 2325 |
#endif |
2326 |
+#if HAVE_OPENCL_D3D11 |
|
2327 |
+ case AV_HWDEVICE_TYPE_D3D11VA: |
|
2328 |
+ if (!priv->d3d11_mapping_usable) |
|
2329 |
+ return AVERROR(ENOSYS); |
|
2330 |
+ { |
|
2331 |
+ int err; |
|
2332 |
+ err = opencl_frames_derive_from_d3d11(dst_fc, src_fc, flags); |
|
2333 |
+ if (err < 0) |
|
2334 |
+ return err; |
|
2335 |
+ } |
|
2336 |
+ break; |
|
2337 |
+#endif |
|
2326 | 2338 |
default: |
2327 | 2339 |
return AVERROR(ENOSYS); |
2328 | 2340 |
} |