[FFmpeg-devel] [INFO]AMD D3D11 to OpenCL interop extension for NV12 and P010 textures - split planes

Mark Thompson sw at jkqxz.net
Sun Nov 25 21:34:37 EET 2018


On 24/05/2018 15:26, Mironov, Mikhail wrote:
> AMD has published OpenCL extension which allows split D3D11 texture interoped as a single 2D image into two 2D images representing Y and UV planes.
> https://www.khronos.org/registry/OpenCL/extensions/amd/cl_amd_planar_yuv.txt

I had a go at implementing this now that it is actually visible in released drivers, but I can't get it to work.

Patch trying to implement it is below.  It finds the extension and the new function correctly, but I'm stuck on the creation of the whole-texture image with clCreateFromD3D11Texture2DKHR().  The error returned is CL_INVALID_D3D11_RESOURCE_KHR (-1007), but as far as I can tell none of the documented failure cases which would return that error code apply.

$ ./ffmpeg_g.exe -report -v debug -y -hwaccel d3d11va -hwaccel_device 0 -hwaccel_output_format d3d11 -i input.mp4 -an -vf "hwmap=derive_device=opencl:mode=read,unsharp_opencl,hwdownload,format=nv12" -f null -
...
[AVHWDeviceContext @ 0000000001c0de80] Using device 1002:665f (AMD Radeon (TM) R7 360 Series).
...
[h264 @ 000000000284adc0] Format d3d11 chosen by get_format().
...
[Parsed_hwmap_0 @ 0000000002a2be00] Configure hwmap d3d11 -> opencl.
[AVHWDeviceContext @ 000000000d328500] 2 OpenCL platforms found.
[AVHWDeviceContext @ 000000000d328500] 1 OpenCL devices found on platform "Intel(R) OpenCL".
[AVHWDeviceContext @ 000000000d328500] Device Intel(R) Core(TM) i3-6300 CPU @ 3.80GHz skipped (not GPU).
[AVHWDeviceContext @ 000000000d328500] 1 OpenCL devices found on platform "AMD Accelerated Parallel Processing".
[AVHWDeviceContext @ 000000000d328500] 1.0: AMD Accelerated Parallel Processing / Bonaire
[AVHWDeviceContext @ 000000000d328500] DXVA2 to OpenCL mapping function found (clCreateFromDX9MediaSurfaceKHR).
[AVHWDeviceContext @ 000000000d328500] DXVA2 in OpenCL acquire function found (clEnqueueAcquireDX9MediaSurfacesKHR).
[AVHWDeviceContext @ 000000000d328500] DXVA2 in OpenCL release function found (clEnqueueReleaseDX9MediaSurfacesKHR).
[AVHWDeviceContext @ 000000000d328500] cl_khr_d3d11_sharing found as platform extension.
[AVHWDeviceContext @ 000000000d328500] cl_amd_planar_yuv found as device extension.
[AVHWDeviceContext @ 000000000d328500] D3D11 to OpenCL mapping function found (clCreateFromD3D11Texture2DKHR).
[AVHWDeviceContext @ 000000000d328500] D3D11 in OpenCL acquire function found (clEnqueueAcquireD3D11ObjectsKHR).
[AVHWDeviceContext @ 000000000d328500] D3D11 in OpenCL release function found (clEnqueueReleaseD3D11ObjectsKHR).
[AVHWDeviceContext @ 000000000d328500] D3D11 to OpenCL mapping on AMD function found (clGetPlaneFromImageAMD).
[AVHWFramesContext @ 0000000002c13180] Failed to create CL image from D3D texture index 0: -1007.
[Parsed_hwmap_0 @ 0000000002a2be00] Failed to create derived frames context: -5.
[Parsed_hwmap_0 @ 0000000002a2be00] Failed to configure output pad on Parsed_hwmap_0


Are there any examples of using this extension that I could compare with?  Alternatively, is the source code for the CL driver available somewhere so that I can work out what that error actually means?

Thanks,

- Mark


>From 25fb98f021b1347394d56ecf4781466096616542 Mon Sep 17 00:00:00 2001
From: Mark Thompson <sw at jkqxz.net>
Date: Sun, 25 Nov 2018 16:59:24 +0000
Subject: [PATCH] hwcontext_opencl: Add support for D3D11 to OpenCL mapping on AMD

Uses cl_amd_planar_yuv.
---
 libavutil/hwcontext_opencl.c | 106 ++++++++++++++++++++++++++++-------
 1 file changed, 86 insertions(+), 20 deletions(-)

diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c
index 728877553f..c745b91775 100644
--- a/libavutil/hwcontext_opencl.c
+++ b/libavutil/hwcontext_opencl.c
@@ -64,6 +64,12 @@
 #if HAVE_OPENCL_D3D11
 #include <CL/cl_d3d11.h>
 #include "hwcontext_d3d11va.h"
+
+// From cl_amd_planar_yuv; unfortunately no header is provided.
+typedef cl_mem (*clGetPlaneFromImageAMD_fn)(cl_context context,
+                                            cl_mem     mem,
+                                            cl_uint    plane,
+                                            cl_int    *errcode_ret);
 #endif
 
 #if HAVE_OPENCL_DRM_ARM
@@ -113,12 +119,17 @@ typedef struct OpenCLDeviceContext {
 
 #if HAVE_OPENCL_D3D11
     int d3d11_mapping_usable;
+    int d3d11_map_amd;
+    int d3d11_map_intel;
+
     clCreateFromD3D11Texture2DKHR_fn
         clCreateFromD3D11Texture2DKHR;
     clEnqueueAcquireD3D11ObjectsKHR_fn
         clEnqueueAcquireD3D11ObjectsKHR;
     clEnqueueReleaseD3D11ObjectsKHR_fn
         clEnqueueReleaseD3D11ObjectsKHR;
+    clGetPlaneFromImageAMD_fn
+        clGetPlaneFromImageAMD;
 #endif
 
 #if HAVE_OPENCL_DRM_ARM
@@ -817,17 +828,25 @@ static int opencl_device_init(AVHWDeviceContext *hwdev)
 #if HAVE_OPENCL_D3D11
     {
         const char *d3d11_ext = "cl_khr_d3d11_sharing";
-        const char *nv12_ext  = "cl_intel_d3d11_nv12_media_sharing";
+        const char *amd_ext   = "cl_amd_planar_yuv";
+        const char *intel_ext = "cl_intel_d3d11_nv12_media_sharing";
         int fail = 0;
 
         if (!opencl_check_extension(hwdev, d3d11_ext)) {
             av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is "
                    "required for D3D11 to OpenCL mapping.\n", d3d11_ext);
             fail = 1;
-        } else if (!opencl_check_extension(hwdev, nv12_ext)) {
-            av_log(hwdev, AV_LOG_VERBOSE, "The %s extension may be "
-                   "required for D3D11 to OpenCL mapping.\n", nv12_ext);
-            // Not fatal.
+        } else {
+            if (opencl_check_extension(hwdev, amd_ext)) {
+                priv->d3d11_map_amd = 1;
+            } else if (opencl_check_extension(hwdev, intel_ext)) {
+                priv->d3d11_map_intel = 1;
+            } else {
+                av_log(hwdev, AV_LOG_VERBOSE, "One of the %s or %s "
+                       "extensions are required for D3D11 to OpenCL "
+                       "mapping.\n", amd_ext, intel_ext);
+                fail = 1;
+            }
         }
 
         CL_FUNC(clCreateFromD3D11Texture2DKHR,
@@ -837,6 +856,11 @@ static int opencl_device_init(AVHWDeviceContext *hwdev)
         CL_FUNC(clEnqueueReleaseD3D11ObjectsKHR,
                 "D3D11 in OpenCL release");
 
+        if (priv->d3d11_map_amd) {
+            CL_FUNC(clGetPlaneFromImageAMD,
+                    "D3D11 to OpenCL mapping on AMD");
+        }
+
         if (fail) {
             av_log(hwdev, AV_LOG_WARNING, "D3D11 to OpenCL mapping "
                    "not usable.\n");
@@ -2573,10 +2597,22 @@ static int opencl_frames_derive_from_d3d11(AVHWFramesContext *dst_fc,
     cl_int cle;
     int err, i, p, nb_planes;
 
-    if (src_fc->sw_format != AV_PIX_FMT_NV12) {
-        av_log(dst_fc, AV_LOG_ERROR, "Only NV12 textures are supported "
-               "for D3D11 to OpenCL mapping.\n");
-        return AVERROR(EINVAL);
+    // AMD supports NV12 and P010, Intel only supports NV12.
+    if (device_priv->d3d11_map_amd) {
+        if (src_fc->sw_format != AV_PIX_FMT_NV12 &&
+            src_fc->sw_format != AV_PIX_FMT_P010) {
+            av_log(dst_fc, AV_LOG_ERROR, "Only NV12 and P010 textures are "
+                   "supported with AMD for D3D11 to OpenCL mapping.\n");
+            return AVERROR(EINVAL);
+        }
+    } else if (device_priv->d3d11_map_intel) {
+        if (src_fc->sw_format != AV_PIX_FMT_NV12) {
+            av_log(dst_fc, AV_LOG_ERROR, "Only NV12 and P010 textures are "
+                   "supported with Intel for D3D11 to OpenCL mapping.\n");
+            return AVERROR(EINVAL);
+        }
+    } else {
+        av_assert0(0);
     }
     nb_planes = 2;
 
@@ -2601,21 +2637,51 @@ static int opencl_frames_derive_from_d3d11(AVHWFramesContext *dst_fc,
     for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
         AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
         desc->nb_planes = nb_planes;
-        for (p = 0; p < nb_planes; p++) {
-            UINT subresource = 2 * i + p;
 
-            desc->planes[p] =
-                device_priv->clCreateFromD3D11Texture2DKHR(
-                    dst_dev->context, cl_flags, src_hwctx->texture,
-                    subresource, &cle);
-            if (!desc->planes[p]) {
-                av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL "
-                       "image from plane %d of D3D texture "
-                       "index %d (subresource %u): %d.\n",
-                       p, i, (unsigned int)subresource, cle);
+        if (device_priv->d3d11_map_amd) {
+            cl_mem image;
+
+            image = device_priv->clCreateFromD3D11Texture2DKHR(
+                dst_dev->context, cl_flags, src_hwctx->texture, i, &cle);
+            if (!image) {
+                av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL image "
+                       "from D3D texture index %d: %d.\n", i, cle);
                 err = AVERROR(EIO);
                 goto fail;
             }
+
+            for (p = 0; p < nb_planes; p++) {
+                desc->planes[p] = device_priv->clGetPlaneFromImageAMD(
+                    dst_dev->context, image, p, &cle);
+                if (!desc->planes[p]) {
+                    av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL image "
+                           "from plane %d of image created from D3D11 "
+                           "texture index %d: %d.\n", p, cle, i);
+                    clReleaseMemObject(image);
+                    err = AVERROR(EIO);
+                    goto fail;
+                }
+            }
+
+            clReleaseMemObject(image);
+
+        } else {
+            for (p = 0; p < nb_planes; p++) {
+                UINT subresource = 2 * i + p;
+
+                desc->planes[p] =
+                    device_priv->clCreateFromD3D11Texture2DKHR(
+                        dst_dev->context, cl_flags, src_hwctx->texture,
+                        subresource, &cle);
+                if (!desc->planes[p]) {
+                    av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL "
+                           "image from plane %d of D3D texture "
+                           "index %d (subresource %u): %d.\n",
+                           p, i, (unsigned int)subresource, cle);
+                    err = AVERROR(EIO);
+                    goto fail;
+                }
+            }
         }
     }
 
-- 
2.19.1


More information about the ffmpeg-devel mailing list