This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 47d0aa27ab1029b24e64596773211f1c3e143eb2
Author:     Philip Langdale <[email protected]>
AuthorDate: Fri Jul 31 15:59:10 2026 +0800
Commit:     Philip Langdale <[email protected]>
CommitDate: Fri Aug 7 08:45:59 2026 -0700

    avfilter: add vsr_drv_cuda, the driver RTX VSR network
    
    The video super-resolution the NVIDIA driver itself runs (the DXVA/PPE 
plugin
    nvaivpx.dll, ppe/features/AIVP), as opposed to the NGX SDK snippet that
    vsr_cuda drives.  It is a newer and heavier network over the same DLPP 
kernels,
    with its own quality levels and tunables, and it is worth having both: they 
do
    not produce the same picture.
    
    The driver numbers its networks 0-4, but they are not ordered by strength 
and
    index 0 is a byte-identical duplicate of index 4.  Only 1-4 are exposed 
here:
    one network reachable under two numbers is a usability trap, not a feature. 
 By
    fidelity the order runs q1 (most faithful) > q3 > q4 > q2 (most aggressive
    detail synthesis), so the default is q1.
    
    Two things differ from vsr_cuda beyond the tables, and both are visible 
here:
    each launch is issued with the kernel's own EIATTR_CBANK_PARAM_SIZE rather 
than
    the captured driver argsize, because the driver over-reports by 8 bytes for 
the
    two DLPP tex/surf kernels and cuLaunchKernel then fails with
    CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES; and the graph has only two bindless 
slots in
    total -- the input texture at dlpp_preProcess and the output surface at
    dlpp_postProcess or ResampleAndComposeFP16 -- with no internal surfaces.
    
    The graph super-resolves 2x internally: an exact isotropic 2x output stores
    directly, anything else composes to the requested rectangle.
---
 configure                     |   1 +
 doc/filters.texi              |  77 ++++++++++
 libavfilter/Makefile          |   1 +
 libavfilter/allfilters.c      |   1 +
 libavfilter/vf_vsr_drv_cuda.c | 350 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 430 insertions(+)

diff --git a/configure b/configure
index f8b1e2ba2b..32ed6f6836 100755
--- a/configure
+++ b/configure
@@ -4324,6 +4324,7 @@ scale_vulkan_filter_deps="vulkan spirv_compiler swscale"
 vpp_qsv_filter_deps="libmfx"
 vpp_qsv_filter_select="qsvvpp"
 vsr_cuda_filter_deps="ffnvcodec nvfdata_vsr"
+vsr_drv_cuda_filter_deps="ffnvcodec nvfdata_vsr_drv"
 xfade_opencl_filter_deps="opencl"
 xfade_vulkan_filter_deps="vulkan spirv_compiler"
 yadif_cuda_filter_deps="ffnvcodec"
diff --git a/doc/filters.texi b/doc/filters.texi
index ee0fdf2236..d7870e6827 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -28014,6 +28014,83 @@ ingest @strong{YCbCr only}.  The Vulkan encoders 
reject every RGB pixel format
 likewise takes @code{nv12}/@code{p010}, so @code{vsr_cuda}'s RGB output cannot 
be
 fed to an encoder directly.
 
+@anchor{vsr_drv_cuda}
+@section vsr_drv_cuda
+
+Upscale video with the NVIDIA driver's RTX Video Super Resolution network,
+running it directly on CUDA.
+
+This is the driver's AIVP plugin, not the NGX SDK network that @ref{vsr_cuda}
+drives -- a newer and heavier network over the same underlying kernels.  The
+two do not produce the same picture, and neither is uniformly better, so it is
+worth comparing them on your own content.  @code{dlpp_drv_cuda} is a third
+option again.
+
+The graph super-resolves 2x internally.  An exact isotropic 2x output stores
+directly; any other size resamples that result to the requested rectangle with
+a bicubic compose.
+
+It accepts the following options:
+
+@table @option
+@item quality
+Which of the driver's four networks to run, @code{1} to @code{4}.  Default
+@code{1}.
+
+They are @strong{not} ordered by strength.  By fidelity, from the most faithful
+to the most aggressive at synthesizing detail, the order is @code{1}, @code{3},
+@code{4}, @code{2}.  The default @code{1} is the least grainy and the closest
+to a faithful upscale; @code{2} invents the most.
+
+@item detail
+@item smooth
+Perceptual pre-processing of the input, each @code{0} to @code{16} and
+defaulting to @code{0}, which is neutral and byte-exact against the driver.
+@option{detail} raises high-frequency content and @option{smooth} lowers it --
+an unsharp/denoise pair applied before the network.  They tune the look, not
+the fidelity.
+
+@item w
+@item h
+Output width and height, as expressions (as in @ref{scale}); the variables
+@var{iw}/@var{in_w} and @var{ih}/@var{in_h} hold the input size.  Defaults
+@code{iw*2} and @code{ih*2}.
+
+@item format
+Output pixel format.  Empty (the default) keeps the input format.
+
+@item data
+Directory holding the extracted cubins and the shared @file{weights.bin}.
+
+@item experimental_arch
+Allow GPU architectures whose cubins were matched statically rather than
+exercised.  Ada (sm_89) and Blackwell do not need this.  Turing and older
+cannot run this network at all -- its convolution kernels need sm_80 tensor
+cores -- and are refused unconditionally.
+@end table
+
+@subsection Supported formats
+
+Packed RGB formats are accepted for both input and output: @code{rgb0},
+@code{rgba}, @code{bgr0}, @code{bgra} (8-bit) and @code{rgba64le} (16-bit).
+Input and output formats are chosen independently (see the @option{format}
+option).  16-bit carries the network's full internal precision and avoids
+banding.
+
+The kernels branch on a format selector that exposes an R@math{<->}B swap only
+on the 8-bit path, so the B-first @code{bgr0}/@code{bgra} are handled natively.
+That swap does not exist on the high-bit-depth path, which packs in 
array-native
+order, so 16-bit is R-first only (@code{rgba64le}).
+
+This filter does @strong{not} do YUV@math{<->}RGB conversion or tone mapping;
+see @ref{vsr_cuda} for the @code{libplacebo} pipeline that feeds these filters
+from real video and for the hardware decode/encode combinations.
+
+The cubins and weights are extracted from the proprietary NVIDIA libraries and
+are @emph{not} shipped: the filter is only built when an
+@code{nvidia-video-filters} package carrying the driver VSR data is installed, 
and
+@option{data} defaults to that package's data directory.
+
 @section yadif_cuda
 
 Deinterlace the input video using the @ref{yadif} algorithm, but implemented
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 9f955565b2..ffba98faca 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -577,6 +577,7 @@ OBJS-$(CONFIG_FRC_AMF_FILTER)                += 
vf_frc_amf.o vf_amf_common.o
 OBJS-$(CONFIG_VQE_AMF_FILTER)                += vf_vqe_amf.o vf_amf_common.o
 OBJS-$(CONFIG_VPP_QSV_FILTER)                += vf_vpp_qsv.o
 OBJS-$(CONFIG_VSR_CUDA_FILTER)               += vf_vsr_cuda.o rtx_cuda.o
+OBJS-$(CONFIG_VSR_DRV_CUDA_FILTER)           += vf_vsr_drv_cuda.o rtx_cuda.o
 OBJS-$(CONFIG_VSTACK_FILTER)                 += vf_stack.o framesync.o
 OBJS-$(CONFIG_W3FDIF_FILTER)                 += vf_w3fdif.o
 OBJS-$(CONFIG_WAVEFORM_FILTER)               += vf_waveform.o
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index 35629fe1c3..7e4bc775f5 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -541,6 +541,7 @@ extern const FFFilter ff_vf_vignette;
 extern const FFFilter ff_vf_vmafmotion;
 extern const FFFilter ff_vf_vpp_qsv;
 extern const FFFilter ff_vf_vsr_cuda;
+extern const FFFilter ff_vf_vsr_drv_cuda;
 extern const FFFilter ff_vf_vstack;
 extern const FFFilter ff_vf_w3fdif;
 extern const FFFilter ff_vf_waveform;
diff --git a/libavfilter/vf_vsr_drv_cuda.c b/libavfilter/vf_vsr_drv_cuda.c
new file mode 100644
index 0000000000..62fb7f7b49
--- /dev/null
+++ b/libavfilter/vf_vsr_drv_cuda.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2026 Philip Langdale <[email protected]>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Super-resolution filter driving the NVIDIA *driver* RTX Video Super 
Resolution
+ * network (the DXVA/PPE plugin nvaivpx.dll, ppe/features/AIVP) -- distinct 
from
+ * vf_vsr_cuda, which runs the NGX SDK snippet (nvngx_vsr.dll).  The driver 
graph
+ * is a newer/heavier network; its cubins were extracted and the forward pass
+ * reverse-engineered by running the plugin on Linux via loader_ppe and
+ * intercepting the live CUDA Driver-API launches.  vsr_drv_cuda_gen.h encodes,
+ * per quality and scaling path, how the whole graph (grids, scratch 
allocations,
+ * packed arg-buffer scalars incl. division-magic constants and float32 
resample
+ * steps, weight-upload targets, pointer fixups) scales with the input W,H and
+ * output oW,oH -- derived and validated byte-exact against the loader
+ * (rtx-video-re).
+ * The filter evaluates that at config time and replays the graph with 
libcuda; no
+ * DLL is needed at run time.  The replay machinery itself is rtx_cuda.c.
+ *
+ * The graph performs a fixed internal 2x super-resolution.  Exact isotropic 2x
+ * output takes the "fast" path (direct dlpp_postProcess store); any other 
factor
+ * takes the "resample" path (dlpp_ResampleAndComposeFP16 to the requested 
rect).
+ *
+ * Differences from vf_vsr_cuda:
+ *   - Each launch is issued with the kernel's EIATTR_CBANK_PARAM_SIZE (psize) 
as
+ *     CU_LAUNCH_PARAM_BUFFER_SIZE, NOT the captured driver argsize (the driver
+ *     over-reports by 8 bytes for the two DLPP tex/surf kernels, which makes
+ *     cuLaunchKernel return CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES).
+ *   - Only two bindless slots in the whole graph (input tex @ dlpp_preProcess,
+ *     output surf @ dlpp_postProcess/ResampleAndComposeFP16); no internal 
surfaces.
+ *
+ * The cubins and the shared weights blob are external files (the "data" 
option),
+ * extracted from the proprietary driver and not shipped with FFmpeg.
+ */
+
+#include "libavutil/hwcontext.h"
+#include "libavutil/mem.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+
+#include "avfilter.h"
+#include "filters.h"
+#include "rtx_cuda.h"
+#include "rtx_dlpp_abi.h"
+#include "video.h"
+
+/* Generated by rtx-video-re from the proprietary NVIDIA library, and
+ * installed rather than carried here -- located, together with the cubins and
+ * weights it names, through pkg-config (see configure's nvfdata_* checks). */
+#include <vsr_drv_cuda_gen.h>
+
+FF_RTX_ASSERT_MODULE_LAYOUT(VsrDrvModule);
+FF_RTX_ASSERT_FUNC_LAYOUT(VsrDrvFunc);
+FF_RTX_ASSERT_UPLOAD_LAYOUT(VsrDrvGenUpload);
+FF_RTX_ASSERT_LAUNCH_LAYOUT(VsrDrvGenLaunch);
+
+/* preProcess arg-buffer offsets of the two input pre-processing floats (params
+ * +0x3c/+0x40, direct copies; located by sentinel probe -- both inside its 
64-byte
+ * param cbank).  preProcess is the first launch in every config. */
+#define VSRDRV_PRE_DETAIL_OFF 0x38
+#define VSRDRV_PRE_SMOOTH_OFF 0x3c
+/* The format selectors -- the 3-way enum documented on ff_rtx_packed_rgb_fmts,
+ * sentinel-probed at the driver's params +0x30/+0x34 (see rtx-video-re
+ * docs/FINDINGS-vsr-drv-params.md) -- sit on the DLPP glue kernels this filter
+ * shares with vf_dlpp_drv_cuda, so their offsets live in rtx_dlpp_abi.h. */
+
+typedef struct VsrDrvCudaContext {
+    const AVClass *class;
+
+    FFRtxCuda   r;
+    FFRtxImage *in_img, *out_img;
+
+    int W, H, oW, oH;                 ///< input / output size
+    int cfg;                          ///< index into vsrdrv_configs
+
+    const FFRtxPixFmt *inpf, *outpf;
+
+    int   quality;
+    float detail;                     ///< preProcess detail gain (params 
+0x3c -> arg@0x38)
+    float smooth;                     ///< preProcess smoothing   (params 
+0x40 -> arg@0x3c)
+    char *w_expr;
+    char *h_expr;
+    char *data_dir;
+    char *out_format;                 ///< output pixel format (empty = same 
as input)
+    int   experimental_arch;          ///< allow the unverified sub-Blackwell 
(sm_75/sm_80) path
+} VsrDrvCudaContext;
+
+#define OFFSET(x) offsetof(VsrDrvCudaContext, x)
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM)
+
+static const AVOption vsr_drv_cuda_options[] = {
+    /* Driver quality selects the internal network; they are NOT ordered by 
index.
+     * By fidelity/gentleness: q1 (most faithful) > q3 > q4 > q2 (most 
aggressive
+     * detail synthesis).  Default q1 -- the least grainy, closest to a 
faithful
+     * upscale.
+     *
+     * The driver's own index 0 selects the same network as 4, 
byte-identically.
+     * It is not exposed: one model under two numbers only invites someone to 
A/B
+     * them and find no difference. */
+    { "quality", "driver VSR quality level (1=gentlest .. 2=strongest)", 
OFFSET(quality), AV_OPT_TYPE_INT, {.i64=1}, 1, 4, FLAGS },
+    /* Perceptual input pre-processing (driver params +0x3c/+0x40, fed to
+     * dlpp_preProcess). 0 = neutral (byte-exact with the DLL); >0 only.  
detail
+     * raises high-frequency, smooth lowers it -- an unsharp/denoise pair.  
These
+     * tune look, NOT fidelity (see rtx-video-re 
docs/FINDINGS-vsr-drv-params.md). */
+    { "detail", "input detail gain (0=neutral, higher=sharper)", 
OFFSET(detail), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 16, FLAGS },
+    { "smooth", "input smoothing (0=neutral, higher=softer)",    
OFFSET(smooth), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 16, FLAGS },
+    { "w", "output width expression (default: 2x input)",  OFFSET(w_expr), 
AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+    { "h", "output height expression (default: 2x input)", OFFSET(h_expr), 
AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+    { "data", "directory with extracted driver VSR cubins + the shared 
weights.bin",
+      OFFSET(data_dir), AV_OPT_TYPE_STRING, {.str=VSRDRV_DEFAULT_DATA_DIR}, 0, 
0, FLAGS },
+    { "format", "output pixel format (empty = same as input); e.g. bgra, 
rgba64le",
+      OFFSET(out_format), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+    /* The cubins ship as multi-arch fatbins (sm_75/sm_80/sm_120); 
cuModuleLoadData
+     * picks the image for the running GPU.  Blackwell (sm_120) is validated 
byte-
+     * exact; Ada (sm_89) is verified on an RTX 4060 Ti -- the sm_80 slice 
loaded
+     * there is byte-identical to the driver DLL's own sm_80 cubin for all 53
+     * kernels.  Other sub-Blackwell arches run that same sm_80 image but were 
never
+     * exercised on real silicon, hence the opt-in.  (Turing/older can't run 
VSR at
+     * all -- its conv kernels are sm_80+; refused unconditionally.) */
+    { "experimental_arch", "allow the unverified sub-Blackwell path (sm_89/Ada 
does not need this)",
+      OFFSET(experimental_arch), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(vsr_drv_cuda);
+
+FF_RTX_ASSERT_PRIV_LAYOUT(VsrDrvCudaContext);
+
+static const FFRtxArchGate vsrdrv_gate = {
+    /* The all_fuse_with_pooling conv kernels use the sm_80+ tensor-core MMA
+     * (m16n8k16 / HMMA.16816), which Turing/Volta/Pascal tensor cores cannot
+     * execute -- so the driver ships no cc<8 image for them and 
cuModuleLoadData
+     * would fail (CUDA_ERROR_NO_BINARY_FOR_GPU).  NVIDIA's real Turing VSR 
path
+     * uses a different (HMMA.1688) kernel set and launch graph, which we 
captured
+     * only on Blackwell -- so it cannot be driven here.  experimental_arch 
cannot
+     * help, so this refusal is unconditional. */
+    .hard_min_major = 8,
+    .hard_msg =
+        "vsr_drv_cuda cannot run on this GPU (cc %d.%d): VSR's conv kernels "
+        "require sm_80+ (Ampere) tensor cores (the m16n8k16 MMA), so the 
driver "
+        "ships no image for Turing/Volta/Pascal.  NVIDIA's Turing VSR uses a "
+        "different kernel set and graph that is not captured here -- needs "
+        "Ampere or newer.\n",
+    .gate_msg =
+        "vsr_drv_cuda is validated on Blackwell (cc 12.x) and Ada (cc 8.9); 
this "
+        "GPU is cc %d.%d.  Other Ampere/Ada support is unverified (they run 
the "
+        "sm_80 image) -- set experimental_arch=1 to attempt it.\n",
+    .warn_msg =
+        "vsr_drv_cuda: EXPERIMENTAL sub-Blackwell (cc %d.%d) path -- it runs 
the "
+        "sm_80 image, unverified on real hardware.\n",
+};
+
+/* ------------------------------------------------------------------------- *
+ * One-time graph setup for the selected config + W,H,oW,oH (context current).
+ * ------------------------------------------------------------------------- */
+static void fill_sizes(AVFilterContext *ctx, long long *sz)
+{
+    VsrDrvCudaContext *s = ctx->priv;
+    vsrdrv_fill_allocs(s->cfg, s->W, s->H, s->oW, s->oH, sz);
+}
+
+static int setup_graph(AVFilterContext *ctx)
+{
+    VsrDrvCudaContext *s = ctx->priv;
+    const VsrDrvConfig *c = &vsrdrv_configs[s->cfg];
+    VsrDrvGenUpload *up;
+    int ret, nup, pre;
+
+    if ((ret = ff_rtx_arch_gate(ctx, &s->r, &vsrdrv_gate, 
s->experimental_arch)) < 0)
+        return ret;
+    if ((ret = ff_rtx_load_modules(ctx, &s->r, s->data_dir,
+                                   (const FFRtxModule *)c->modules, c->nmod, 
VSRDRV_MAX_MID,
+                                   (const FFRtxFunc *)c->funcs, c->nfunc, 
VSRDRV_MAX_FID,
+                                   NULL)) < 0)
+        return ret;
+    if ((ret = ff_rtx_alloc_arena(ctx, &s->r, c->nalloc, fill_sizes, 0)) < 0)
+        return ret;
+
+    up = av_calloc(c->nupload, sizeof(*up));
+    if (!up)
+        return AVERROR(ENOMEM);
+    nup = vsrdrv_fill_uploads(s->cfg, s->W, s->H, s->oW, s->oH,
+                              (const vsrdrv_devptr *)s->r.alloc, up);
+    ret = ff_rtx_upload_weights(ctx, &s->r, s->data_dir, "weights.bin",
+                                (const FFRtxUpload *)up, nup);
+    av_freep(&up);
+    if (ret < 0)
+        return ret;
+
+    /* input array + texture (linear/normalized/clamp; the frame is copied in
+     * each frame), and the output array + surface (the SUST.P target). */
+    s->in_img = ff_rtx_image_array(ctx, &s->r, s->W, s->H, s->inpf->cufmt,
+                                   FF_RTX_TEX | FF_RTX_CLAMP);
+    s->out_img = ff_rtx_image_array(ctx, &s->r, s->oW, s->oH, s->outpf->cufmt,
+                                    FF_RTX_SURF | FF_RTX_LDST);
+    if (!s->in_img || !s->out_img)
+        return AVERROR_EXTERNAL;
+
+    /* Build the graph.  vsrdrv_fill_graph() is generated from the same fit as 
the
+     * tables above and assigns every field through its named vsrdrv_*_params
+     * struct, so the argument blocks are constructed rather than patched.
+     * CUdeviceptr and vsrdrv_devptr are both 64-bit device addresses; the 
casts
+     * are only to satisfy `unsigned long long *` vs `uint64_t *` on LP64. */
+    if ((ret = ff_rtx_alloc_launches(ctx, &s->r, c->nlaunch, 
sizeof(VsrDrvGenLaunch))) < 0)
+        return ret;
+    if (vsrdrv_fill_graph(s->cfg, s->W, s->H, s->oW, s->oH,
+                          (const vsrdrv_devptr *)s->r.alloc,
+                          (vsrdrv_devptr)s->in_img->tex, 
(vsrdrv_devptr)s->out_img->surf,
+                          s->r.launches) != c->nlaunch) {
+        av_log(ctx, AV_LOG_ERROR, "generated fill disagrees with the config 
tables\n");
+        return AVERROR_BUG;
+    }
+
+    /* Format selectors, on the shared DLPP glue kernels.  preProcess is also
+     * where this filter's own tunables sit, so keep its launch index. */
+    if ((ret = ff_dlpp_patch_selectors(ctx, &s->r, (const FFRtxFunc *)c->funcs,
+                                       c->nfunc, s->inpf, s->outpf, c->tag, 
&pre)) < 0)
+        return ret;
+
+    /* Perceptual tunables: overwrite the two preProcess input pre-processing 
floats
+     * (params +0x3c/+0x40 -> its arg @0x38/@0x3c) when set non-zero.  0 
leaves the
+     * byte-exact-with-the-DLL default. */
+    if (s->detail != 0 || s->smooth != 0) {
+        uint8_t *a;
+        if (pre < 0) {
+            av_log(ctx, AV_LOG_ERROR,
+                   "no input pre-process kernel for config %s; detail/smooth "
+                   "cannot be applied\n", c->tag);
+            return AVERROR_BUG;
+        }
+        a = ff_rtx_launch_at(&s->r, pre)->params;
+        if (s->detail != 0) memcpy(a + VSRDRV_PRE_DETAIL_OFF, &s->detail, 4);
+        if (s->smooth != 0) memcpy(a + VSRDRV_PRE_SMOOTH_OFF, &s->smooth, 4);
+        av_log(ctx, AV_LOG_VERBOSE, "preProcess tunables: detail=%g smooth=%g 
(launch %d)\n",
+               s->detail, s->smooth, pre);
+    }
+
+    /* No sub-Blackwell param-size fix-up.  This filter used to append 8 zero 
bytes
+     * to the three tex/surf glue kernels' param buffers on cc < 12, on the 
theory
+     * that their sm_80 build declares a larger cbank than the sm_120 one.  
That is
+     * wrong, and vf_dlpp_drv_cuda.c -- the same kernels, driven from the other
+     * plugin -- dropped the identical splice for the same reason: every 
kernel's
+     * EIATTR_CBANK_PARAM_SIZE is the same across sm_80 and sm_120, so growing 
the
+     * buffer makes cuLaunchKernel disagree with the cbank and fail
+     * CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES on Ada.  The generator settles it 
either
+     * way: psize comes from the loaded cubin's own EIATTR, and for every 
vsr_drv
+     * config it equals the argsize the driver itself launched with. */
+
+    av_log(ctx, AV_LOG_INFO,
+           "driver VSR graph ready: quality %d [%s]  %dx%d -> %dx%d  "
+           "(%d launches, %d buffers)\n",
+           s->quality, c->tag, s->W, s->H, s->oW, s->oH,
+           s->r.nlaunch, s->r.nalloc);
+    return 0;
+}
+
+/* ------------------------------------------------------------------------- *
+ * Per-frame: bind the input frame as a texture, replay the graph, copy out.
+ * ------------------------------------------------------------------------- */
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    VsrDrvCudaContext *s = inlink->dst->priv;
+    /* psize is the kernel's own cbank size, NOT the captured argsize */
+    const FFRtxFrameOp op = {
+        .in_img = s->in_img,  .iW = s->W,  .iH = s->H,  .ibpp = s->inpf->bpp,
+        .out_img = s->out_img, .oW = s->oW, .oH = s->oH, .obpp = s->outpf->bpp,
+        .flags = FF_RTX_OP_PSIZE |
+                 (s->outpf->sel == 2 ? FF_RTX_OP_OPAQUE_ALPHA : 0),
+    };
+
+    return ff_rtx_filter_frame(inlink, in, &s->r, &op, NULL);
+}
+
+static int config_output(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    AVFilterLink *inlink = ctx->inputs[0];
+    VsrDrvCudaContext *s = ctx->priv;
+    AVHWFramesContext *in_frames_ctx;
+    FFRtxFormats fmts = {
+        .in_tbl  = ff_rtx_packed_rgb_fmts, .n_in  = 
FF_ARRAY_ELEMS(ff_rtx_packed_rgb_fmts),
+        .out_tbl = ff_rtx_packed_rgb_fmts, .n_out = 
FF_ARRAY_ELEMS(ff_rtx_packed_rgb_fmts),
+    };
+    int fast, ret;
+
+    ff_rtx_free_graph(ctx, &s->r);
+
+    fmts.out_format = s->out_format;
+    if ((ret = ff_rtx_config_formats(ctx, inlink, &fmts, &in_frames_ctx,
+                                     &s->inpf, &s->outpf)) < 0)
+        return ret;
+
+    s->W = inlink->w;
+    s->H = inlink->h;
+    if ((ret = ff_rtx_eval_dims(ctx, inlink, s->w_expr, s->h_expr, 2,
+                                &s->oW, &s->oH)) < 0)
+        return ret;
+
+    fast = (s->oW == 2 * s->W && s->oH == 2 * s->H);
+    s->cfg = vsrdrv_config_index(s->quality, fast ? 0 : 1);
+    if (s->cfg < 0) {
+        av_log(ctx, AV_LOG_ERROR, "no config for quality %d %s path\n",
+               s->quality, fast ? "fast" : "resample");
+        return AVERROR(ENOSYS);
+    }
+
+    if ((ret = ff_rtx_bind_device(ctx, &s->r, in_frames_ctx)) < 0)
+        return ret;
+    if ((ret = ff_rtx_config_hwframes(ctx, outlink, &s->r, s->oW, s->oH,
+                                      s->outpf->f)) < 0)
+        return ret;
+    return ff_rtx_setup(ctx, &s->r, "driver VSR", setup_graph);
+}
+
+static const AVFilterPad vsr_drv_cuda_inputs[] = {
+    { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .filter_frame = 
filter_frame },
+};
+
+static const AVFilterPad vsr_drv_cuda_outputs[] = {
+    { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .config_props = 
config_output },
+};
+
+const FFFilter ff_vf_vsr_drv_cuda = {
+    .p.name        = "vsr_drv_cuda",
+    .p.description = NULL_IF_CONFIG_SMALL("NVIDIA driver RTX Video Super 
Resolution (CUDA)"),
+    .p.priv_class  = &vsr_drv_cuda_class,
+    .priv_size     = sizeof(VsrDrvCudaContext),
+    .uninit        = ff_rtx_uninit,
+    FILTER_INPUTS(vsr_drv_cuda_inputs),
+    FILTER_OUTPUTS(vsr_drv_cuda_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_CUDA),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to