PR #24834 opened by dhalsimax
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24834
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24834.patch

# Summary of changes

Adds a fast option, off by default, that builds the kernel with 
-cl-fast-relaxed-math. On an Intel HD Graphics 500 a 4K HDR10 film tone mapped 
to 1080p goes from 0.86x to 2.67x real time, and the output differs by PSNR 
54.5 dB / SSIM 0.9977.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


From 87f00151b44f8b6c80a2b70ea42de2fa031fc85a Mon Sep 17 00:00:00 2001
From: dhalsimax <[email protected]>
Date: Thu, 1 Oct 2026 08:38:55 +0200
Subject: [PATCH] avfilter/vf_tonemap_opencl: add an option to use relaxed math

The tonemap kernel spends most of its time in powr() and the other
transcendental functions of the PQ/HLG and BT.709 transfer curves, four
pixels per work item. Built with -cl-fast-relaxed-math it can use the
native versions. On an Intel HD Graphics 500 (Gen9, Apollo Lake J3455,
compute-runtime 24.35), tone mapping a minute of a 3840x1604 HDR10 film
to 1920x802, with VAAPI decode and h264_vaapi encode, runs at 0.86x real
time with fast=0 and at 2.67x with fast=1. The two encodes compared
give PSNR 54.5 dB, SSIM 0.9977.

Add a fast option, off by default, for devices where speed matters more
than the last bit of precision. It reaches clBuildProgram() through a
new build_opts field in OpenCLFilterContext, NULL for every other
filter.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LnW49Xq639xegtVtMcLNR4
---
 doc/filters.texi                | 6 ++++++
 libavfilter/opencl.c            | 2 +-
 libavfilter/opencl.h            | 4 ++++
 libavfilter/vf_tonemap_opencl.c | 7 +++++++
 4 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index e8c8b23481..d86fcd09f7 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -28855,6 +28855,12 @@ the current frame average brightness and the current 
running average exceeds
 a threshold value, we would re-calculate scene average and peak brightness.
 The default value is 0.2.
 
+@item fast
+Build the OpenCL kernel with relaxed math (@code{-cl-fast-relaxed-math}), so
+that the compiler can use faster and less precise versions of the functions of
+the transfer curves. On slow devices this can be much faster, at the cost of a
+small loss of precision. Disabled by default.
+
 @item format
 Specify the output pixel format.
 
diff --git a/libavfilter/opencl.c b/libavfilter/opencl.c
index e91610a10e..ab851911e7 100644
--- a/libavfilter/opencl.c
+++ b/libavfilter/opencl.c
@@ -172,7 +172,7 @@ int ff_opencl_filter_load_program(AVFilterContext *avctx,
     }
 
     cle = clBuildProgram(ctx->program, 1, &ctx->hwctx->device_id,
-                         NULL, NULL, NULL);
+                         ctx->build_opts, NULL, NULL);
     if (cle != CL_SUCCESS) {
         av_log(avctx, AV_LOG_ERROR, "Failed to build program: %d.\n", cle);
 
diff --git a/libavfilter/opencl.h b/libavfilter/opencl.h
index dec376766e..3d02d65e57 100644
--- a/libavfilter/opencl.h
+++ b/libavfilter/opencl.h
@@ -45,6 +45,10 @@ typedef struct OpenCLFilterContext {
     enum AVPixelFormat output_format;
     int                output_width;
     int                output_height;
+
+    // Options passed to clBuildProgram() by ff_opencl_filter_load_program(),
+    // NULL for none.
+    const char        *build_opts;
 } OpenCLFilterContext;
 
 // Groups together information about a kernel argument
diff --git a/libavfilter/vf_tonemap_opencl.c b/libavfilter/vf_tonemap_opencl.c
index 2f47cfd49f..42d55aa867 100644
--- a/libavfilter/vf_tonemap_opencl.c
+++ b/libavfilter/vf_tonemap_opencl.c
@@ -65,6 +65,7 @@ typedef struct TonemapOpenCLContext {
     double                desat_param;
     double                target_peak;
     double                scene_threshold;
+    int                   fast;
     int                   initialised;
     cl_kernel             kernel;
     cl_command_queue      command_queue;
@@ -243,6 +244,11 @@ static int tonemap_opencl_init(AVFilterContext *avctx)
     opencl_sources[0] = header.str;
     opencl_sources[1] = ff_source_tonemap_cl;
     opencl_sources[2] = ff_source_colorspace_common_cl;
+    // The kernel is dominated by powr() and the other transcendental
+    // functions of the transfer curves, and relaxed math lets the compiler
+    // use the native ones.
+    if (ctx->fast)
+        ctx->ocf.build_opts = "-cl-fast-relaxed-math";
     err = ff_opencl_filter_load_program(avctx, opencl_sources, 
OPENCL_SOURCE_NB);
 
     av_bprint_finalize(&header, NULL);
@@ -515,6 +521,7 @@ static const AVOption tonemap_opencl_options[] = {
     { "param",     "tonemap parameter",   OFFSET(param), AV_OPT_TYPE_DOUBLE, 
{.dbl = NAN}, DBL_MIN, DBL_MAX, FLAGS },
     { "desat",     "desaturation parameter",   OFFSET(desat_param), 
AV_OPT_TYPE_DOUBLE, {.dbl = 0.5}, 0, DBL_MAX, FLAGS },
     { "threshold", "scene detection threshold",   OFFSET(scene_threshold), 
AV_OPT_TYPE_DOUBLE, {.dbl = 0.2}, 0, DBL_MAX, FLAGS },
+    { "fast",      "build the kernel with relaxed math", OFFSET(fast), 
AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
     { NULL }
 };
 
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to